serverless-java-container icon indicating copy to clipboard operation
serverless-java-container copied to clipboard

No public method named handleRequest with appropriate method signature on SpringBootLambdaContainerHandler

Open jeusdi opened this issue 1 year ago • 12 comments

To help us debug your issue fill in the basic information below using the options provided

Serverless Java Container version: 2.0

Implementations: Spring Boot

Framework version: SpringBoot

Frontend service: HTTP API

Deployment method: Serverless Framework

Scenario

I'm trying to execute my lambda.

Expected behavior

Reach my exposed endpoints

Actual behavior

I'm getting:

No public method named handleRequest with appropriate method signature found on class com.amazonaws.serverless.proxy.spring.SpringBootLambdaContainerHandler

Steps to reproduce

Here my pom.xml related tree dependencies:

\- com.amazonaws.serverless:aws-serverless-java-container-springboot3:jar:2.0.0:compile
[INFO]    +- org.springframework.cloud:spring-cloud-function-serverless-web:jar:4.0.6:compile
[INFO]    \- com.amazonaws.serverless:aws-serverless-java-container-core:jar:2.0.0:compile
[INFO]       +- com.amazonaws:aws-lambda-java-core:jar:1.2.3:compile
[INFO]       +- jakarta.servlet:jakarta.servlet-api:jar:6.0.0:compile
[INFO]       +- jakarta.ws.rs:jakarta.ws.rs-api:jar:3.1.0:compile
[INFO]       +- com.fasterxml.jackson.module:jackson-module-afterburner:jar:2.15.3:compile
[INFO]       \- org.apache.commons:commons-fileupload2-jakarta-servlet6:jar:2.0.0-M2:compile
[INFO]          +- org.apache.commons:commons-fileupload2-core:jar:2.0.0-M2:compile
[INFO]          \- commons-io:commons-io:jar:2.15.1:compil

Full log output

Here my lambda output (`aws logs filter-log-events --log-group-name "/aws/lambda/espaidoc-dev-api")

{
  "events": [
    {
      "logStreamName": "2024/02/21/[$LATEST]a70d67063ade2e352772539d2f3a6f74",
      "timestamp": 1708553587372,
      "message": "START RequestId: f61e24d9-9990-43cf-8b29-789a63584e4e Version: $LATEST",
      "ingestionTime": 1708553588494,
      "eventId": "0"
    },
    {
      "logStreamName": "2024/02/21/[$LATEST]a70d67063ade2e352772539d2f3a6f74",
      "timestamp": 1708553587425,
      "message": "No public method named handleRequest with appropriate method signature found on class com.amazonaws.serverless.proxy.spring.SpringBootLambdaContainerHandler",
      "ingestionTime": 1708553588494,
      "eventId": "1"
    },
    {
      "logStreamName": "2024/02/21/[$LATEST]a70d67063ade2e352772539d2f3a6f74",
      "timestamp": 1708553587478,
      "message": "END RequestId: f61e24d9-9990-43cf-8b29-789a63584e4e",
      "ingestionTime": 1708553588494,
      "eventId": "2"
    },
    {
      "logStreamName": "2024/02/21/[$LATEST]a70d67063ade2e352772539d2f3a6f74",
      "timestamp": 1708553587532,
      "message": "REPORT RequestId: f61e24d9-9990-43cf-8b29-789a63584e4e\tDuration: 84.01 ms\tBilled Duration: 85 ms\tMemory Size: 1024 MB\tMax Memory Used: 1024 MB\t",
      "ingestionTime": 1708553588494,
      "eventId": "3"
    }
  ],
  "searchedLogStreams": [
    {
      "logStreamName": "2024/02/21/[$LATEST]a70d67063ade2e352772539d2f3a6f74",
      "searchedCompletely": true
    }
  ]
}

I also put my entire pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <parent>
      <groupId>me.jeusdi.slab.localstack</groupId>
      <artifactId>espaidoc</artifactId>
      <version>0.0.1-SNAPSHOT</version>
   </parent>
   <groupId>me.jeusdi.slab.localstack</groupId>
   <artifactId>frontoffice</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <name>frontoffice</name>
   <description>PoC to see how to send and receive messages from AWS SQS</description>
   <properties>
      <java.version>17</java.version>
      <spring-boot-dependencies.version>3.2.2</spring-boot-dependencies.version>
      <spring-cloud-aws.version>3.1.0</spring-cloud-aws.version>
   </properties>
   <dependencyManagement>
      <dependencies>
         <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>${spring-boot-dependencies.version}</version>
            <type>pom</type>
            <scope>import</scope>
         </dependency>
         <dependency>
            <groupId>io.awspring.cloud</groupId>
            <artifactId>spring-cloud-aws-dependencies</artifactId>
            <version>${spring-cloud-aws.version}</version>
            <type>pom</type>
            <scope>import</scope>
         </dependency>
      </dependencies>
   </dependencyManagement>
   <dependencies>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
      </dependency>
      <dependency>
         <groupId>io.awspring.cloud</groupId>
         <artifactId>spring-cloud-aws-starter-s3</artifactId>
      </dependency>
      <dependency>
         <groupId>io.awspring.cloud</groupId>
         <artifactId>spring-cloud-aws-starter-sqs</artifactId>
      </dependency>
      <dependency>
         <groupId>me.jeusdi.slab.localstack</groupId>
         <artifactId>domain</artifactId>
         <version>0.0.1-SNAPSHOT</version>
      </dependency>
      <dependency>
         <groupId>me.jeusdi.slab.localstack</groupId>
         <artifactId>application</artifactId>
         <version>0.0.1-SNAPSHOT</version>
      </dependency>
      <dependency>
         <groupId>me.jeusdi.slab.localstack</groupId>
         <artifactId>infrastructure</artifactId>
         <version>0.0.1-SNAPSHOT</version>
      </dependency>
      <dependency>
         <groupId>org.projectlombok</groupId>
         <artifactId>lombok</artifactId>
         <optional>true</optional>
      </dependency>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
      </dependency>
   </dependencies>
   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
               <excludes>
                  <exclude>
                     <groupId>org.projectlombok</groupId>
                     <artifactId>lombok</artifactId>
                  </exclude>
               </excludes>
            </configuration>
         </plugin>
      </plugins>
   </build>
   <profiles>
      <profile>
         <id>lambda</id>
         <activation>
            <activeByDefault>true</activeByDefault>
         </activation>
         <dependencies>
            <dependency>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-starter-web</artifactId>
               <exclusions>
                  <exclusion>
                     <groupId>org.springframework.boot</groupId>
                     <artifactId>spring-boot-starter-tomcat</artifactId>
                  </exclusion>
               </exclusions>
            </dependency>
            <dependency>
               <groupId>com.amazonaws.serverless</groupId>
               <artifactId>aws-serverless-java-container-springboot3</artifactId>
               <version>2.0.0</version>
            </dependency>
         </dependencies>
         <build>
            <plugins>
               <plugin>
                  <groupId>org.apache.maven.plugins</groupId>
                  <artifactId>maven-shade-plugin</artifactId>
                  <version>3.5.1</version>
                  <configuration>
                     <createDependencyReducedPom>false</createDependencyReducedPom>
                  </configuration>
                  <executions>
                     <execution>
                        <phase>package</phase>
                        <goals>
                           <goal>shade</goal>
                        </goals>
                        <configuration>
                           <artifactSet>
                              <excludes>
                                 <exclude>org.apache.tomcat.embed:*</exclude>
                              </excludes>
                           </artifactSet>
                        </configuration>
                     </execution>
                  </executions>
               </plugin>
            </plugins>
         </build>
      </profile>
   </profiles>
</project>

Also, my serverless.yml:

service: espaidoc

provider:
  name: aws
  runtime: java17
  stage: dev
  region: us-east-1
  versionFunctions: false

package:
  artifact: ./target/frontoffice-0.0.1-SNAPSHOT.jar

plugins:
  - serverless-localstack

custom:
  localstack:
    stages:
      - dev
    host: localstack.localhost
    edgePort: 8000
    endpointFile: .localstack/endpoints.json

functions:
  api:
    handler: com.amazonaws.serverless.proxy.spring.SpringBootLambdaContainerHandler::handleRequest
    environment:
      MAIN_CLASS: FluxApplication
    events:
      - http:
          method: POST
          path: /documents

Any ideas?

jeusdi avatar Feb 21 '24 22:02 jeusdi

Hi, take a look at https://aws.amazon.com/blogs/compute/re-platforming-java-applications-using-the-updated-aws-serverless-java-container/.

You can configure and use the SpringDelegatingLambdaContainerHandler implementation or implement your own handler Java class that delegates to AWS Serverless Java Container.

In your case the easiest fix is replacing handler: com.amazonaws.serverless.proxy.spring.SpringBootLambdaContainerHandler::handleRequest with handler: com.amazonaws.serverless.proxy.spring.SpringDelegatingLambdaContainerHandler in your serverless.yml.

deki avatar Feb 22 '24 05:02 deki

I think I'm almost there.

I'm getting this message now:

2024-02-22T14:41:01.451 WARN --- [ asgi_gw_0] l.s.apigateway.integration : Lambda output should follow the next JSON format: { "isBase64Encoded": true|false, "statusCode": httpStatusCode, "headers": { "headerName": "headerValue", ... },"body": "..."} Lambda output: {'errorMessage': 'Could not find class [FluxApplication]', 'errorType': 'java.lang.IllegalArgumentException'}

I've took a look on uploaded jar:

$ jar tf target/frontoffice-0.0.1-SNAPSHOT.jar | grep FluxApplication
me/jeusdi/slab/localstack/flux/presentation/frontoffice/FluxApplication.class

As you can see, FluxApplication in on jar file.

FluxApplication class is:

package me.jeusdi.slab.localstack.flux.presentation.frontoffice;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FilterType;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;

import me.jeusdi.slab.localstack.flux.application.document.pull.PullDocumentInputPort;
import me.jeusdi.slab.localstack.flux.application.document.push.PushDocumentInputPort;
import me.jeusdi.slab.localstack.flux.application.document.push.PushDocumentPersistenceGatewayOutputPort;
import me.jeusdi.slab.localstack.flux.application.document.pushed.PushedDocumentPersistenceGatewayOutputPort;
import me.jeusdi.slab.localstack.flux.domain.model.document.PullDocumentService;
import me.jeusdi.slab.localstack.flux.domain.model.document.PushDocumentService;
import me.jeusdi.slab.localstack.flux.domain.model.document.ResourceProvider;
import me.jeusdi.slab.localstack.flux.infrastructure.repository.ResourceMongoRespository;

@SpringBootApplication
@ComponentScan
@ComponentScan(basePackages = "me.jeusdi.slab.localstack.flux.domain.model.document", includeFilters = {
		@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = PullDocumentService.class),
		@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = PushDocumentService.class),
})
@ComponentScan(basePackages = "me.jeusdi.slab.localstack.flux.application", includeFilters = {
		@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = PushDocumentInputPort.class),
		@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = PullDocumentInputPort.class)
})
@ComponentScan(basePackages = "me.jeusdi.slab.localstack.flux.infrastructure", includeFilters = {
		@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = ResourceProvider.class),
		@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = PushDocumentPersistenceGatewayOutputPort.class),
		@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = PushedDocumentPersistenceGatewayOutputPort.class),
		@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = ResourceMongoRespository.class)
})
@EnableMongoRepositories(basePackages = "me.jeusdi.slab.localstack.flux.infrastructure")
public class FluxApplication {

	public static void main(String[] args) {
		SpringApplication.run(FluxApplication.class, args);
	}

}

In order to set with "main" to pick up for DelegateContainer, I've set MAIN_CLASS environment variable to "FluxApplication" into serverless.yml:

service: espaidoc

provider:
  name: aws
  runtime: java17
  stage: dev
  region: us-east-1
  versionFunctions: false

package:
  artifact: ./target/frontoffice-0.0.1-SNAPSHOT.jar

plugins:
  - serverless-localstack

custom:
  localstack:
    stages:
      - dev
    host: localstack.localhost
    edgePort: 8000
    endpointFile: .localstack/endpoints.json

functions:
  api:
    handler: com.amazonaws.serverless.proxy.spring.SpringDelegatingLambdaContainerHandler
    environment:
      MAIN_CLASS: FluxApplication
    events:
      - http:
          method: POST
          path: /documents

Any ideas?

jeusdi avatar Feb 22 '24 14:02 jeusdi

Yeah it has to be a fully qualified class name including the package. So in your case: MAIN_CLASS: me.jeusdi.slab.localstack.flux.presentation.frontoffice.FluxApplication

deki avatar Feb 22 '24 15:02 deki

Thanks @deki . I was solved it using fully qualified class name.

Another issue here:

I'm getting:

2024-02-22T15:09:13.612 WARN --- [ asgi_gw_3] l.s.apigateway.integration : Lambda output should follow the next JSON format: { "isBase64Encoded": true|false, "statusCode": httpStatusCode, "headers": { "headerName": "headerValue", ... },"body": "..."} Lambda output: {'errorMessage': 'java.lang.NullPointerException: Cannot invoke "org.springframework.web.servlet.DispatcherServlet.getServletContext()" because "servlet" is null', 'errorType': 'java.lang.IllegalStateException', 'stackTrace': ['com.amazonaws.serverless.proxy.spring.AwsSpringHttpProcessingUtils.processRequest(AwsSpringHttpProcessingUtils.java:61)', 'com.amazonaws.serverless.proxy.spring.SpringDelegatingLambdaContainerHandler.handleRequest(SpringDelegatingLambdaContainerHandler.java:64)'], 'cause': {'errorMessage': 'Cannot invoke "org.springframework.web.servlet.DispatcherServlet.getServletContext()" because "servlet" is null', 'errorType': 'java.lang.NullPointerException', 'stackTrace': ['org.springframework.cloud.function.serverless.web.ServerlessMVC$ProxyFilterChain.(ServerlessMVC.java:224)', 'org.springframework.cloud.function.serverless.web.ServerlessMVC.service(ServerlessMVC.java:167)', 'org.springframework.cloud.function.serverless.web.ServerlessMVC.service(ServerlessMVC.java:163)', 'com.amazonaws.serverless.proxy.spring.AwsSpringHttpProcessingUtils.processRequest(AwsSpringHttpProcessingUtils.java:51)', 'com.amazonaws.serverless.proxy.spring.SpringDelegatingLambdaContainerHandler.handleRequest(SpringDelegatingLambdaContainerHandler.java:64)']}}

Any suggestion here?

EDIT

I've also tested trying to invoke my function using serverless framework getting the same but more detailed logs. Here the output:

$ sls invoke local --function "api"
(node:10982) NOTE: We are formalizing our plans to enter AWS SDK for JavaScript (v2) into maintenance mode in
2023.

Please migrate your code to use AWS SDK for JavaScript (v3).
For more information, check the migration guide at https://a.co/7PzMCcy
(Use `sls --trace-warnings ...` to show where the warning was created)
Using serverless-localstack
serverless-localstack: Reconfigured endpoints
Warning: In order to get human-readable output, please implement "toString()" method of your "ApiGatewayRespon
se" object.
Standard Commons Logging discovery in action with spring-jcl: please remove commons-logging.jar from classpath
 in order to avoid potential conflicts

19:36:43.582 [main] INFO org.springframework.cloud.function.serverless.web.FunctionClassUtils -- Main class: c
lass me.jeusdi.slab.localstack.flux.presentation.frontoffice.FluxApplication

19:36:43.641 [Thread-0] INFO org.springframework.cloud.function.serverless.web.ServerlessMVC -- Starting application with the following configuration classes:

19:36:43.644 [Thread-0] INFO org.springframework.cloud.function.serverless.web.ServerlessMVC -- FluxApplication


  .   ____          _            __ _ _

 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/

 :: Spring Boot ::                (v3.2.2)



2024-02-22T19:36:45.258+01:00  INFO 11078 --- [       Thread-0] o.s.boot.SpringApplication               : Starting application using Java 21.0.1 with PID 11078 (started by jcabre in /home/jcabre/projects/gene/cultura/espa

2024-02-22T19:36:45.261+01:00  INFO 11078 --- [       Thread-0] o.s.boot.SpringApplication               : No active profile set, falling back to 1 default profile: "default"

2024-02-22T19:36:45.740+01:00 DEBUG 11078 --- [       Thread-0] o.s.c.a.ClassPathBeanDefinitionScanner   : Identified candidate component class: URL [jar:file:/home/jcabre/projects/gene/cultura/espaidoc/workarea/repositori

2024-02-22T19:36:45.805+01:00 DEBUG 11078 --- [       Thread-0] o.s.c.a.ClassPathBeanDefinitionScanner   : Identified candidate component class: URL [jar:file:/home/jcabre/projects/gene/cultura/espaidoc/workarea/repositori

2024-02-22T19:36:45.819+01:00 DEBUG 11078 --- [       Thread-0] o.s.c.a.ClassPathBeanDefinitionScanner   : Identified candidate component class: URL [jar:file:/home/jcabre/projects/gene/cultura/espaidoc/workarea/repositori

2024-02-22T19:36:45.846+01:00 DEBUG 11078 --- [       Thread-0] o.s.c.a.ClassPathBeanDefinitionScanner   : Identified candidate component class: URL [jar:file:/home/jcabre/projects/gene/cultura/espaidoc/workarea/repositori

2024-02-22T19:36:45.847+01:00 DEBUG 11078 --- [       Thread-0] o.s.c.a.ClassPathBeanDefinitionScanner   : Ignored because not a concrete top-level class: URL [jar:file:/home/jcabre/projects/gene/cultura/espaidoc/workarea/
2024-02-22T19:36:45.848+01:00 DEBUG 11078 --- [       Thread-0] o.s.c.a.ClassPathBeanDefinitionScanner   : Identified candidate component class: URL [jar:file:/home/jcabre/projects/gene/cultura/espaidoc/workarea/repositori
2024-02-22T19:36:45.848+01:00 DEBUG 11078 --- [       Thread-0] o.s.c.a.ClassPathBeanDefinitionScanner   : Ignored because not a concrete top-level class: URL [jar:file:/home/jcabre/projects/gene/cultura/espaidoc/workarea/

2024-02-22T19:36:45.895+01:00 DEBUG 11078 --- [       Thread-0] o.s.c.a.ClassPathBeanDefinitionScanner   : Ignored because not a concrete top-level class: URL [jar:file:/home/jcabre/projects/gene/cultura/espaidoc/workarea/

2024-02-22T19:36:45.900+01:00 DEBUG 11078 --- [       Thread-0] o.s.c.a.ClassPathBeanDefinitionScanner   : Identified candidate component class: URL [jar:file:/home/jcabre/projects/gene/cultura/espaidoc/workarea/repositori

2024-02-22T19:36:45.907+01:00 DEBUG 11078 --- [       Thread-0] o.s.c.a.ClassPathBeanDefinitionScanner   : Identified candidate component class: URL [jar:file:/home/jcabre/projects/gene/cultura/espaidoc/workarea/repositori

2024-02-22T19:36:47.289+01:00  INFO 11078 --- [       Thread-0] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data MongoDB repositories in DEFAULT mode.

2024-02-22T19:36:47.472+01:00  INFO 11078 --- [       Thread-0] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 170 ms. Found 1 MongoDB repository interface.

2024-02-22T19:36:48.888+01:00  WARN 11078 --- [       Thread-0] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.context.Appli

2024-02-22T19:36:48.975+01:00 ERROR 11078 --- [       Thread-0] o.s.b.d.LoggingFailureAnalysisReporter   :

***************************
APPLICATION FAILED TO START
***************************

Description:

Web application could not be started as there was no org.springframework.boot.web.servlet.server.ServletWebServerFactory bean defined in the context.

Action:

Check your application's dependencies for a supported servlet web server.
Check the configured web application type.


2024-02-22T19:36:48.979+01:00  INFO 11078 --- [       Thread-0] o.s.c.f.serverless.web.ServerlessMVC     : Application is started successfully.

Exception in thread "Thread-0" java.lang.IllegalStateException: org.springframework.context.ApplicationContextException: Unable to start web server
        at org.springframework.cloud.function.serverless.web.ServerlessMVC.lambda$initializeContextAsync$1(ServerlessMVC.java:116)
        at java.base/java.lang.Thread.run(Thread.java:1583)
Caused by: org.springframework.context.ApplicationContextException: Unable to start web server
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:165)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:618)
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146)

        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754)

        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:334)

        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1354)
        at org.springframework.cloud.function.serverless.web.ServerlessMVC.initContext(ServerlessMVC.java:126)
        at org.springframework.cloud.function.serverless.web.ServerlessMVC.lambda$initializeContextAsync$1(ServerlessMVC.java:113)
        ... 1 more
Caused by: org.springframework.boot.web.context.MissingWebServerFactoryBeanException: No qualifying bean of type 'org.springframework.boot.web.servlet.server.ServletWebServerFactory' available: Unable to start AnnotationCo
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.getWebServerFactory(ServletWebServerApplicationContext.java:216)
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.createWebServer(ServletWebServerApplicationContext.java:186)
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:162)
        ... 9 more

java.lang.NullPointerException: Cannot invoke "org.springframework.web.servlet.DispatcherServlet.getServletContext()" because "servlet" is null
        at org.springframework.cloud.function.serverless.web.ServerlessMVC$ProxyFilterChain.<init>(ServerlessMVC.java:224)
        at org.springframework.cloud.function.serverless.web.ServerlessMVC.service(ServerlessMVC.java:167)
        at org.springframework.cloud.function.serverless.web.ServerlessMVC.service(ServerlessMVC.java:163)
        at com.amazonaws.serverless.proxy.spring.AwsSpringHttpProcessingUtils.processRequest(AwsSpringHttpProcessingUtils.java:51)
        at com.amazonaws.serverless.proxy.spring.SpringDelegatingLambdaContainerHandler.handleRequest(SpringDelegatingLambdaContainerHandler.java:64)
        at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
        at java.base/java.lang.reflect.Method.invoke(Method.java:580)
        at com.serverless.InvokeBridge.invoke(InvokeBridge.java:86)
        at com.serverless.InvokeBridge.<init>(InvokeBridge.java:38)
        at com.serverless.InvokeBridge.main(InvokeBridge.java:137)

java.lang.reflect.InvocationTargetException
        at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:118)
        at java.base/java.lang.reflect.Method.invoke(Method.java:580)
        at com.serverless.InvokeBridge.invoke(InvokeBridge.java:86)
        at com.serverless.InvokeBridge.<init>(InvokeBridge.java:38)
        at com.serverless.InvokeBridge.main(InvokeBridge.java:137)
Caused by: java.lang.IllegalStateException: java.lang.NullPointerException: Cannot invoke "org.springframework.web.servlet.DispatcherServlet.getServletContext()" because "servlet" is null
        at com.amazonaws.serverless.proxy.spring.AwsSpringHttpProcessingUtils.processRequest(AwsSpringHttpProcessingUtils.java:61)
        at com.amazonaws.serverless.proxy.spring.SpringDelegatingLambdaContainerHandler.handleRequest(SpringDelegatingLambdaContainerHandler.java:64)
        at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
        ... 4 more
Caused by: java.lang.NullPointerException: Cannot invoke "org.springframework.web.servlet.DispatcherServlet.getServletContext()" because "servlet" is null
        at org.springframework.cloud.function.serverless.web.ServerlessMVC$ProxyFilterChain.<init>(ServerlessMVC.java:224)
        at org.springframework.cloud.function.serverless.web.ServerlessMVC.service(ServerlessMVC.java:167)

        at org.springframework.cloud.function.serverless.web.ServerlessMVC.service(ServerlessMVC.java:163)
        at com.amazonaws.serverless.proxy.spring.AwsSpringHttpProcessingUtils.processRequest(AwsSpringHttpProcessingUtils.java:51)
        ... 6 more

jeusdi avatar Feb 22 '24 15:02 jeusdi

@olegz can you look into this one?

deki avatar Feb 22 '24 15:02 deki

I'm running into the exact same problem that @jeusdi is running into, i.e. Caused by: java.lang.NullPointerException: Cannot invoke "org.springframework.web.servlet.DispatcherServlet.getServletContext()" because "servlet" is null I've tried both versions 2.0.0 and 2.0.1 of aws-serverless-java-container-springboot3, and get that same error stack. Any updates please?

fabiencoppens avatar Apr 10 '24 21:04 fabiencoppens

see also #819 it seems to be webflux related. we'll take a look...

deki avatar Apr 12 '24 06:04 deki

I have not tested it with webflux, so at this point it is safe to say it is not supported. Not saying it can not be supported, but DispatcherServlet model is not really for webflux

olegz avatar Apr 15 '24 07:04 olegz

Also, based on your stack trace it appears you can't start the application at all. That is strange since it appears spring-cloud-function-serverless-web auto-configuration is not picked up as if it is not on the classpath. Can you please re-post the POM that you currently have? Better of provide a sample app that reproduces the issue

olegz avatar Apr 15 '24 07:04 olegz

@olegz @deki I actually created a separate ticket last week for my issue, and it has my full stack trace: https://github.com/aws/serverless-java-container/issues/828 We have webflux in our dependencies, but we don't really leverage it, as all our APIs are traditional blocking I/O. I'll try to exclude webflux and see if that fixes the issue. Is there also a workaround if we wanted to keep webflux?

fabiencoppens avatar Apr 15 '24 16:04 fabiencoppens

@fabiencoppens I was on PTO and getting back to it now. Give me few days and I'll see what is going on

olegz avatar Apr 24 '24 07:04 olegz

@fabiencoppens @deki I just used your POM from the above comments and everything works as expected, so what am I missing? FWIW, here is my template.yaml

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Example Pet Store API written with spring-cloud-function web-proxy support

Globals:
  Api:
    # API Gateway regional endpoints
    EndpointConfiguration: REGIONAL

Resources:
  PetStoreMVC:
    Type: AWS::Serverless::Function
    Properties:
#      AutoPublishAlias: bcn
      FunctionName: pet-store-boot-3
      Handler: com.amazonaws.serverless.proxy.spring.SpringDelegatingLambdaContainerHandler::handleRequest
      Runtime: java17
      SnapStart:
        ApplyOn: PublishedVersions
      CodeUri: .
      MemorySize: 1024
      Policies: AWSLambdaBasicExecutionRole
      Timeout: 30
      Environment:
        Variables:
          MAIN_CLASS: io.spring.sample.springboot3.Application
      Events:
        HttpApiEvent:
          Type: HttpApi
          Properties:
            TimeoutInMillis: 20000
            PayloadFormatVersion: '1.0'

Outputs:
  PetStoreMVCApi:
    Description: URL for application
    Value: !Sub 'https://${ServerlessHttpApi}.execute-api.${AWS::Region}.amazonaws.com/pets'
    Export:
      Name: PetStoreMVCApi

And here is the full POM.xml which is pretty much a copy of what you have up above in the comments. In fact I am not seeing eny webflux there, so it puzzles me even more when you say you are using it

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>io.spring.sample</groupId>
    <artifactId>mvc-aws</artifactId>
    <version>2.0-SNAPSHOT</version>
    <name>Spring Boot example for the aws-serverless-java-container library</name>
    <description>Simple pet store written with the Spring framework and Spring Boot</description>
    <url>https://aws.amazon.com/lambda/</url>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.2</version>
    </parent>

    <licenses>
        <license>
            <name>The Apache Software License, Version 2.0</name>
            <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
            <distribution>repo</distribution>
        </license>
    </licenses>

    <properties>
      <java.version>17</java.version>
      <spring-boot-dependencies.version>3.2.2</spring-boot-dependencies.version>
      <spring-cloud-aws.version>3.1.0</spring-cloud-aws.version>
   </properties>
   <dependencyManagement>
      <dependencies>
         <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>${spring-boot-dependencies.version}</version>
            <type>pom</type>
            <scope>import</scope>
         </dependency>
         <dependency>
            <groupId>io.awspring.cloud</groupId>
            <artifactId>spring-cloud-aws-dependencies</artifactId>
            <version>${spring-cloud-aws.version}</version>
            <type>pom</type>
            <scope>import</scope>
         </dependency>
      </dependencies>
   </dependencyManagement>
   <dependencies>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
      </dependency>
      <dependency>
         <groupId>io.awspring.cloud</groupId>
         <artifactId>spring-cloud-aws-starter-s3</artifactId>
      </dependency>
      <dependency>
         <groupId>io.awspring.cloud</groupId>
         <artifactId>spring-cloud-aws-starter-sqs</artifactId>
      </dependency>
      <dependency>
         <groupId>org.projectlombok</groupId>
         <artifactId>lombok</artifactId>
         <optional>true</optional>
      </dependency>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
      </dependency>
   </dependencies>
   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
               <excludes>
                  <exclude>
                     <groupId>org.projectlombok</groupId>
                     <artifactId>lombok</artifactId>
                  </exclude>
               </excludes>
            </configuration>
         </plugin>
      </plugins>
   </build>
   <profiles>
      <profile>
         <id>lambda</id>
         <activation>
            <activeByDefault>true</activeByDefault>
         </activation>
         <dependencies>
            <dependency>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-starter-web</artifactId>
               <exclusions>
                  <exclusion>
                     <groupId>org.springframework.boot</groupId>
                     <artifactId>spring-boot-starter-tomcat</artifactId>
                  </exclusion>
               </exclusions>
            </dependency>
            <dependency>
               <groupId>com.amazonaws.serverless</groupId>
               <artifactId>aws-serverless-java-container-springboot3</artifactId>
               <version>2.0.0</version>
            </dependency>
         </dependencies>
         <build>
            <plugins>
               <plugin>
                  <groupId>org.apache.maven.plugins</groupId>
                  <artifactId>maven-shade-plugin</artifactId>
                  <version>3.5.1</version>
                  <configuration>
                     <createDependencyReducedPom>false</createDependencyReducedPom>
                  </configuration>
                  <executions>
                     <execution>
                        <phase>package</phase>
                        <goals>
                           <goal>shade</goal>
                        </goals>
                        <configuration>
                           <artifactSet>
                              <excludes>
                                 <exclude>org.apache.tomcat.embed:*</exclude>
                              </excludes>
                           </artifactSet>
                        </configuration>
                     </execution>
                  </executions>
               </plugin>
            </plugins>
         </build>
      </profile>
   </profiles>
</project>

olegz avatar Apr 24 '24 13:04 olegz