spring-attic / spring-native

Spring Native is now superseded by Spring Boot 3 official native support
https://docs.spring.io/spring-boot/docs/current/reference/html/native-image.html
Apache License 2.0
2.74k stars 355 forks source link

IOException parsing XML document from ServletContext resource fails #1653

Closed yyjason closed 2 years ago

yyjason commented 2 years ago

here is my demo https://github.com/yyjason/servlet-demo-202206/tree/master

yyjason commented 2 years ago

java -version: openjdk version "11.0.14" 2022-01-18 OpenJDK Runtime Environment GraalVM CE 22.0.0.2 (build 11.0.14+9-jvmci-22.0-b05) OpenJDK 64-Bit Server VM GraalVM CE 22.0.0.2 (build 11.0.14+9-jvmci-22.0-b05, mixed mode, sharing) spring-boot:2.6.7 spring-native:0.11.5 native-maven-plugin:0.9.11

yyjason commented 2 years ago

native compile is ok and native-image runs successfully.However,sending request(http:localhost:8080) fails with missing exampleServlet-servlet.xml.In fact,it's not needed.

mhalbritter commented 2 years ago

It fails with this stacktrace:

java.lang.NoSuchMethodException: org.springframework.web.context.support.XmlWebApplicationContext.<init>()
        at java.lang.Class.getConstructor0(DynamicHub.java:3585) ~[servlet-demo:na]
        at java.lang.Class.getDeclaredConstructor(DynamicHub.java:2754) ~[servlet-demo:na]
        at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:25) ~[na:na]
        at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:660) ~[servlet-demo:5.3.19]
        at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:716) ~[servlet-demo:5.3.19]
        at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:591) ~[servlet-demo:5.3.19]
        at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:530) ~[servlet-demo:5.3.19]
        at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:170) ~[servlet-demo:5.3.19]
        at javax.servlet.GenericServlet.init(GenericServlet.java:158) ~[servlet-demo:4.0.FR]
        at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1164) ~[na:na]
        at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:804) ~[na:na]
        at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:687) ~[na:na]
        at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:461) ~[na:na]
        at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:385) ~[na:na]
        at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:313) ~[na:na]
        at org.apache.catalina.core.StandardHostValve.custom(StandardHostValve.java:403) ~[na:na]
        at org.apache.catalina.core.StandardHostValve.status(StandardHostValve.java:249) ~[na:na]
        at org.apache.catalina.core.StandardHostValve.throwable(StandardHostValve.java:344) ~[na:na]
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:169) ~[na:na]
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[servlet-demo:9.0.62]
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[na:na]
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:360) ~[na:na]
        at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399) ~[na:na]
        at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[servlet-demo:9.0.62]
        at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:890) ~[na:na]
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1743) ~[na:na]
        at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[servlet-demo:9.0.62]
        at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[na:na]
        at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[na:na]
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[na:na]
        at java.lang.Thread.run(Thread.java:833) ~[servlet-demo:na]
        at com.oracle.svm.core.thread.PlatformThreads.threadStartRoutine(PlatformThreads.java:704) ~[servlet-demo:na]
        at com.oracle.svm.core.posix.thread.PosixPlatformThreads.pthreadStartRoutine(PosixPlatformThreads.java:202) ~[na:na]

2022-07-04 10:53:03.218 ERROR 240662 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost]           : Exception Processing ErrorPage[errorCode=0, location=/error]

javax.servlet.ServletException: Servlet.init() for servlet [exmpleServlet] threw exception
        at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1181) ~[na:na]
        at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:804) ~[na:na]
        at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:687) ~[na:na]
        at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:461) ~[na:na]
        at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:385) ~[na:na]
        at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:313) ~[na:na]
        at org.apache.catalina.core.StandardHostValve.custom(StandardHostValve.java:403) ~[na:na]
        at org.apache.catalina.core.StandardHostValve.status(StandardHostValve.java:249) ~[na:na]
        at org.apache.catalina.core.StandardHostValve.throwable(StandardHostValve.java:344) ~[na:na]
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:169) ~[na:na]
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[servlet-demo:9.0.62]
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[na:na]
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:360) ~[na:na]
        at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399) ~[na:na]
        at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[servlet-demo:9.0.62]
        at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:890) ~[na:na]
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1743) ~[na:na]
        at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[servlet-demo:9.0.62]
        at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[na:na]
        at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[na:na]
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[na:na]
        at java.lang.Thread.run(Thread.java:833) ~[servlet-demo:na]
        at com.oracle.svm.core.thread.PlatformThreads.threadStartRoutine(PlatformThreads.java:704) ~[servlet-demo:na]
        at com.oracle.svm.core.posix.thread.PosixPlatformThreads.pthreadStartRoutine(PosixPlatformThreads.java:202) ~[na:na]
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.web.context.support.XmlWebApplicationContext]: No default constructor found; nested exception is java.lang.NoSuchMethodException: org.springframework.web.context.support.XmlWebApplicationContext.<init>()
        at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:29) ~[na:na]
        at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:660) ~[servlet-demo:5.3.19]
        at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:716) ~[servlet-demo:5.3.19]
        at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:591) ~[servlet-demo:5.3.19]
        at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:530) ~[servlet-demo:5.3.19]
        at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:170) ~[servlet-demo:5.3.19]
        at javax.servlet.GenericServlet.init(GenericServlet.java:158) ~[servlet-demo:4.0.FR]
        at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1164) ~[na:na]
        ... 23 common frames omitted
Caused by: java.lang.NoSuchMethodException: org.springframework.web.context.support.XmlWebApplicationContext.<init>()
        at java.lang.Class.getConstructor0(DynamicHub.java:3585) ~[servlet-demo:na]
        at java.lang.Class.getDeclaredConstructor(DynamicHub.java:2754) ~[servlet-demo:na]
        at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:25) ~[na:na]
        ... 30 common frames omitted

which is "expected", as your Servlet tries to create a new XmlWebApplicationContext, as you extend from FrameworkServlet.

You can fix it for example this way:

public class ExmpleServlet extends FrameworkServlet {
    ExmpleServlet(WebApplicationContext webApplicationContext) {
        super(webApplicationContext);
    }
}

@Configuration
public class ServletConfiguration {

    @Bean
    public ExmpleServlet mainServletBean(WebApplicationContext webApplicationContext){
        return new ExmpleServlet(webApplicationContext);
    }

    @Bean
    public ServletRegistrationBean<ExmpleServlet> mainServletRegistration(ExmpleServlet exmpleServlet){
        ServletRegistrationBean<ExmpleServlet> servletRegistration = new ServletRegistrationBean<>(exmpleServlet);
        servletRegistration.getUrlMappings().clear();
        servletRegistration.addUrlMappings("/*");
        return servletRegistration;
    }
}

this way your servlet doesn't try to create a new context, but reuses the one Spring Boot has created.