-
Notifications
You must be signed in to change notification settings - Fork 2
Open
Description
Description of the bug / feature
Using custom servlet in a Quarkus+Vaadin app causes DevModeInitializer
to fail with ClassNotFoundException.
The reason is that Quarkus uses multiple classloaders; it loads Vaadin jars in one classloader and the app code (including the Servlet class) in another classloader. The "Vaadin classloader" is then unable to load the Servlet class.
The exception stacktrace follows:
2021-01-07 09:52:04,044 ERROR [io.qua.run.boo.StartupActionImpl] (Quarkus Main Thread) Error running Quarkus: java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at io.quarkus.runner.bootstrap.StartupActionImpl$3.run(StartupActionImpl.java:134)
at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.lang.ExceptionInInitializerError
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
at java.base/java.lang.Class.newInstance(Class.java:584)
at io.quarkus.runtime.Quarkus.run(Quarkus.java:61)
at io.quarkus.runtime.Quarkus.run(Quarkus.java:38)
at io.quarkus.runtime.Quarkus.run(Quarkus.java:104)
at io.quarkus.runner.GeneratedMain.main(GeneratedMain.zig:29)
... 6 more
Caused by: java.lang.RuntimeException: Failed to start quarkus
at io.quarkus.runner.ApplicationImpl.<clinit>(ApplicationImpl.zig:178)
... 15 more
Caused by: java.lang.RuntimeException: java.lang.RuntimeException: javax.servlet.ServletException: java.lang.reflect.InvocationTargetException
at io.quarkus.undertow.runtime.UndertowDeploymentRecorder.bootServletContainer(UndertowDeploymentRecorder.java:519)
at io.quarkus.deployment.steps.UndertowBuildStep$build-649634386.deploy_0(UndertowBuildStep$build-649634386.zig:1948)
at io.quarkus.deployment.steps.UndertowBuildStep$build-649634386.deploy(UndertowBuildStep$build-649634386.zig:40)
at io.quarkus.runner.ApplicationImpl.<clinit>(ApplicationImpl.zig:158)
... 15 more
Caused by: java.lang.RuntimeException: javax.servlet.ServletException: java.lang.reflect.InvocationTargetException
at io.undertow.servlet.core.DeploymentManagerImpl.deploy(DeploymentManagerImpl.java:255)
at io.quarkus.undertow.runtime.UndertowDeploymentRecorder.bootServletContainer(UndertowDeploymentRecorder.java:508)
... 18 more
Caused by: javax.servlet.ServletException: java.lang.reflect.InvocationTargetException
at com.vaadin.flow.server.startup.ClassLoaderAwareServletContainerInitializer.onStartup(ClassLoaderAwareServletContainerInitializer.java:99)
at io.undertow.servlet.core.DeploymentManagerImpl$1.call(DeploymentManagerImpl.java:205)
at io.undertow.servlet.core.DeploymentManagerImpl$1.call(DeploymentManagerImpl.java:187)
at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:42)
at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
at io.quarkus.undertow.runtime.UndertowDeploymentRecorder$10$1.call(UndertowDeploymentRecorder.java:554)
at io.undertow.servlet.core.DeploymentManagerImpl.deploy(DeploymentManagerImpl.java:253)
... 19 more
Caused by: java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at com.vaadin.flow.server.startup.ClassLoaderAwareServletContainerInitializer.onStartup(ClassLoaderAwareServletContainerInitializer.java:94)
... 25 more
Caused by: javax.servlet.ServletException: Servlet class name (org.acme.servlet.MyServlet) can't be found!
at com.vaadin.flow.server.startup.DevModeInitializer.process(DevModeInitializer.java:198)
... 30 more
Caused by: java.lang.ClassNotFoundException: org.acme.servlet.MyServlet
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
at io.quarkus.bootstrap.classloading.QuarkusClassLoader.loadClass(QuarkusClassLoader.java:412)
at io.quarkus.bootstrap.classloading.QuarkusClassLoader.loadClass(QuarkusClassLoader.java:365)
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:315)
at com.vaadin.flow.server.startup.DevModeInitializer.isVaadinServletSubClass(DevModeInitializer.java:218)
at com.vaadin.flow.server.startup.DevModeInitializer.process(DevModeInitializer.java:191)
... 30 more
Minimal reproducible example
Please see the attached app.
- Unzip the app
- Run
mvn -C clean package quarkus:dev
Expected behavior
Vaadin should use Thread's context class loader to load the classes
Actual behavior
Vaadin uses Class.forName()
which uses DevModeInitializer.class.getClassLoader()
.
Versions:
- Vaadin / Flow version: 14.4.4/2.4.3
- Java version: 11
- Application Server (if applicable): Quarkus+Vertx+Undertow
Metadata
Metadata
Assignees
Labels
No labels