我最近开始玩AWS Lambda with Java。
一直顺利,直到我开始使用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构建。
我检查过的其他问题表明,这可能是由于依赖项不可用,但是,该类的内容没有依赖关系。
/*
* 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",
]
)
这是WORKSPACE文件:
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
,它将正常运行。
答案 0 :(得分: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(
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
"""
)