I'm trying to stand up an embedded Tomcat with spring-boot. I want to use CXF for a set of web services in the app but I can not figure out how to stand up the CXF servlet.
My Main class looks like this...
@Configuration
@EnableAutoConfiguration
@ComponentScan(basePackages={"com.connecture.services.documentservice.webservice"})
public class Application {
public static void main(String[] args) {
SpringApplication.run(new Class[] { Application.class, CfxInitializer.class }, args);
}
@Bean
public EmbeddedServletContainerFactory embeddedServletContainerFactory() {
TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory("", 8080);
return factory;
}
}
And my CfxInitializer like this...
public class CfxInitializer implements ServletContextInitializer
{
@Override
public void onStartup(ServletContext servletContext) throws ServletException
{
XmlWebApplicationContext rootContext = new XmlWebApplicationContext();
rootContext.setConfigLocations(new String[] { "classpath*:applicationContext.xml" });
servletContext.addListener(new ContextLoaderListener(rootContext));
ServletRegistration.Dynamic dispatcher = servletContext.addServlet("CXFServlet", CXFServlet.class);
dispatcher.addMapping("/api/*");
}
}
When I try to build and start the jar with the typical command ./gradlew build && java -jar build/libs/gs-spring-boot-0.1.0.jar
I get an Exception for multiple Contexts.
Java.lang.IllegalStateException: Cannot initialize context because there is already a root application context present - check whether you have multiple ContextLoader* definitions in your web.xml!
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:277)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4971)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5467)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
Here is a more complete pastebin - http://pastebin.com/bcJ2ULhM
Similarly to Dave's answer I was able to fix it by removing the ServletContextInitializer and adding a bean to the Application Class.
@Bean
public ServletRegistrationBean servletRegistrationBean(){
return new ServletRegistrationBean(new CXFServlet(),"/api/*");
}
The Spring Boot embedded servlet features are designed to work with Servlet
and ServletRegistration
@Beans
, and not with the ContextLoaderListener
(which looks like it is trying to steal the ServletContext
attribute for the root context). Try adding a ServletRegistration
for your servlet instead; if it is Spring aware, assuming it has an interface that lets you change the application context or the context location, then you should be able to configure it in the registration.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With