Catching exceptions from a Jersey REST client thrown from a Spring MVC Rest service
exception, jakarta-ee, java, jersey, spring
Solution
`@ExceptionHandler` annotation 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:
@ExceptionHandler(value = {NullPointerException.class, AnotherException.class})
@ResponseBody
public String handleException1(Exception ex) {
return ex.getMessage();
}
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 adding
@ResponseStatus(value = HttpStatus.WHATEVER_CODE_YOU_WANT, reason = "Your message")`
annotation to your exception handler.
In case when http code returned by the call is greater or equal than `300`, jersey client throws `UniformInterfaceException`. 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 `UniformInterfaceException` and change the exception handler on the server so it returns `ServiceResponse` as response body, then you can get the reponse using:
ServiceResponse response = uniformInterfaceException.getResponse().getEntity(ServiceResponse.class);
Problem
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 `ServiceResponse` type. 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