Use Apache cxf with spring mvc in the same application with shared services

I am currently working on a project that is based on spring MVC, this is just a standard project using the spring MVC template. so i have web.xml and servlet-context.xml.

I am working on adding Apache cxf web services to this project and encounter some problems when sharing services with existing spring MVC.

My initial approach was to make web services work, so here my web.xml looks like this:

<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <!-- The definition of the Root Spring Container shared by all Servlets and Filters --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring/root-context.xml /WEB-INF/spring/jaxwsServlet/jaxwsServlet-context.xml </param-value> </context-param> <!-- Creates the Spring Container shared by all Servlets and Filters --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- Process web service requests --> <servlet> <servlet-name>jaxws</servlet-name> <servlet-class>com.sun.xml.ws.transport.http.servlet.WSSpringServlet</servlet-class> <load-on-startup>2</load-on-startup> </servlet> <servlet-mapping> <servlet-name>jaxws</servlet-name> <url-pattern>/industryAspectWS</url-pattern> </servlet-mapping> <!-- Processes application requests --> <servlet> <servlet-name>appServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>appServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app> 

and my jaxwsServlet-context.xml

 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ws="http://jax-ws.dev.java.net/spring/core" xmlns:context="http://www.springframework.org/schema/context" xmlns:wss="http://jax-ws.dev.java.net/spring/servlet" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://jax-ws.dev.java.net/spring/core classpath:spring-jax-ws-core.xsd http://jax-ws.dev.java.net/spring/servlet classpath:spring-jax-ws-servlet.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd" > <wss:binding url="/industryAspectWS"> <wss:service> <ws:service bean="#industryAspectWS"/> </wss:service> </wss:binding> <!-- Web service methods --> <bean id="industryAspectWS" class="com.example.ws.IndustryAspectWS"></bean> <context:component-scan base-package="com.example" /> <beans:import resource="../HibernateTransaction.xml" /> <beans:import resource="../JaxbMarshaller.xml" /> </beans> 

I copied the context: component-scan beans: import sections from servlet-context.xml

This configuration works fine, as I was able to load the server and call web services, as well as access to servlets and jsp. However, I noticed that since I was quoting hibernateTransaction.xml in both context XML files, there are two session factories.

I want to share all services (such as hibernation) between Apache cxf and spring MVC controllers, so I tried to set the settings in root-context.xml, this did not work. I also tried searching the Internet, but did not find any examples for shared services. Is it possible that we can set a parameter for the exchange of services between the two?

===================================================

I experimented with some settings after I posted this and decided that if I put the lines

 <context:component-scan base-package="com.example" /> 

and

 <tx:annotation-driven transaction-manager="txManagerExample" /> 

both in servlet-context.xml and in jaxwsServlet-context.xml, it will work fine. all other settings can be in the general root context. xml

+6
source share
2 answers

WSSpringServlet not CXF. This is the subway. I would recommend using CXF. In this case, you will have a CXFServlet , but then you must configure CXF in your main Spring context (created by ContextLoaderListener .

It will work as follows: your main context will have all the common beans, including CXF. Your servlet context will have only your controllers. Because the servlet context is a child of the main context, your controllers will also have access to everything in the main context.

See Implementing CXF inside a Spring page , CXF Servlet Transport Page and my answer to this question about exchanging beans between a servlet context and the main context.

+7
source

Thanks to fooobar.com/questions/924025 / ... :

Two dispatchers (Spring MVC REST Controller and CXF JAX-WS) with one Spring Context, Java Config (no xml file ...):

WebApplicationInitializer:

 @Override public void onStartup(ServletContext servletContext) throws ServletException { AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext(); rootContext.register(MyServiceConfig.class); servletContext.addListener(new ContextLoaderListener(rootContext)); AnnotationConfigWebApplicationContext webContext = new AnnotationConfigWebApplicationContext(); webContext.setParent(rootContext); ServletRegistration.Dynamic restDispatcher = servletContext.addServlet("REST dispatcher", new DispatcherServlet(webContext)); restDispatcher.setLoadOnStartup(1); restDispatcher.addMapping("/api/*"); ServletRegistration.Dynamic cxfDispatcher = servletContext.addServlet("CXF dispatcher", CXFServlet.class); cxfDispatcher.setLoadOnStartup(1); cxfDispatcher.addMapping("/services/*"); } 

Config:

 @Configuration @ComponentScan("my.root.package") @ImportResource(value = {"classpath:META-INF/cxf/cxf.xml"}) @PropertySource("classpath:app-env.properties") @PropertySource("classpath:app.properties") @EnableWebMvc public class MyServiceConfig { @Autowired private Bus cxfBus; @Autowired private CxfEndpointImpl cxfEndpoint; @Bean public Endpoint cxfService() { EndpointImpl endpoint = new EndpointImpl(cxfBus, cxfEndpoint); endpoint.setAddress("/CxfEndpointImpl"); endpoint.setWsdlLocation("classpath:CxfService/CxfService-v1.0.wsdl"); endpoint.publish(); return endpoint; } @Bean public static PropertySourcesPlaceholderConfigurer placeHolderConfigurer() { return new PropertySourcesPlaceholderConfigurer(); } } 

Example endpoint CXF (first WSDL):

 @Component @WebService( endpointInterface = ".....v1_0.CxfServicePort", targetNamespace = "http://..../service/CxfService/v1_0", serviceName = "CxfService", portName = "CxfServicePort", wsdlLocation = "classpath:CxfService/CxfService-v1.0.wsdl") @MTOM(enabled = true) @SchemaValidation(type = SchemaValidationType.BOTH) @InInterceptors(classes = NoBinaryContentLoggingInInterceptor.class) @OutInterceptors(classes = NoBinaryContentLoggingOutInterceptor.class) @EndpointProperty(key = "ws-security.callback-handler", ref = "cxfEndpointSecurityHandler") public class CxfEndpointImpl implements CxfServicePort { //... } 

An example of a REST controller:

 @RestController @RequestMapping(value = "/system", produces = MediaType.APPLICATION_JSON_VALUE) public class RestController { //... } 

CXF Endpoint Deployment Address:

 ip:port/tomcat-context/services/CxfEndpointImpl?wsdl 

Spring REST Controller Deployment Address:

 ip:port/tomcat-context/api/system 
0
source

Source: https://habr.com/ru/post/924023/


All Articles