I have a working Vaadin 18 prototype that uses web.xml and Spring.
The prototype is for a port of a large webapp that uses web.xml and vanilla Spring. I want to update the front-end without dropping web.xml or using Spring Boot.
It works fine in Vaadin 18.0.6, but fails on startup in Vaadin 22.0.0 with:
java.lang.IllegalStateException: The application Lookup instance is not found in the interface com.vaadin.flow.server.VaadinContext instance. It means that the container has not executed Lookup initialization code: so either the container is not Servlet 3.0 compatible or project configuration is broken.
at com.vaadin.flow.server.startup.ApplicationConfiguration.lambda$get$0 (ApplicationConfiguration.java:58)
at com.vaadin.flow.server.VaadinServletContext.getAttribute (VaadinServletContext.java:73)
at com.vaadin.flow.server.startup.ApplicationConfiguration.get (ApplicationConfiguration.java:50)
Initial digging suggests that the disable.automatic.servlet.registration context parameter is no longer supported.
What is required to get the prototype working in Vaadin 22?
Here is the web.xml:
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1"
metadata-complete="false">
<!-- NOTE: metadata-complete="false" is required, in order to invoke
ClassLoaderAwareServletContainerInitializer subclasses (DevModeInitializer etc) -->
<context-param>
<!-- disables registration of the VaadinServlet. This is required as it is registered via AppServlet -->
<param-name>disable.automatic.servlet.registration</param-name>
<param-value>true</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>AppServlet</servlet-name>
<servlet-class>org.example.AppServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>AppServlet</servlet-name>
<url-pattern>/app</url-pattern>
<url-pattern>/app/*</url-pattern>
</servlet-mapping>
</web-app>
And the corresponding servlet:
/**
* Servlet to wire Vaadin into web.xml.
*/
public class AppServlet extends HttpServlet {
private SpringServlet delegate;
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
ServletContext servletContext = getServletContext();
WebApplicationContext context = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);
delegate = new SpringServlet(context, false);
delegate.init(config);
}
@Override
public void destroy() {
if (delegate != null) {
delegate.destroy();
}
}
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
delegate.service(request, response);
}
}
As per this comment, the solution is to add a com.vaadin.flow.spring.VaadinApplicationConfiguration bean to applicationContext.xml.
This requires <context:annotation-config/> in order to work e.g.:
If you don't want to use <context:annotation-config/>, the beans that VaadinApplicationConfiguration creates can be added directly:
This isn't recommended as SpringApplicationContextInit is internal to Vaadin.