Saturday, 15 February 2014

REST with Apache CXF

Overview

Apache CXF is a front-end framework for JAX-WS and JAX-RS services. 
Here in tutorial I am going to show how to develop restful service with Apache CXF.

Building your first REST Application

Though I have used IntelliJ IDEA to write this application, but you can use any other IDE like Eclipse or Netbeans to write it. This application will use Apache Maven for its build and dependency management.


1. Create your project

We will create a project named TodoApplication. Since this will be a maven project, so the project structure is going to be pretty standard as shown below:


 Don't mind the .idea folder since it is IDE specific. Rest should look as is.

2. Defining dependencies in pom.xml

For Apache CXF, there is a bundle jar which contains everything for JAX-RS implementation. Add the following dependency in pom.xml

 <dependency>  
       <groupId>org.apache.cxf</groupId>  
       <artifactId>cxf-bundle-jaxrs</artifactId>  
       <version>2.6.13</version>  
       <exclusions>  
         <exclusion>  
           <groupId>org.eclipse.jetty</groupId>  
           <artifactId>jetty-server</artifactId>  
         </exclusion>  
       </exclusions>  
 </dependency>  

For logging we will use slf4j over log4j.

 <dependency>  
       <groupId>log4j</groupId>  
       <artifactId>log4j</artifactId>  
       <version>${log4j.version}</version>  
 </dependency>  
 <dependency>  
       <groupId>org.slf4j</groupId>  
       <artifactId>slf4j-log4j12</artifactId>  
       <version>${sl4j.version}</version>  
 </dependency>  
 <dependency>  
       <groupId>org.slf4j</groupId>  
       <artifactId>slf4j-api</artifactId>  
       <version>${sl4j.version}</version>  
 </dependency>  

And lastly dependencies for Spring

 <dependency>  
       <groupId>org.springframework</groupId>  
       <artifactId>spring-core</artifactId>  
       <version>${org.springframework.version}</version>  
 </dependency>  
 <dependency>  
       <groupId>org.springframework</groupId>  
       <artifactId>spring-beans</artifactId>  
       <version>${org.springframework.version}</version>  
 </dependency>  
 dependency>  
       <groupId>org.springframework</groupId>  
       <artifactId>spring-context</artifactId>  
       <version>${org.springframework.version}</version>  
 </dependency>  
 <dependency>  
       <groupId>org.springframework</groupId>  
       <artifactId>spring-context-support</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-test</artifactId>  
       <version>${org.springframework.version}</version>  
       <scope>test</scope>  
 </dependency>  

The versions for slf4j, log4j and spring are : 

 <properties>  
     <org.springframework.version>3.2.4.RELEASE</org.springframework.version>  
     <log4j.version>1.2.17</log4j.version>  
     <sl4j.version>1.7.1</sl4j.version>  
 </properties>  

3. Defining web.xml

In folder src/main/webapp create a new folder with name WEB-INF. Under this folder create a file web.xml which defines your servlets and their mappings. CXF under the hood uses servlet only to map the urls to restful resources. Following is how our web.xml will look


 <?xml version="1.0" encoding="UTF-8"?>  
 <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">  
   <display-name>TodoApplication</display-name>  
   
   <context-param>  
     <param-name>contextConfigLocation</param-name>  
     <param-value>classpath:cxf-context.xml</param-value>  
   </context-param>  
   <listener>  
     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>  
   </listener>  
   <servlet>  
     <servlet-name>CXFServlet</servlet-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>  

CXFServlet is the servlet that dispatches the http call to restful resources. cxf-context.xml has the rest endpoints defined in it. We will get there in a while.

4. Writing a Rest Service

A Rest Service is basically the service class that will be exposed as endpoints. These have JAX-RS annotations that define the service. For starters let's write a Ping service which will simply tell that whether application is running fine or not.

 package com.examples.todo.rest;  
   
 import org.slf4j.Logger;  
 import org.slf4j.LoggerFactory;  
   
 import javax.ws.rs.GET;  
 import javax.ws.rs.Path;  
 import javax.ws.rs.Produces;  
 import javax.ws.rs.core.MediaType;  
 import javax.ws.rs.core.Response;  
   
   
 @Path("/ping")  
 public class PingService {  
   
   Logger logger = LoggerFactory.getLogger(PingService.class);  
   
   @GET  
   @Produces(MediaType.TEXT_PLAIN)  
   public Response ping(){  
     logger.info("Received request for ping service");  
     return Response.ok("Application is running fine").build();  
   }  
   
 }  
   

@Path annotation defines the path at which this service will be exposed.
@GET bind ping method to HTTP GET call. There are similar annotation for PUT, POST, DELETE and OPTIONS.
@Produces defines the Content-Type of the response.


5. Defining cxf-context.xml

This context file contains the configuration for cxf bus i.e. the transport and the endpoints.


 <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:cxf="http://cxf.apache.org/core"  
   
     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
               http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd  
              http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd  
  ">  
   
   <bean id="pingService" class="com.examples.todo.rest.PingService"/>  
   
   <jaxrs:server id="restContainer" address="/">  
     <jaxrs:serviceBeans>  
       <ref bean="pingService"/>  
     </jaxrs:serviceBeans>  
   </jaxrs:server>  
   
   <cxf:bus>  
     <cxf:features>  
       <cxf:logging/>  
     </cxf:features>  
   </cxf:bus>  
   
 </beans>  

<jaxrs:server> contains the service endpoints and the provider entries. Service endpoints goes in the <jaxrs:serviceBeans>

<cxf:bus> contains the configuration for cxf bus. Like logging is one of the features which will log every incoming request and outgoing response.

6. Deploying the application

This application can be deployed on one JEE container like Tomcat, Jetty.

After deployment hit the following url in your browser :

http://localhost:[PORT]/<context-root>/services/ping

You will see "Application is running fine" message in the browser.