CXF REST Exception Handling

CXF REST Exception Handling explains about step by step details of Exception Handling In REST services using Apache CXF with Eclipse IDE

JAX-RS is Java API for RESTful Webservices which is very rely upon Representational State Transfer model, you can view JAX-RS specification. JAX-RS uses annotations for simplifying the development efforts.

Apache CXF provides in built exception handling mechanism for both REST & SOAP based services, By using this you can handle exceptions very easily without any additional efforts.

You can see the below example, which is demonstrating How to handle an exception in a REST service using CXF

Note

You can also see the CXF REST & SOAP Exception Handling Together, please refer CXF REST & SOAP Exception Handling, For CXF SOAP exception handling, please refer CXF Web Service Exception Handling

Required Libraries

You need to download

  1. JDK 7
  2. Eclipse 4.2
  3. CXF-2.7.3
  4. Tomcat 7

Following jar must be in classpath

  1. commons-logging-1.1.1.jar
  2. cxf-2.7.3.jar
  3. httpasyncclient-4.0-beta3.jar
  4. httpclient-4.2.1.jar
  5. httpcore-4.2.2.jar
  6. httpcore-nio-4.2.2.jar
  7. neethi-3.0.2.jar
  8. spring-aop-3.0.7.RELEASE.jar
  9. spring-asm-3.0.7.RELEASE.jar
  10. spring-beans-3.0.7.RELEASE.jar
  11. spring-context-3.0.7.RELEASE.jar
  12. spring-core-3.0.7.RELEASE.jar
  13. spring-expression-3.0.7.RELEASE.jar
  14. spring-web-3.0.7.RELEASE.jar
  15. wsdl4j-1.6.2.jar
  16. jaxb-impl-2.2.6.jar
  17. javax.ws.rs-api-2.0-m10.jar
  18. xmlschema-core-2.0.3.jar
  19. jettison-1.3.3.jar (JSON library)

CXF REST Exception Handling Example

I am creating a sample restful service project that pass Student object and return with some changes on that object. The service is using simple POJO (Plain Old Java Object) bean.

Firstly create a Dynamic Web Project (File->New->Dynamic Web Project) named "CXFRestfulTutorial" according to following screenshot

CXF REST Exception Handling CXF REST Exception Handling

Create a Student Object

package com.student;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "Student")
public class Student {
 
private String name;

 
public String getName() {
   
return name;
 
}

 
public void setName(String name) {
   
this.name = name;
 
}

}
Here @XmlRootElement(name = "Student"), is a JAXB convention specifies that Student is XML document.

If you are specifies that @Produces("application/json") then Jettison library converts the JAXB to json text as response

Create a Service Interface

This service interface will defines which methods of restful service, to be invoked by the client

package com.student;

public interface ChangeStudentDetails {

 
public Student changeName(Student student) throws ServiceException;
}

Create a ServiceExceptionDetails

This class holds the exception details for a service

package com.student;

import java.io.Serializable;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "ServiceExceptionDetails")
public class ServiceExceptionDetails implements Serializable {
 
 
private String faultCode;
 
private String faultMessage;

 
public ServiceExceptionDetails() {
  }

 
public String getFaultCode() {
   
return faultCode;
 
}

 
public void setFaultCode(String faultCode) {
   
this.faultCode = faultCode;
 
}

 
public String getFaultMessage() {
   
return faultMessage;
 
}

 
public void setFaultMessage(String faultMessage) {
   
this.faultMessage = faultMessage;
 
}

}

Create a ServiceException

This class contains an array of ServiceExceptionDetails(if more than one exceptions occurred)

package com.student;

import java.io.Serializable;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "ServiceException")
public class ServiceException extends Exception implements Serializable {
 
 
private ServiceExceptionDetails faultDetails[];

 
public ServiceException(ServiceExceptionDetails faultDetails[]) {
   
this.faultDetails = faultDetails;
 
}

 
public ServiceException(String message, ServiceExceptionDetails faultDetails[]) {
   
super(message);
   
this.faultDetails = faultDetails;
 
}

 
public ServiceExceptionDetails[] getFaultDetails() {
   
return faultDetails;
 
}

}

Implement the Service Interface

Here we implement the service interface created on the previous step

Here we are using one example showing with GET method& another with POST method

GET---> Calling this method will not result any changes to the server

POST---> Calling this method will result changes to the server, This have more secure than GET method

package com.student;

import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;

@Consumes("application/json")
@Produces("application/json")
public class ChangeStudentDetailsImpl implements ChangeStudentDetails {

 
@POST
  @Path
("/changeName")
 
public Student changeName(Student student) throws ServiceException {
   
if (student.getName().equals("Tom")) {
     
student.setName((new StringBuilder("HELLO ")).append(student.getName()).toString());
     
return student;
   
} else {
     
ServiceExceptionDetails serviceExceptionDetailsArray[] = new ServiceExceptionDetails[1];
      ServiceExceptionDetails serviceExceptionDetails =
new ServiceExceptionDetails();
      serviceExceptionDetails.setFaultCode
("100");
      serviceExceptionDetails.setFaultMessage
("Student Name is not correct");
      serviceExceptionDetailsArray
[0] = serviceExceptionDetails;
      throwException
(new ServiceException(serviceExceptionDetailsArray));
     
return null;
   
}
  }

 
public static void throwException(ServiceException serviceException) throws ServiceException {
   
ResponseBuilder builder = Response.status(Response.Status.NOT_ACCEPTABLE);
    builder.type
("application/json");
    builder.entity
(serviceException.getFaultDetails());
   
throw new WebApplicationException(builder.build());
 
}
}

Note; On the above ChangeStudentDetailsImpl class, implementing an interface is not necessity, you can create restful services without implementing an interface.

@Consumes annotation specifies, the request is coming from the client

you can specify the Mime type as @Consumes("application/xml"), if the request is in xml format

@Produces annotation specifies, the response is going to the client

you can specify the Mime type as @Produces ("application/xml"), if the response need to be in xml format

cxf.xml

CXF is using Spring internally, Finding classes by spring we need to add service implementation beans are added on "jaxrs:serviceBeans".

<?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"
    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">
    <import resource="classpath:META-INF/cxf/cxf.xml" />
    <jaxrs:server id="base" address="/rest">
        <jaxrs:serviceBeans>
            <ref bean="StudentService" />
        </jaxrs:serviceBeans>
    </jaxrs:server>
    <bean id="StudentService" class="com.student.ChangeStudentDetailsImpl" />
</beans>

web.xml

Change the web.xml file to find CXF servlet and cxf.xml

<?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">
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>WEB-INF/cxf.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>/*</url-pattern>
    </servlet-mapping>
</web-app>

Publishing CXF Restful Service

CXF REST Exception Handling

Note

You can Find all the deployed JAX-WS/JAX-RS services you need to append 'services' at the end of the URL so URL will become following

http://localhost:8080/CXFRestfulTutorial/services

Deployed REST Web Service Using CXF

CXF REST Exception Handling

Note

you can also see CXF Restful Client in order to run this restful service

When you invoke the above client with student name as Tom, you will get the correct response

Output
Response From Server 

{"Student":{"name":"HELLO Tom"}}

When you invoke the above client with student name other than Tom, you will get an ServiceExceptionDetails

Output
Error From Server 

{"ServiceExceptionDetails":[{"faultCode":100,"faultMessage":"Student Name is not correct"}]}

 





3 Responses to "CXF REST Exception Handling"
  1. harry 2012-11-17 09:30:35.0
  1. admin 2012-11-18 09:30:35.0
  1. Joe 2012-11-19 09:30:35.0

Your email address will not be published. Required fields are marked *