I'm bootifying an existing Spring Web application so the generated war file embed a Jetty web server. I want to stick to the existing configuration as much as I can in order to limit the regressions.
Here is the existing web.xml
:
<web-app id="fbecart-webapp" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<context-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.fbecart.ApplicationConfiguration</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>spring-dispatcher</servlet-name>
<servlet-class>com.fbecart.MyDispatcherServlet</servlet-class>
<init-param>
<param-name>dispatchOptionsRequest</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.fbecart.SpringDispatcherServletConfiguration</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring-dispatcher</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<filter>
<filter-name>GzipFilter</filter-name>
<filter-class>org.eclipse.jetty.servlets.GzipFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>GzipFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>openSessionInView</filter-name>
<filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>openSessionInView</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
Here is my main class JettyApplication.java
:
package com.fbecart;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@Configuration
@Import({ ApplicationConfiguration.class, SpringDispatcherServletConfiguration.class,
EmbeddedServletContainerAutoConfiguration.class })
public class JettyApplication {
public static void main(String[] args) throws Exception {
SpringApplication.run(JettyApplication.class, args);
}
}
I performed a few changes to my Gradle build scripts to make it work:
- addition of the dependencies to spring-boot-starter and spring-boot-starter-jetty
- configuration of the spring-boot plugin
The app starts fine, the controllers are loaded and I can query the server. But none of the filters defined in the web.xml are enabled.
Now I would like to remove the imports of PropertiesConfiguration.class
, ApplicationConfiguration.class
and SpringDispatcherServletConfiguration.class
in JettyApplication.java
, and somehow replace those by loading or importing the content of web.xml
into the embedded servlet container. But I ignore if that is a right strategy and if I can make it. I would greatly appreciate any help.
-- SOLUTION
Here is the final JettyApplication.class
based on Dave's answer:
package com.fbecart;
import org.eclipse.jetty.servlets.GzipFilter;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.DispatcherServlet;
@Configuration
@Import({ ApplicationConfiguration.class, SpringDispatcherServletConfiguration.class,
EmbeddedServletContainerAutoConfiguration.class })
public class JettyApplication {
public static void main(String[] args) throws Exception {
SpringApplication.run(JettyApplication.class, args);
}
@Bean
public DispatcherServlet dispatcherServlet() {
return new MyDispatcherServlet();
}
@Bean
public GzipFilter gzipFilter() {
return new GzipFilter();
}
@Bean
public CharacterEncodingFilter characterEncodingFilter() {
final CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
characterEncodingFilter.setEncoding("UTF-8");
characterEncodingFilter.setForceEncoding(true);
return characterEncodingFilter;
}
@Bean
public OpenEntityManagerInViewFilter openEntityManagerInViewFilter() {
return new OpenEntityManagerInViewFilter();
}
}
I will replace web.xml by a ServletContainerInitializer in a near future... stay tuned ;)
If I were you I would slowly try to peel away the layers in web.xml and remove it altogether. That way you will only have one configuration for the whole application including all filters and servlets (that's the idea anyway). You can do some parallel running while you stabilize where the filters are duplicated in web.xml, and then when you have the same functionality in a main application you can just delete web.xml. To add filters to your main application just create @Bean definitions for
Filter
orFilterRegistrationBean
instances.You can always support a war deployment through
SpringBootServletInitializer
as well if needed.