I have assembled a sample project which is on my GitHub repository.
A Small Introduction
CXF is designed with a very flexible architecture based on interceptors, this architecture allows the developer to make CXF work with different types of front end technologies such as JAX-WS, JAX-RS, CORBA and more!
CXF is also very friendly with the Spring framework so it is (or at least should be) very easy to integrate in this kind of applications.
Working with Maven
CXF artifacts are published on the central maven repository, so first of all, you need to add the dependencies into your project:
<dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-jaxws</artifactId> <version>${cxf.version}</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-jaxrs</artifactId> <version>${cxf.version}</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-transports-http</artifactId> <version>${cxf.version}</version> </dependency>
At the moment of writing this post CXF latest version is 2.6.2. Also you need to include dependencies for the Spring Framework, please refer to the sample project for these.
Spring Configuration
To start with this little how to, I created a service class with has mixed JAX-WS and JAX-RS annotations. This makes easy to export the same functionality as SOAP and REST web services:@WebService @SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE) public interface MyWebService { @WebMethod String doSomeWork(String work); public String beRestful(String name); @WebMethod public ArrayList<Customer> findCustomers(CustomerRequest request); }
And the implementation:
@WebService public class MyWebServiceImpl implements MyWebService { @WebMethod @Override public String doSomeWork(String work) { return "Doing some work with this: "+work; } @Override @GET @Path("/beRestful") @Produces("text/plain") //REST Annotations @WebMethod //SOAP Annotations public String beRestful(@QueryParam("name") String name) { return "Your name is: "+name; } @WebMethod public ArrayList<Customer> findCustomers(CustomerRequest request) { ArrayList<Customer> ret = new ArrayList<Customer>(); Customer customer = new Customer(); customer.setCustomerName(request.getName()); customer.setMembershipLevel(request.getMembershipLevel()); customer.setCustomerSince(new Date()); ret.add(customer); return ret; } }
The Customer and CustomerRequest classes are pretty simple and therefore not shown here, please refer to the sample project for the source code.
These exposes three methods through SOAP and one through REST, CXF has its own XML namespaces for JAX-WS and JAX-RS, the header of the applicationContext.xml file looks like the following:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:util="http://www.springframework.org/schema/util" xmlns:p="http://www.springframework.org/schema/p" xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:jaxrs="http://cxf.apache.org/jaxrs" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd/spring-spring-context-3.1.xsd-3.1.2.RELEASE.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd ">
CXF also has its own configuration files included inside the JAR files, even though these files look empty, the documentation suggests to include them so here are the lines for it:
<!-- import cxf webservices --> <import resource="classpath:META-INF/cxf/cxf.xml" /> <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
Finally, we need to declare the bean we just created as a Spring Bean and reference it in a SOAP and a REST endpoint:
<jaxws:endpoint id="mywebservice" implementor="#webserviceImpl" address="/myws" /> <jaxrs:server id="myrestservice" address="/rest"> <jaxrs:serviceBeans> <ref bean="webserviceImpl" /> </jaxrs:serviceBeans> </jaxrs:server> <bean id="webserviceImpl" class="com.juancavallotti.cxfdemo.MyWebServiceImpl" />
The last ingredient is configuring the CXF servlet in our web.xml file.
Configuration of web.xml
The configuration of this file is pretty standard, first I have declared the CXF servlet and map it to the /ws/* URL pattern, and then I just declared the standard listeners for the Spring Framework to work on a web environment.<!-- the cxf servlet --> <servlet> <servlet-name>cxfservlet</servlet-name> <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>cxfservlet</servlet-name> <url-pattern>/ws/*</url-pattern> </servlet-mapping> <!-- spring context and request listeners --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <listener> <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class> </listener>
Running the example
After following these steps we are ready to run the example application, if you have forked or cloned the sample application just run: $ mvn tomcat:run command line and after the startup, point the browser to: http://localhost:8080/CxfDemo/ws, you should see a very simple webpage that informs the webservices running on the CXF servlet and links to the WSDL and the WADL: