问题
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/*");
}
回答1:
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.
回答2:
I found the following project on github which helped me get started
https://github.com/ungerts/spring-boot-jaxrs-sample
Worked for me with:
- spring-boot 1.2.3
- cxf-rt-frontend-jaxrs:3.1.0
- jackson-jaxrs-json-provider:2.5.3
回答3:
Samples are now part of the CXF wiki: http://cxf.apache.org/docs/jaxrs-services-configuration.html#JAXRSServicesConfiguration-SpringBoot
来源:https://stackoverflow.com/questions/24002089/spring-boot-with-tomcat-and-cxf-servlet