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

Cannot invoke "org.springframework.web.servlet.DispatcherServlet.getServletContext()" because "servlet" is null

Open fabiencoppens opened this issue 1 year ago • 4 comments

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

Serverless Java Container version: 2.0.1

Implementations: Spring Boot

Framework version: Spring Boot 3.2.2

Frontend service: HTTP API (Spring GraphQl)

Deployment method: Local Docker image with AWS RIE runtime interface emulator

Scenario

I'm running a Spring Boot 3 based Lambda packaged as a Docker image and testing it via the RIE, as described here https://docs.aws.amazon.com/lambda/latest/dg/images-test.html#images-test-alt I'm using aws-serverless-java-container-springboot3 v2.0.1 Using the SpringDelegatingLambdaContainerHandler

Environment variables used: MAIN_CLASS="com.acme.ist.ebs.polaris.payschedules.Application" SPRING_PROFILES_ACTIVE="dev" DB_PASSWORD="redacted"

Expected behavior

I would expect the serverless container to properly bootstrap the Spring application context

Actual behavior

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.(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)

Steps to reproduce

Environment variables used: MAIN_CLASS="com.acme.ist.ebs.polaris.payschedules.Application" SPRING_PROFILES_ACTIVE="dev" DB_PASSWORD="redacted"

Dockerfile entrypoint: ENTRYPOINT [ "/entry_script.sh","com.amazonaws.serverless.proxy.spring.SpringDelegatingLambdaContainerHandler" ]

docker build --platform linux/amd64 -t latest . docker run --platform linux/amd64 -p 9000:8080 latest

curl "http://localhost:9000/2015-03-31/functions/function/invocations" -H "Content-Type: application/json" -X POST -d '{}'

Full log output

Exception in thread "Thread-0" java.lang.IllegalStateException: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'payScheduleServiceImpl' defined in URL [jar:file:/usr/src/app/app.jar!/com/acme/ist/ebs/polaris/payschedules/service/PayScheduleServiceImpl.class]: Unsatisfied dependency expressed through constructor parameter 0: No qualifying bean of type 'com.acme.ist.ebs.polaris.payschedules.repository.PayScheduleRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {} at org.springframework.cloud.function.serverless.web.ServerlessMVC.lambda$initializeContextAsync$1(ServerlessMVC.java:116) at java.base/java.lang.Thread.run(Unknown Source) Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'payScheduleServiceImpl' defined in URL [jar:file:/usr/src/app/app.jar!/com/acme/ist/ebs/polaris/payschedules/service/PayScheduleServiceImpl.class]: Unsatisfied dependency expressed through constructor parameter 0: No qualifying bean of type 'com.acme.ist.ebs.polaris.payschedules.repository.PayScheduleRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {} at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:801) at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:240) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1350) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1187) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:558) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:518) at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:325) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:323) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:973) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:950) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:616) at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:746) at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:448) at org.springframework.boot.SpringApplication.run(SpringApplication.java:324) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1321) 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.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.acme.ist.ebs.polaris.payschedules.repository.PayScheduleRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {} at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1824) at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1383) at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1337) at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:910) at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:788) ... 19 more %d [%thread] %-5level %logger - %msg%n org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'payScheduleServiceImpl' defined in URL [jar:file:/usr/src/app/app.jar!/com/acme/ist/ebs/polaris/payschedules/service/PayScheduleServiceImpl.class]: Unsatisfied dependency expressed through constructor parameter 0: No qualifying bean of type 'com.acme.ist.ebs.polaris.payschedules.repository.PayScheduleRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {} at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:801) ~[app.jar:?] at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:240) ~[app.jar:?] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1350) ~[app.jar:?] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1187) ~[app.jar:?] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:558) ~[app.jar:?] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:518) ~[app.jar:?] at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:325) ~[app.jar:?] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[app.jar:?] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:323) ~[app.jar:?] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[app.jar:?] at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:973) ~[app.jar:?] at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:950) ~[app.jar:?] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:616) ~[app.jar:?] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:746) ~[app.jar:?] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:448) ~[app.jar:?] at org.springframework.boot.SpringApplication.run(SpringApplication.java:324) ~[app.jar:?] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1321) ~[app.jar:?] at org.springframework.cloud.function.serverless.web.ServerlessMVC.initContext(ServerlessMVC.java:126) ~[app.jar:?] at org.springframework.cloud.function.serverless.web.ServerlessMVC.lambda$initializeContextAsync$1(ServerlessMVC.java:113) ~[app.jar:?] at java.lang.Thread.run(Unknown Source) [?:?] Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.acme.ist.ebs.polaris.payschedules.repository.PayScheduleRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {} at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1824) ~[app.jar:?] at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1383) ~[app.jar:?] at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1337) ~[app.jar:?] at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:910) ~[app.jar:?] at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:788) ~[app.jar:?] ... 19 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.(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:68) at com.amazonaws.services.lambda.runtime.api.client.EventHandlerLoader$2.call(EventHandlerLoader.java:907) at com.amazonaws.services.lambda.runtime.api.client.AWSLambda.startRuntime(AWSLambda.java:239) at com.amazonaws.services.lambda.runtime.api.client.AWSLambda.startRuntime(AWSLambda.java:191) at com.amazonaws.services.lambda.runtime.api.client.AWSLambda.main(AWSLambda.java:181) java.lang.NullPointerException: Cannot invoke "org.springframework.web.servlet.DispatcherServlet.getServletContext()" because "servlet" is null: java.lang.IllegalStateException 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:68) 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.(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) ... 1 more

fabiencoppens avatar Apr 11 '24 17:04 fabiencoppens

I am a bit puzzled by this error as I can not reproduce it, while it seems like few have already reproduced it. Perhaps I am missing something with regard to some specific configuration, so a sample app that reproduces it would help. The DispatcherServlet's ServletContext should me automatically set during the initialisation of application context, so the fact that it doesn't makes me wonder. I'll keep looking but if someone can produce a sample app that reproduces the issue it would help.

olegz avatar Apr 17 '24 12:04 olegz

@fabiencoppens please see this comment https://github.com/aws/serverless-java-container/issues/770#issuecomment-2074977920 Please help me understand what is going on as I can not reproduce it

olegz avatar Apr 24 '24 13:04 olegz

Hey @fabiencoppens I had the same error when I forgot to exclude the spring-boot-starter-tomcat from the jar deployed to Lambda. Maybe this helps you or any other person stumbling upon this issue 🤷

mircohacker avatar Apr 26 '24 15:04 mircohacker

@fabiencoppens please try this

handler = new SpringBootProxyHandlerBuilder<AwsProxyRequest>() .defaultProxy() .servletApplication() .asyncInit() .springBootApplication(GoalMainApplication.class) .buildAndInitialize();

jahidmomin avatar Jun 13 '24 06:06 jahidmomin