NullPointerException when initializing VaadinServlet using Vaadin 14
Asked Answered
W

1

6

I am working on upgrading a Vaadin 8 application to Vaadin 14. I had to manually define an extension of VaadinServlet rather than using Vaadin 14's automatic servlet registration, as I need it to be mapped to a specific URL pattern. I am using web.xml to configure the servlet in the same way that it was successfully configured for Vaadin 8.

When my servlet is initialized, I get a ServletException caused by a NullPointerException coming from Vaadin's code. I looked at the source code and I can see that the exception occurs when Vaadin tries to get a Lookup instance from the servlet's ServletContext and instead it returns null. I found that the Lookup instance is supposed to get added to the context in LookupServletContainerInitializer, but it appears that this is not happening in my case.

Does anyone know what might be causing this issue? The stack trace of the NullPointerException is below.

Caused by: java.lang.NullPointerException
    at com.vaadin.flow.server.DeploymentConfigurationFactory.getTokenFileFromClassloader(DeploymentConfigurationFactory.java:341)
    at com.vaadin.flow.server.DeploymentConfigurationFactory.getTokenFileContents(DeploymentConfigurationFactory.java:311)
    at com.vaadin.flow.server.DeploymentConfigurationFactory.readBuildInfo(DeploymentConfigurationFactory.java:181)
    at com.vaadin.flow.server.DeploymentConfigurationFactory.createInitParameters(DeploymentConfigurationFactory.java:174)
    at com.vaadin.flow.server.VaadinServlet.createDeploymentConfiguration(VaadinServlet.java:152)
    at com.vaadin.flow.server.VaadinServlet.createServletService(VaadinServlet.java:190)
    at com.vaadin.flow.server.VaadinServlet.init(VaadinServlet.java:77)
    at org.eclipse.jetty.servlet.ServletHolder.initServlet(ServletHolder.java:602)
    ... 28 more
Witch answered 13/5, 2021 at 20:3 Comment(0)
S
4

LookupServletContainerInitializer is a javax.servlet.ServletContainerInitializer which is supposed to be automatically run by the servlet container during initialization.

There are two typical situations in which this part of initialization is skipped:

  • web.xml is configured to skip certain steps e.g. because metadata-complete is set to true or there's an empty <absolute-ordering>.
  • The functionality might need to be explicitly enabled if you're embedding a servlet container instead of running it as a standalone server. In the case of Jetty, you need to enable the AnnotationConfiguration module and maybe also set the ContainerIncludeJarPattern property to include at least the .jar file that includes VaadinServlet and related classes.

A third alternative is that you emulate ServletContainerInitializer by manually instantiating and invoking the initializers used by Vaadin. It requires a little bit of trial and error to discover exactly which initializers need to be run with what parameters. I created an example for what this might look like in https://github.com/Legioth/vaadin-without-classpath-scanning, but that was before LookupServletContainerInitializer was introduced so you would have to take care of that one separately.

Spasm answered 14/5, 2021 at 5:52 Comment(2)
Thanks for your help. I followed the example you provided and I no longer get the NullPointerException, though I now get a 404 error for one of the resources in /VAADIN/static/client and I'm not sure if it is related. Can you clarify which Vaadin classes I should pass to the DevModeInitializer? I see you passed it the class of every component you used in MainView. Is it necessary to pass it the class of every type of component I use in my application?Witch
If you're doing things manually, then you need to look at the @HandlesTypes annotation of the DevModeInitializer and pass in classes for everything relevant on the application's classpath that implements or is annotated with any of the listed interfaces or annotations. Then repeat the same for all the other ServletContainerInitializer subclasses that are part of Vaadin. Or alternatively, configure your servlet container to do that automatically for you instead. /VAADIN/static/client might be related to @PWA.Ovariotomy

© 2022 - 2024 — McMap. All rights reserved.