2

我最近开始在 Java 中使用 AWS Lambda。

一直进展顺利,直到我开始使用 Dagger 2 进行注射。

现在 Lambda 抛出以下错误:

{
  "errorMessage": "dagger/internal/Preconditions",
  "errorType": "java.lang.NoClassDefFoundError",
  "stackTrace": [
    "com.company.server.user.SignUpActionAws.handler(SignUpActionAws.java:27)",
    "sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)",
    "sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)",
    "sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)",
    "java.lang.reflect.Method.invoke(Method.java:498)"
  ],
  "cause": {
    "errorMessage": "dagger.internal.Preconditions",
    "errorType": "java.lang.ClassNotFoundException",
    "stackTrace": [
      "java.net.URLClassLoader.findClass(URLClassLoader.java:381)",
      "java.lang.ClassLoader.loadClass(ClassLoader.java:424)",
      "java.lang.ClassLoader.loadClass(ClassLoader.java:357)",
      "com.company.server.user.SignUpActionAws.handler(SignUpActionAws.java:27)",
      "sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)",
      "sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)",
      "sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)",
      "java.lang.reflect.Method.invoke(Method.java:498)"
    ]
  }
}

java -jar myjar.jar但是,在本地运行时不会发生这种情况。我还使用jar tvf myjar.jar.

我使用 Bazel 构建。

我检查过的其他问题表明这可能是由于依赖项不可用,但是,该类的内容没有依赖项。

取自Dagger 回购

/*
 * Copyright (C) 2016 Google, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package dagger.internal;

/**
 * An adaptation of Guava's {@code com.google.common.base.Preconditions} that is specially tailored
 * to support checks applied in Dagger's generated code.
 */
public final class Preconditions {
  /**
   * Ensures that an object reference passed as a parameter to the calling method is not null.
   *
   * @param reference an object reference
   * @return the non-null reference that was validated
   * @throws NullPointerException if {@code reference} is null
   */
  public static <T> T checkNotNull(T reference) {
    if (reference == null) {
      throw new NullPointerException();
    }
    return reference;
  }

  /**
   * Ensures that an object reference passed as a parameter to the calling method is not null.
   *
   * @param reference an object reference
   * @param errorMessage the exception message to use if the check fails
   * @return the non-null reference that was validated
   * @throws NullPointerException if {@code reference} is null
   */
  public static <T> T checkNotNull(T reference, String errorMessage) {
    if (reference == null) {
      throw new NullPointerException(errorMessage);
    }
    return reference;
  }

  private Preconditions() {}
}

运行独立 jar 时,可能导致 AWS 上出现的问题在我的本地环境中没有出现?

提前致谢

编辑 1:这是最小的 BUILD 文件:

java_binary(
  name = "bin",
  srcs = glob(["Action.java"]),
  main_class = "com.company.Action",
  deps = [
    "//external:aws-lambda",
    "//external:dagger",
  ]
)

这是工作空间文件:

bind(name = "aws-lambda", actual = "@com_amazonaws_aws_lambda_java_core//jar")
maven_jar(
  name = "com_amazonaws_aws_lambda_java_core",
  artifact = "com.amazonaws:aws-lambda-java-core:1.1.0"
)
bind(name = "dagger", actual = "@com_google_dagger//jar")
maven_jar(
  name = "com_google_dagger",
  artifact = "com.google.dagger:dagger:2.5",
)

这是 Action.java (注意,我直接使用 Preconditions 使其成为最小实现,在我的实际代码中,它在尝试构建组件时失败):

package com.company;

import com.amazonaws.services.lambda.runtime.Context;

public class Action {
  public static void main(String[] s) {
    Action.handler(null, null);
  }

  public static String handler(String request, Context context) {
    dagger.internal.Preconditions.checkNotNull(new Object(), "Test");
    return null;
  }
}

如果您运行bazel build //src/main/com/company:bin_deploy.jar并将其上传到 AWS Lambda 函数,它应该会失败。如果您在本地运行bazel run //src/main/com/company:bin,否则java -jar bazel-bin/src/main/com/company/bin_deploy.jar它将正常工作。

4

1 回答 1

0

这完全是由于我的 jar 内的 dagger 文件夹中的权限。所有其他文件夹(例如 com、org、mozilla)都有 755,但没有 dagger 文件夹。我解压缩了我的 jar,运行了两个命令将目录转换为 755,将文件转换为 644,然后我将其压缩回来。

更改权限的命令:

From inside the unzipped directory:
find . -type f -exec chmod 644 {} +
find . -type d -exec chmod 755 {} +

我不知道为什么在 Bazel 构建它时它与其他目录不同。但这就是问题所在。


对于未来的 Bazel 搜索者,这是我现在使用的 genrule:

genrule(
  name = "target-aws",
  srcs = ["target_deploy.jar"],
  outs = ["target-aws.jar"],
  cmd = """
  unzip -q $< -d t
  cd t
  find . -type f -exec chmod 644 {} +
  find . -type d -exec chmod 755 {} +
  zip ../$@ -q -r .
  rm -rf t
  """
)
于 2016-07-04T08:59:58.317 回答