Step 1: Create Maven project
Following pom.xml defines the dependencies for this example.
Copy
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.lal.pro</groupId>
<artifactId>apache-cxf-rest-ws</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>apache-cxf-rest-ws Maven Webapp</name>
<url>http://maven.apache.org</url>
<properties>
<cxf.version>2.5.0</cxf.version>
<org.springframework.version>4.1.1.RELEASE</org.springframework.version>
<com.fasterxml.jackson.version>2.3.3</com.fasterxml.jackson.version>
<ch.qos.logback.version>1.1.3</ch.qos.logback.version>
<org.sl4j.version>1.7.12</org.sl4j.version>
<spring.ws.version>2.2.4.RELEASE</spring.ws.version>
</properties>
<dependencies>
<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-transports-http</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>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${com.fasterxml.jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${com.fasterxml.jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${com.fasterxml.jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>${com.fasterxml.jackson.version}</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.1</version>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${org.springframework.version}</version>
</dependency>
</dependencies>
<build>
<finalName>apache_cxf_rest_ws</finalName>
</build>
</project>
Step 2: Create web.xml
Following web.xml must be placed at "/apache-cxf-rest-ws/src/main/webapp/WEB-INF/".
Copy
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>CXF</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:ApplicationContext-cxf.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<servlet>
<servlet-name>CXFServlet</servlet-name>
<display-name>CXF Servlet</display-name>
<servlet-class>
org.apache.cxf.transport.servlet.CXFServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
</web-app>
Step 3: Create ApplicationContext
In the following xml we can define the beans, also group the web services and specify In and out interceptors. Place this xml file at /apache-cxf-rest-ws/src/main/resources/. Make sure it is added in your web.xml.
Copy
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxrs="http://cxf.apache.org/jaxrs"
xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:cxf="http://cxf.apache.org/core" xmlns:task="http://www.springframework.org/schema/task"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.1.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<task:annotation-driven />
<context:component-scan base-package="com.lal.pro">
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Service" />
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Component" />
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Repository" />
</context:component-scan>
<context:annotation-config />
<context:component-scan base-package="com.lal.pro" />
<bean id="addressWebService" class="com.lal.pro.cxf.ws.impl.AddressWebServiceImpl" />
<jaxrs:server id="systemService" address="/system">
<jaxrs:serviceBeans>
<ref bean="addressWebService" />
</jaxrs:serviceBeans>
<jaxrs:providers>
<ref bean="jsonProvider" />
</jaxrs:providers>
</jaxrs:server>
<bean
class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor" />
<bean id="jacksonMapper"
class="com.lal.pro.cxf.ws.impl.mapper.CustomJacksonObjectMapper" />
<bean id="jsonProvider" class="com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider">
<property name="mapper" ref="jacksonMapper" />
</bean>
</beans>
Step 4: Create a data transfer object
Following DTO can be used in request and response.
Copy
package com.lal.pro.dto;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Address {
private String streetAddress;
private String addressOptional;
private String city;
private String state;
private String country;
private String zip;
public String getStreetAddress() {
return streetAddress;
}
public void setStreetAddress(String streetAddress) {
this.streetAddress = streetAddress;
}
public String getAddressOptional() {
return addressOptional;
}
public void setAddressOptional(String addressOptional) {
this.addressOptional = addressOptional;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getZip() {
return zip;
}
public void setZip(String zip) {
this.zip = zip;
}
}
Step 5: Create Web Service
Following code snippet shows the implementaion of Web Service class. It just creates a java object and returns it. When a client consumes this REST webservice it can decide whether it wants the data in xml or json format by setting the header Accept = "application/xml" or Accept = "application/json"
Copy
package com.lal.pro.cxf.ws.impl;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Response;
import com.lal.pro.dto.Address;
public class AddressWebServiceImpl {
@GET
@Path("/v1/address")
@Produces({ "application/xml", "application/json" })
public Response getAddress() {
Address addressResponse = createAddress();
return Response.ok(addressResponse).build();
}
private Address createAddress() {
Address address = new Address();
address.setStreetAddress("4800 abc Rd");
address.setCity("abcd");
address.setState("NJ");
address.setCountry("US");
address.setZip("10001");
address.setAddressOptional("addressOptional");
return address;
}
}
Step 6: Customize ObjectMapper
Configure the ObjectMapper not to FAIL_ON_UNKNOWN_PROPERTIES
Copy
package com.lal.pro.cxf.ws.impl.mapper;
import java.text.SimpleDateFormat;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
public class CustomJacksonObjectMapper extends ObjectMapper {
private static final String DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX";
public CustomJacksonObjectMapper() {
this.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
this.configure(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL, true);
this.setSerializationInclusion(Include.NON_EMPTY);
this.setDateFormat(new SimpleDateFormat(DATE_FORMAT));
}
}
JSON Response
When client Header, Accept="application/json"
Copy
{
"streetAddress": "4800 abc Rd",
"addressOptional": "addressOptional",
"city": "abcd",
"state": "NJ",
"country": "US",
"zip": "10001"
}
XML Response
When client Header, Accept="application/xml"
Copy
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<address>
<addressOptional>addressOptional</addressOptional>
<city>abcd</city>
<country>US</country>
<state>NJ</state>
<streetAddress>4800 abc Rd</streetAddress>
<zip>10001</zip>
</address>