Skip to content

@WebListener does not work in a native image without additional reflection hints #36008

@oliveryasuna

Description

@oliveryasuna

Reproducible with Spring Boot 3.1.0.

  1. Define a minimal servlet listener:
@WebListener public class MyServletContextListener implements ServletContextListener { }
  1. Add @ServletComponentScan to a configuration.

If you run the application from main, everything works as expected. However, if you build a native image with GraalVM, you get an exception:

java.lang.ClassNotFoundException: com.oliveryasuna.MyServletContextListener at org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader.loadClass(TomcatEmbeddedWebappClassLoader.java:72) at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1245) at org.apache.catalina.core.DefaultInstanceManager.loadClass(DefaultInstanceManager.java:490) at org.apache.catalina.core.DefaultInstanceManager.loadClassMaybePrivileged(DefaultInstanceManager.java:472) at org.apache.catalina.core.DefaultInstanceManager.newInstance(DefaultInstanceManager.java:142) at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4381) at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:4892) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1332) at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1322) at java.base@17.0.5/java.util.concurrent.FutureTask.run(FutureTask.java:264) at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75) at java.base@17.0.5/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:145) at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:871) at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:846) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1332) at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1322) at java.base@17.0.5/java.util.concurrent.FutureTask.run(FutureTask.java:264) at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75) at java.base@17.0.5/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:145) at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:871) at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:241) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) at org.apache.catalina.core.StandardService.startInternal(StandardService.java:428) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:913) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) at org.apache.catalina.startup.Tomcat.start(Tomcat.java:485) at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.initialize(TomcatWebServer.java:123) at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.<init>(TomcatWebServer.java:104) at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.getTomcatWebServer(TomcatServletWebServerFactory.java:489) at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.getWebServer(TomcatServletWebServerFactory.java:211) at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.createWebServer(ServletWebServerApplicationContext.java:183) at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:161) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:602) at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:733) at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:435) at org.springframework.boot.SpringApplication.run(SpringApplication.java:311) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1305) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1294) at com.oliveryasuna.Application.main(Application.java:21) 

I assume that this issue would present itself on all servlet component types: @WebFilter, @WebServlet, and @WebListener. I tried adding a reflection runtime hint, but this didn't work:

hints.reflection() .registerType( TypeReference.of(MyServletContextListener.class), MemberCategory.INVOKE_DECLARED_CONSTRUCTORS );

Metadata

Metadata

Assignees

No one assigned

    Labels

    theme: aotAn issue related to Ahead-of-time processingtype: bugA general bug

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions