I implemented a REST application using Spring MVC, Jersey and JAXB.
The client sends a ServiceRequest object which contains information about the request and receives a ServiceResponse object back with information about the response.
ServiceRequest
@XmlRootElement(name = "servicerequest")
public class ServiceRequest{
String serviceName = "AddUser"
public String getServiceName() {
return serviceName;
}
@XmlElement
public void setServiceName(String serviceName) {
this.serviceName = name;
}
}
ServiceResponse
@XmlRootElement(name = "serviceresponse")
public class ServiceResponse {
String responseCode;
public String getResponseCode() {
return responseCode;
}
@XmlElement
public void setResponseCode(String code) {
this.responseCode = name;
}
}
The client makes the call to the service using Jersey
ServiceClient
ClientConfig config = new DefaultClientConfig();
Client client = Client.create(config);
WebResource service = client.resource(RESOURCE_URL);
ServiceRequest request = new ServiceRequest();
ServiceResponse response = service.path("addUser").type(MediaType.APPLICATION_XML)
.accept(MediaType.APPLICATION_XML).entity(request).post(ServiceRequest.class);
On the server side, the service gets the request, handles it and returns a ServiceResponse object.
@RequestMapping(method = RequestMethod.POST,
value = "/addUser",headers="Accept=application/xml")
@ResponseStatus(HttpStatus.OK)
public @ResponseBody ServiceResponse addUser(@RequestBody ServiceRequest request) {
ServiceResponse response = new ServiceResponse();
//Handle request
//service.addUser();
response.setCode("200");
return response;
}
The controller class shown above makes a call to another service class to handle the request (service.addUser()). This service class can raise a number of exceptions.
What i am not sure of is how best to handle them. After googling around, i found that i can use an ExceptionHandler as shown below:
@ExceptionHandler(NullPointerException.class)
@ResponseBody
public String handleException1(NullPointerException ex)
{
return ex.getMessage();
}
I can have the controllers extend a base class that has the exception handler.
A couple of questions regarding the above approach:
- Do i have to create one handler for each exception type? There are so many exceptions that i need to handle so is it not possible to just have a generic handler for all exceptions?
- As my controller returns an object of type
ServiceResponse, what would be the object type that would be returned when an exception occurs? - The client expects to get an object of
ServiceResponsetype. How does it work if the response is an exception type?
And finally, i noticed that the ExceptionHanlder can only have a return type that is one of the following:
ModelAndView
Model
Map
View
String – interpreted as a view name
void, but only if the method writes directly to the response object
I thought i can create the ServiceResponse object in the ExceptionHandler and set the appropriate code and return the ServiceResponse object. This however is not possible if i cant return a ServiceResponse type in the excpetion handler.
Edit
I tried using the ExceptionHandler using a generic exception class as shown below
@ExceptionHandler(ServiceException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public @ResponseBody resolveServiceValidationException(ServiceException ex) {
System.out.println("In resolveServiceError");
ServiceResponse = new ServiceResponse();
response.setResponseException(ex.getMessage());
return response;
}
The exception is being caught but the ServiceResponse object is always null. All i get is the following message:
GET http://localhost:8080/myService/services/pingError returned a response status of 400 Bad Request
How can i access the response object when an exception is returned back?
Thanks
@ExceptionHandlerannotation can take an array of classes as a parameter, so you can create only one (or more) handlers for multiple exceptions. Change the method signature to take the common ancestor of all handled exception classes as a parameter. Something along the lines:In your case it’ll be
String, since you annotated it with@ResponseBody, but you probably want to change the returned http code to some error code. You can do it by addingannotation to your exception handler.
In case when http code returned by the call is greater or equal than
300, jersey client throwsUniformInterfaceException. You can catch and handle it. The response type doesn’t matter in this case, as the exception is thrown before the conversion.update
Once you get a hold of
UniformInterfaceExceptionand change the exception handler on the server so it returnsServiceResponseas response body, then you can get the reponse using: