title: Native Image - Spring Boot - AWS Serverless Java Container - startup error - missing ServletWebServerFactory bean
body: <p>I am trying to create a native image for my Spring Boot application that also uses the AWS serverless Java container.</p>
  <p>The Spring Boot app is a simple petstore application.</p>
  <pre><code>&lt;dependencies&gt;
      &lt;dependency&gt;
          &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
          &lt;artifactId&gt;spring-boot-starter-data-jdbc&lt;/artifactId&gt;
      &lt;/dependency&gt;
      &lt;dependency&gt;
          &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
          &lt;artifactId&gt;spring-boot-starter-web&lt;/artifactId&gt;
          &lt;exclusions&gt;
              
              &lt;!-- Comment for local --&gt;
              &lt;exclusion&gt;
                &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
                &lt;artifactId&gt;spring-boot-starter-tomcat&lt;/artifactId&gt;
              &lt;/exclusion&gt;
              &lt;!-- Not using yaml --&gt;
              &lt;exclusion&gt;
                &lt;groupId&gt;org.yaml&lt;/groupId&gt;
                &lt;artifactId&gt;snakeyaml&lt;/artifactId&gt;
              &lt;/exclusion&gt;
          &lt;/exclusions&gt;
      &lt;/dependency&gt;
      &lt;dependency&gt;
          &lt;groupId&gt;org.springframework&lt;/groupId&gt;
          &lt;artifactId&gt;spring-context-indexer&lt;/artifactId&gt;
          &lt;optional&gt;true&lt;/optional&gt;
      &lt;/dependency&gt;
  
      &lt;dependency&gt;
          &lt;groupId&gt;com.amazonaws.serverless&lt;/groupId&gt;
          &lt;artifactId&gt;aws-serverless-java-container-springboot2&lt;/artifactId&gt;
          &lt;version&gt;1.8&lt;/version&gt;
      &lt;/dependency&gt;
      &lt;dependency&gt;
          &lt;groupId&gt;mysql&lt;/groupId&gt;
          &lt;artifactId&gt;mysql-connector-java&lt;/artifactId&gt;
          &lt;scope&gt;runtime&lt;/scope&gt;
      &lt;/dependency&gt;
      &lt;dependency&gt;
          &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
          &lt;artifactId&gt;spring-boot-starter-test&lt;/artifactId&gt;
          &lt;scope&gt;test&lt;/scope&gt;
      &lt;/dependency&gt;
  &lt;/dependencies&gt;
  
  &lt;build&gt;
      &lt;plugins&gt;
          &lt;!-- &lt;plugin&gt;
              &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
              &lt;artifactId&gt;spring-boot-maven-plugin&lt;/artifactId&gt;
          &lt;/plugin&gt; --&gt;
          &lt;plugin&gt;
              &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
              &lt;artifactId&gt;maven-shade-plugin&lt;/artifactId&gt;
              &lt;configuration&gt;
                  &lt;createDependencyReducedPom&gt;false&lt;/createDependencyReducedPom&gt;
                  &lt;!-- &lt;filters&gt;
                      &lt;filter&gt;
                          &lt;artifact&gt;*:*&lt;/artifact&gt;
                          &lt;excludes&gt;
                              &lt;exclude&gt;**/Log4j2Plugins.dat&lt;/exclude&gt;
                          &lt;/excludes&gt;
                      &lt;/filter&gt;
                  &lt;/filters&gt; --&gt;
              &lt;/configuration&gt;
              &lt;executions&gt;
                  &lt;execution&gt;
                      &lt;phase&gt;package&lt;/phase&gt;
                      &lt;goals&gt;
                          &lt;goal&gt;shade&lt;/goal&gt;
                      &lt;/goals&gt;
                      &lt;configuration&gt;
                          &lt;artifactSet&gt;
                              &lt;excludes&gt;
                                  &lt;exclude&gt;org.apache.tomcat.embed:*.jar&lt;/exclude&gt;
                              &lt;/excludes&gt;
                          &lt;/artifactSet&gt;
                      &lt;/configuration&gt;
                  &lt;/execution&gt;
              &lt;/executions&gt;
          &lt;/plugin&gt;
      &lt;/plugins&gt;
      
  &lt;/build&gt;
  </code></pre>
  <p>Entry point</p>
  <pre><code>public class StreamLambdaHandler implements RequestStreamHandler {
  private static SpringBootLambdaContainerHandler&lt;HttpApiV2ProxyRequest, AwsProxyResponse&gt; handler;
  private static Logger logger = LoggerFactory.getLogger(StreamLambdaHandler.class);
  
  public static void main(String[] args) {
      
  }
  
  static {
      try {
          logger.info(&quot;StreamLambdaHandler static init start&quot;);
          //handler = SpringBootLambdaContainerHandler.getHttpApiV2ProxyHandler(SamplebootApplication.class);
          
            handler = new SpringBootProxyHandlerBuilder&lt;HttpApiV2ProxyRequest&gt;()
            .defaultHttpApiV2Proxy() .asyncInit()
            .springBootApplication(SamplebootApplication.class) .buildAndInitialize();
            
            logger.info(&quot;StreamLambdaHandler init -async init call &quot;);
           
          logger.info(&quot;StreamLambdaHandler init call invoked&quot;);
  
      } catch (ContainerInitializationException e) {
          // if we fail here. We re-throw the exception to force another cold start
          e.printStackTrace();
          throw new RuntimeException(&quot;Could not initialize Spring Boot application&quot;, e);
      }
  }
  
  @Override
  public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) throws IOException {
      Instant start = Instant.now();
      logger.info(&quot;StreamLambdaHandler handler method begin&quot;);
      handler.proxyStream(inputStream, outputStream, context);
      logger.info(
              &quot;StreamLambdaHandler handler method end in millisecs:&quot; + start.until(Instant.now(), ChronoUnit.MILLIS));
  
  }
  </code></pre>
  <p>The application works when deployed on AWS lambda. I am now trying to optimise the cold start time by converting to Native Image.</p>
  <p>Added spring native</p>
  <pre><code>&lt;dependency&gt;
          &lt;!-- This is a mandatory dependency for your application --&gt;
          &lt;groupId&gt;org.springframework.experimental&lt;/groupId&gt;
          &lt;artifactId&gt;spring-native&lt;/artifactId&gt;
          &lt;version&gt;0.11.4&lt;/version&gt;
      &lt;/dependency&gt;
  </code></pre>
  <p>Removed shade plugin, added AOT plugin</p>
  <pre><code>&lt;plugin&gt;
              &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
              &lt;artifactId&gt;spring-boot-maven-plugin&lt;/artifactId&gt;
              
          &lt;/plugin&gt;
          &lt;plugin&gt;
              &lt;groupId&gt;org.springframework.experimental&lt;/groupId&gt;
              &lt;artifactId&gt;spring-aot-maven-plugin&lt;/artifactId&gt;
              &lt;version&gt;0.11.4&lt;/version&gt;
              &lt;executions&gt;
                  &lt;execution&gt;
                      &lt;id&gt;generate&lt;/id&gt;
                      &lt;goals&gt;
                          &lt;goal&gt;generate&lt;/goal&gt;
                      &lt;/goals&gt;
                  &lt;/execution&gt;
                  &lt;!-- &lt;execution&gt; &lt;id&gt;test-generate&lt;/id&gt; &lt;goals&gt; &lt;goal&gt;test-generate&lt;/goal&gt; 
                      &lt;/goals&gt; &lt;/execution&gt; --&gt;
              &lt;/executions&gt;
          &lt;/plugin&gt;
  </code></pre>
  <p>The executable jar  - works fine in local.</p>
  <p><strong>Edit:</strong>
  <strong>The jar fails with the same error as below when run with springAot=true.</strong></p>
  <p>The jar is now converted to Native Image using below steps.</p>
  <pre><code>rm -rf native
  mkdir -p native
  cd native
  jar -xvf ../samplebootv2-native-0.0.1-SNAPSHOT.jar &gt;/dev/null 2&gt;&amp;1
  cp -R META-INF BOOT-INF/classes
  native-image -H:Name=samplebootv2-native-app -cp BOOT-INF/classes:`find BOOT-INF/lib | tr '\n' ':'`
  </code></pre>
  <p>Image is build without errors. However, when the native image is excecuted it fails with following error.</p>
  <pre><code>    org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.context.ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean.
          at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:163) ~[samplebootv2-native-app:2.6.6]
          at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:577) ~[samplebootv2-native-app:5.3.18]
          at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145) ~[samplebootv2-native-app:2.6.6]
          at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:740) ~[samplebootv2-native-app:2.6.6]
          at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:415) ~[samplebootv2-native-app:2.6.6]
          at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) ~[samplebootv2-native-app:2.6.6]
          at org.springframework.boot.builder.SpringApplicationBuilder.run(SpringApplicationBuilder.java:164) ~[na:na]
          at com.amazonaws.serverless.proxy.spring.SpringBootLambdaContainerHandler.initialize(SpringBootLambdaContainerHandler.java:195) ~[samplebootv2-native-app:na]
          at com.amazonaws.serverless.proxy.AsyncInitializationWrapper$AsyncInitializer.run(AsyncInitializationWrapper.java:120) ~[na:na]
          at java.lang.Thread.run(Thread.java:829) ~[samplebootv2-native-app:na]
          at com.oracle.svm.core.thread.PlatformThreads.threadStartRoutine(PlatformThreads.java:704) ~[samplebootv2-native-app:na]
          at com.oracle.svm.core.posix.thread.PosixPlatformThreads.pthreadStartRoutine(PosixPlatformThreads.java:202) ~[na:na]
      Caused by: org.springframework.context.ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean.
          at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.getWebServerFactory(ServletWebServerApplicationContext.java:210) ~[samplebootv2-native-app:2.6.6]
          at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.createWebServer(ServletWebServerApplicationContext.java:180) ~[samplebootv2-native-app:2.6.6]
          at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:160) ~[samplebootv2-native-app:2.6.6]
          ... 11 common frames omitted    
  </code></pre>
  <p>I checked the generated image using graal vm visualiser and found that the classes from the aws-serverless-java-container-springboot2-1.8.jar were missing in the image</p>
  <p>So I added the class files (only few of them) in</p>
  <pre><code>META-INF\native-image\org.springframework.aot\spring-aot\reflect-config.json
  </code></pre>
  <p>Also tried(with both init modes)</p>
  <pre><code>@InitializationHint(types =com.amazonaws.serverless.proxy.spring.embedded.ServerlessServletEmbeddedServerFactory.class, initTime = InitializationTime.RUN)
  </code></pre>
  <p>However, the same error repeats. The classes are missing in the generated image.</p>
  <p>Could anyone provide some insights into what could be going wrong here?</p>