spring-boot avec Tomcat et cxf-servlet
-
20-12-2019 - |
Question
J'essaie de mettre en place un Tomcat intégré avec Spring-Boot.Je souhaite utiliser CXF pour un ensemble de services Web dans l'application, mais je n'arrive pas à comprendre comment faire fonctionner le servlet CXF.
Ma classe principale ressemble à ceci...
@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;
}
}
Et mon CfxInitializer comme ça...
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/*");
}
}
Quand j'essaie de construire et de démarrer le pot avec la commande typique ./gradlew build && java -jar build/libs/gs-spring-boot-0.1.0.jar
Je reçois une exception pour plusieurs contextes.
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)
Voici un pastebin plus complet - http://pastebin.com/bcJ2ULhM
----------------------------------------------------------------------------------
De la même manière que pour la réponse de Dave, j'ai pu le résoudre en supprimant le ServletContextInitializer et en ajoutant un bean à la classe Application.
@Bean
public ServletRegistrationBean servletRegistrationBean(){
return new ServletRegistrationBean(new CXFServlet(),"/api/*");
}
La solution
Les fonctionnalités du servlet intégré Spring Boot sont conçues pour fonctionner avec Servlet
et ServletRegistration
@Beans
, et non avec le ContextLoaderListener
(on dirait qu'il essaie de voler le ServletContext
attribut pour le contexte racine).Essayez d'ajouter un ServletRegistration
pour votre servlet à la place ;s'il est compatible avec Spring, en supposant qu'il dispose d'une interface qui vous permet de modifier le contexte de l'application ou l'emplacement du contexte, vous devriez alors pouvoir le configurer lors de l'enregistrement.
Autres conseils
J'ai trouvé le projet suivant sur github qui m'a aidé à démarrer
https://github.com/ungerts/spring-boot-jaxrs-sample
J'ai travaillé pour moi avec :
- démarrage à ressort 1.2.3
- cxf-rt-frontend-jaxrs:3.1.0
- jackson-jaxrs-json-provider:2.5.3
Les exemples font désormais partie du wiki CXF : http://cxf.apache.org/docs/jaxrs-services-configuration.html#JAXRSServicesConfiguration-SpringBoot