Skip to content

NPE on org.springframework.boot.SpringApplication.getMainApplicationClass() with AOT #1579

Description

@andreaabram-eutelsat

Hi!
I'm trying to implement AOT into a simple java lambda

I'm using the com.amazonaws.serverless.proxy.spring.SpringDelegatingLambdaContainerHandler handler

Dependencies:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
    <version>3.5.7</version>
</dependency>
<dependency>
    <groupId>com.amazonaws.serverless</groupId>
    <artifactId>aws-serverless-java-container-springboot3</artifactId>
    <version>2.1.5</version>
</dependency>

Logs:

Picked up JAVA_TOOL_OPTIONS: -Dspring.aot.enabled=true
Picked up _JAVA_OPTIONS: -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,quiet=y,address=*:5005 -XX:MaxHeapSize=2834432k -XX:+UseSerialGC -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -Djava.net.preferIPv4Stack=true
11:25:50.498 [main] INFO org.springframework.cloud.function.serverless.web.FunctionClassUtils -- Main class: class org.example.IssueApplication
11:25:50.520 [main] INFO com.amazonaws.serverless.proxy.AsyncInitializationWrapper -- Async initialization will wait for 5775ms (init grace time is configured to 150)
11:25:50.522 [Thread-0] INFO com.amazonaws.serverless.proxy.AsyncInitializationWrapper -- Starting async initializer
11:25:50.550 [Thread-1] INFO org.springframework.cloud.function.serverless.web.ServerlessMVC -- Starting application with the following configuration classes:
11:25:50.551 [Thread-1] INFO org.springframework.cloud.function.serverless.web.ServerlessMVC -- IssueApplication
11:28:37.898 [Thread-1] ERROR org.springframework.boot.SpringApplication -- Application run failed
java.lang.NullPointerException: Cannot invoke "java.lang.Class.getName()" because the return value of "org.springframework.boot.SpringApplication.getMainApplicationClass()" is null
        at org.springframework.boot.env.EnvironmentPostProcessorApplicationListener.addAotGeneratedEnvironmentPostProcessorIfNecessary(EnvironmentPostProcessorApplicationListener.java:160)
        at org.springframework.boot.env.EnvironmentPostProcessorApplicationListener.onApplicationEnvironmentPreparedEvent(EnvironmentPostProcessorApplicationListener.java:130)
        at org.springframework.boot.env.EnvironmentPostProcessorApplicationListener.onApplicationEvent(EnvironmentPostProcessorApplicationListener.java:115)
        at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:185)
        at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:178)
        at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:156)
        at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:138)
        at org.springframework.boot.context.event.EventPublishingRunListener.multicastInitialEvent(EventPublishingRunListener.java:136)
        at org.springframework.boot.context.event.EventPublishingRunListener.environmentPrepared(EventPublishingRunListener.java:81)
        at org.springframework.boot.SpringApplicationRunListeners.lambda$environmentPrepared$2(SpringApplicationRunListeners.java:64)
        at java.base/java.lang.Iterable.forEach(Unknown Source)
        at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:118)
        at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:112)
        at org.springframework.boot.SpringApplicationRunListeners.environmentPrepared(SpringApplicationRunListeners.java:63)
        at org.springframework.boot.SpringApplication.prepareEnvironment(SpringApplication.java:353)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:313)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1361)
        at org.springframework.cloud.function.serverless.web.ServerlessMVC.initContext(ServerlessMVC.java:125)
        at org.springframework.cloud.function.serverless.web.ServerlessMVC.lambda$initializeContextAsync$1(ServerlessMVC.java:112)
        at java.base/java.lang.Thread.run(Unknown Source)
11:28:37.900 [Thread-1] INFO org.springframework.cloud.function.serverless.web.ServerlessMVC -- Application is started successfully.
Exception in thread "Thread-1" java.lang.IllegalStateException: java.lang.NullPointerException: Cannot invoke "java.lang.Class.getName()" because the return value of "org.springframework.boot.SpringApplication.getMainApplicationClass()" is null
        at org.springframework.cloud.function.serverless.web.ServerlessMVC.lambda$initializeContextAsync$1(ServerlessMVC.java:115)
        at java.base/java.lang.Thread.run(Unknown Source)
Caused by: java.lang.NullPointerException: Cannot invoke "java.lang.Class.getName()" because the return value of "org.springframework.boot.SpringApplication.getMainApplicationClass()" is null
        at org.springframework.boot.env.EnvironmentPostProcessorApplicationListener.addAotGeneratedEnvironmentPostProcessorIfNecessary(EnvironmentPostProcessorApplicationListener.java:160)
        at org.springframework.boot.env.EnvironmentPostProcessorApplicationListener.onApplicationEnvironmentPreparedEvent(EnvironmentPostProcessorApplicationListener.java:130)
        at org.springframework.boot.env.EnvironmentPostProcessorApplicationListener.onApplicationEvent(EnvironmentPostProcessorApplicationListener.java:115)
        at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:185)
        at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:178)
        at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:156)
        at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:138)
        at org.springframework.boot.context.event.EventPublishingRunListener.multicastInitialEvent(EventPublishingRunListener.java:136)
        at org.springframework.boot.context.event.EventPublishingRunListener.environmentPrepared(EventPublishingRunListener.java:81)
        at org.springframework.boot.SpringApplicationRunListeners.lambda$environmentPrepared$2(SpringApplicationRunListeners.java:64)
        at java.base/java.lang.Iterable.forEach(Unknown Source)
        at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:118)
        at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:112)
        at org.springframework.boot.SpringApplicationRunListeners.environmentPrepared(SpringApplicationRunListeners.java:63)
        at org.springframework.boot.SpringApplication.prepareEnvironment(SpringApplication.java:353)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:313)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1361)
        at org.springframework.cloud.function.serverless.web.ServerlessMVC.initContext(ServerlessMVC.java:125)
        at org.springframework.cloud.function.serverless.web.ServerlessMVC.lambda$initializeContextAsync$1(ServerlessMVC.java:112)
        ... 1 more
Cannot invoke "org.springframework.web.servlet.DispatcherServlet.getServletContext()" because "this.dispatcher" is null: java.lang.NullPointerException
java.lang.NullPointerException: Cannot invoke "org.springframework.web.servlet.DispatcherServlet.getServletContext()" because "this.dispatcher" is null
        at org.springframework.cloud.function.serverless.web.ServerlessMVC.getServletContext(ServerlessMVC.java:138)
        at com.amazonaws.serverless.proxy.spring.SpringDelegatingLambdaContainerHandler.handleRequest(SpringDelegatingLambdaContainerHandler.java:68)
        at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source)
        at java.base/java.lang.reflect.Method.invoke(Unknown Source)

END RequestId: 8baa5a53-ca92-4fd0-bc7e-b3720868d264
REPORT RequestId: 8baa5a53-ca92-4fd0-bc7e-b3720868d264  Init Duration: 0.02 ms  Duration: 171628.48 ms  Billed Duration: 171629 ms      Memory Size: 4096 MB    Max Memory Used: 4096 MB

Activity

  1. andreaabram-eutelsat commented on Nov 11, 2025

    @andreaabram-eutelsat
    Author

    I think that the issue is in the async initialization logic of the SpringDelegatingLambdaContainerHandler

    Here:

    public SpringDelegatingLambdaContainerHandler(final Class<?>... startupClasses) throws ContainerInitializationException {
    SpringDelegatingInitHandler initHandler = new SpringDelegatingInitHandler(startupClasses);
    if (InitializationTypeHelper.isAsyncInitializationDisabled()) {
    initHandler.initialize();
    } else {
    AsyncInitializationWrapper asyncInitWrapper = new AsyncInitializationWrapper();
    asyncInitWrapper.start(initHandler);
    }
    this.mvc = initHandler.getMvc();
    this.mapper = new ObjectMapper();
    this.responseWriter = new AwsProxyHttpServletResponseWriter();
    }

    Also here:

    private static final class SpringDelegatingInitHandler implements InitializableLambdaContainerHandler {
    private ServerlessMVC mvc;
    private final Class<?>[] startupClasses;
    public SpringDelegatingInitHandler(final Class<?>... startupClasses) {
    this.startupClasses = startupClasses;
    }
    @Override
    public void initialize() throws ContainerInitializationException {
    this.mvc = ServerlessMVC.INSTANCE(this.startupClasses);
    this.mvc.waitForContext();
    }
    public ServerlessMVC getMvc() {
    return this.mvc;
    }
    }

    Spring Code:

    The deduceMainApplicationClass method use the StackWalker to find, in the stacktrace, the first method that has a static main
    This method doesn't exists in the different thread
    Image

  2. andreaabram-eutelsat commented on Nov 11, 2025

    @andreaabram-eutelsat
    Author

    Update

    Creating a custom lambda handler instead of using the SpringDelegatingLambdaContainerHandler "bypass" this issue but creates another

    Handler:

    public class StreamLambdaHandler implements RequestStreamHandler {
    
        private static final Logger logger = LoggerFactory.getLogger(StreamLambdaHandler.class);
    
        private static SpringBootLambdaContainerHandler<AwsProxyRequest, AwsProxyResponse> handler;
    
        static {
            try {
                handler = SpringBootLambdaContainerHandler.getAwsProxyHandler(IssueApplication.class);
            } 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);
            }
        }
    
        @Override
        public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context)
            throws IOException {
            logger.info("entered generic stream lambda handler");
            handler.proxyStream(inputStream, outputStream, context);
        }
    }

    Issue:

    Description:
    
    Startup with AOT mode enabled failed: AOT initializer com.amazonaws.services.lambda.runtime.api.client.AWSLambda__ApplicationContextInitializer could not be found
    
    Action:
    
    Consider the following:
            Did you build the application with enabled AOT processing?
            Is the main class com.amazonaws.services.lambda.runtime.api.client.AWSLambda correct?
            If you want to run the application in regular mode, remove the system property 'spring.aot.enabled'
    
    Error loading class org.example.StreamLambdaHandler: java.lang.ExceptionInInitializerError
    java.lang.ExceptionInInitializerError
            at java.base/java.lang.Class.forName0(Native Method)
            at java.base/java.lang.Class.forName(Unknown Source)
            at java.base/java.lang.Class.forName(Unknown Source)
    Caused by: org.springframework.boot.AotInitializerNotFoundException: Startup with AOT mode enabled failed: AOT initializer com.amazonaws.services.lambda.runtime.api.client.AWSLambda__ApplicationContextInitializer could not be found
            at org.springframework.boot.SpringApplication.addAotGeneratedInitializerIfNecessary(SpringApplication.java:426)
            at org.springframework.boot.SpringApplication.prepareContext(SpringApplication.java:382)
            at org.springframework.boot.SpringApplication.run(SpringApplication.java:317)
            at org.springframework.boot.builder.SpringApplicationBuilder.run(SpringApplicationBuilder.java:149)
            at com.amazonaws.serverless.proxy.spring.SpringBootLambdaContainerHandler.initialize(SpringBootLambdaContainerHandler.java:198)
            at com.amazonaws.serverless.proxy.InitializationWrapper.start(InitializationWrapper.java:35)
            at com.amazonaws.serverless.proxy.spring.SpringBootProxyHandlerBuilder.buildAndInitialize(SpringBootProxyHandlerBuilder.java:80)
            at com.amazonaws.serverless.proxy.spring.SpringBootLambdaContainerHandler.getAwsProxyHandler(SpringBootLambdaContainerHandler.java:96)
            at org.example.StreamLambdaHandler.<clinit>(StreamLambdaHandler.java:23)
            ... 3 more
    

    It this case the deduceMainApplicationClass finds the AWS Runtime Interface Client class: com.amazonaws.services.lambda.runtime.api.client.AWSLambda so AOT looks for the wrong *__ApplicationContextInitializer

    I created another issue about this specific problem: #1580

  3. xav73400 commented on Nov 18, 2025

    @xav73400

    This is a blocking issue for me, too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions