I have a Spring Boot web application that works fine. Now I got a 3rd party lib which I must use in the project. The manual of integrating the lib is written with respect to an existing web.xml file. My project completely relies on a Java based config.
According to the Spring documentation I can reach my goal of taking over the web.xml content into my application with the help of a WebApplicationInitializer.
That's what I did (at least I think I did it correctly). Before going into more details, here is the web.xml:
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>some.package.path.LoginServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>LogoutServlet</servlet-name>
<servlet-class>some.package.path.LogoutServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>ResultServlet</servlet-name>
<servlet-class>some.package.path.ResultServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/saml/login</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>LogoutServlet</servlet-name>
<url-pattern>/saml/logout</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>ResultServlet</servlet-name>
<url-pattern>/saml/result</url-pattern>
</servlet-mapping>
<env-entry>
<env-entry-name>some.package.path.config-file</env-entry-name>
<env-entry-type>java.lang.String</env-entry-type>
<env-entry-value>$HOME/.libName/libName-config.xml</env-entry-value>
</env-entry>
And here is how I refactored this in a Java config:
public class WebAppInitializer implements WebApplicationInitializer {
private static final Logger LOG = Logger.getLogger(WebAppInitializer.class.getSimpleName());
@Override
public void onStartup(ServletContext servletContext) {
final AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.scan("de.davidartmann.myapp.configuration");
final ServletRegistration.Dynamic dispatcher =
servletContext.addServlet("dispatcher", new DispatcherServlet(context));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
final ServletRegistration.Dynamic loginServlet =
servletContext.addServlet("LoginServlet", LoginServlet.class);
loginServlet.addMapping("/saml/login");
final ServletRegistration.Dynamic logoutServlet =
servletContext.addServlet("LogoutServlet", LogoutServlet.class);
logoutServlet.addMapping("/saml/logout");
final ServletRegistration.Dynamic resultServlet =
servletContext.addServlet("ResultServlet", ResultServlet.class);
resultServlet.addMapping("/saml/result");
try {
final InitialContext initialContext = new InitialContext();
initialContext.addToEnvironment("some.package.path.config-file",
"$HOME/.libName/libName-config.xml");
} catch (NamingException e) {
LOG.log(Level.SEVERE, "Could not initialize an InitialContext", e);
}
}
}
The problem is that the 3rd party lib throws an internal NPE with this setup. The NPE is thrown at the point where it @Inject
s (based on CDI) the runtime object of the <env-entry>
in the web.xml which I implemented as InitialContext
in my WebAppInitializer class.
My Spring Boot application uses a SpringBootServletInitializer
. The Spring documentation about Traditional Deployment mentions it with the words:
Normally, all the code from an existing WebApplicationInitializer can be moved into a SpringBootServletInitializer
@SpringBootApplication
public class MyApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(MyApplication.class);
}
}
Now, I am a unsure what to do? Is my implementation of WebApplicationInitializer
correct or do I need to use the SpringBootServletInitializer
in my Spring Boot main class?
Thanks for your help. David
The problem was, that the Tomcat server which was used to deploy the application does not provide an implementation for the dependency injection (CDI). I had to change to Wildfly which provides the necessary implementation.