SpringBoot Lambda 部署问题 - EmbeddedServletContainer - java.lang.NoClassDefFoundError

SpringBoot Lambda deployment Issue - EmbeddedServletContainer - java.lang.NoClassDefFoundError

我正在尝试使用 RequestStreamHandler 在 AWS Lambda/API-Gateway 中部署一个简单的 spring 启动应用程序,但我不断收到以下错误。

查看互联网后发现,由于 spring-boot 包问题,所以包含了 shade 插件,但仍然没有成功。

{
  "errorMessage": "Error loading class com.aws.lambda.testlambda.StreamLambdaHandler: org/springframework/boot/context/embedded/EmbeddedServletContainer",
  "errorType": "java.lang.NoClassDefFoundError"
} 

pom.xml

<properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>com.amazonaws.serverless</groupId>
            <artifactId>aws-serverless-java-container-spring</artifactId>
            <version>1.5</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <transformers>
                                <transformer
                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                    <resource>META-INF/spring.handlers</resource>
                                </transformer>
                                <transformer
                                        implementation="org.springframework.boot.maven.PropertiesMergingResourceTransformer">
                                    <resource>META-INF/spring.factories</resource>
                                </transformer>
                                <transformer
                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                    <resource>META-INF/spring.schemas</resource>
                                </transformer>
                                <transformer
                                        implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
                                <transformer
                                        implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <mainClass>com.aws.lambda.testlambda.TestlambdaApplication</mainClass>
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
public class StreamLambdaHandler implements RequestStreamHandler {
    private static SpringBootLambdaContainerHandler<AwsProxyRequest, AwsProxyResponse> handler;

    static {
        try {
            handler = SpringBootLambdaContainerHandler.getAwsProxyHandler(TestlambdaApplication.class);
            // we use the onStartup method of the handler to register our custom filter
            handler.onStartup(servletContext -> {
                FilterRegistration.Dynamic registration = servletContext.addFilter("CognitoIdentityFilter", CognitoIdentityFilter.class);
                registration.addMappingForUrlPatterns( EnumSet.of( DispatcherType.REQUEST), true, "/*");
            });
        } catch (ContainerInitializationException e) {
            // if we fail here. We re-throw the exception to force another cold start
            e.printStackTrace();
            throw new RuntimeException("Could not initialize Spring Boot application", e);
        }
    }

    public StreamLambdaHandler() {
        // we enable the timer for debugging. This SHOULD NOT be enabled in production.
        Timer.enable();
    }

    @Override
    public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context)
            throws IOException {
        handler.proxyStream(inputStream, outputStream, context);

        // just in case it wasn't closed by the mapper
        outputStream.close();
    }
}

非常感谢任何帮助。提前致谢。

AVAI!

这个问题我有一个猜测。 您可以检查在您的 Lambda 函数中定义的 Java 的版本吗?

我看到您正在使用 Java 8 您的应用程序。 您的 lambda 运行时应匹配此版本。

如果您在 lambda 上使用本地 Oracle JVM 和 AWS Coretto JVM,您可能还会遇到一些问题。

我能够解决这个问题,有几个问题需要解决并使其端到端工作。

下面提到了这个问题 url。

https://github.com/awslabs/aws-serverless-java-container

  1. 打包需要排除tomcat依赖。
  2. RequestStreamHandler 只需稍作修改即可处理请求和响应。
     AwsProxyResponse resp = handler.proxy(req, context);
     LambdaContainerHandler.getObjectMapper().writeValue(outputStream, resp);
  1. 部署到 API 网关时必须选择代理集成选项。