1

Spring MVC REST Service and Client. I am looking for a better way to deal with errors!

I would like sometimes to return a errror message to the client or a status code but I dont know hiow. Can someone please tell me how to find a better way of dealing with errors and error messags for Spring REST Service and Client..

Here is my service code:

@RequestMapping(value = "/{name}", method = RequestMethod.GET)
@ResponseBody
public User getName(@PathVariable String name, ModelMap model) throws ResourceNotFoundException
{

    logger.debug("I am in the controller and got user name: " + name);

    /*

        Simulate a successful lookup for 2 users, this is where your real lookup code would go

     */

    if ("user2".equals(name))
    {
        return new User("User2 Real Name", name);
    }

    if ("user1".equals(name))
    {
        return new User("User1 Real Name", name);
    }

    throw new ResourceNotFoundException("User Is Not Found");
}


 @ExceptionHandler(ResourceNotFoundException.class)
 public ModelAndView handleResourceNotFoundException(ResourceNotFoundException ex)
{
    logger.warn("user requested a resource which didn't exist", ex);
    return new ModelAndView( jsonView, "error", "user requested a resource which didn't exist");
}

Now here is the code for the client:

Map<String, String> vars = new HashMap<String, String>();
vars.put("name", "user1");


/**
 *
 * Doing the REST call and then displaying the data/user object
 *
 */
RestTemplate restTemplate = new RestTemplate(commons);
restTemplate.getMessageConverters().add(new MappingJacksonHttpMessageConverter());
restTemplate.getMessageConverters().add(new StringHttpMessageConverter());

try
{
    User jsonreturn = restTemplate.getForObject("http://" + mRESTServer.getHost() + ":8080/json/{name}", User.class, vars);
    LOGGER.debug("return object:  " + jsonreturn.toString());
}
catch(Exception e)
{
    LOGGER.error("error:  " + e.toString());
}

I want to find so way to return a status code and message if the user is not found and plus my client code is getting this error:

org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON: Unrecognized field "error"
EoD
  • 357
  • 1
  • 3
  • 11
user2428795
  • 547
  • 6
  • 11
  • 26
  • Answer to this question might help you. http://stackoverflow.com/questions/5097134/spring-exceptionhandler-does-not-work-with-responsebody – digitaljoel Jun 07 '13 at 17:10
  • this will work out get for the server side but for the client I am now getting this message.. rg.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON: Unrecognized field "error" – user2428795 Jun 07 '13 at 18:28
  • in the catch on your client you can now parse your custom error JSON to an appropriate Java object representation and get what you want out of there and make appropriate decisions. – digitaljoel Jun 07 '13 at 20:26

2 Answers2

2

I've used this approach (with JSON/Jackson 2) to good success:

class ErrorHolder {
    public String errorMessage;
    public ErrorHolder(String errorMessage) {
        this.errorMessage = errorMessage;
    }
}

@ExceptionHandler
public @ResponseBody ResponseEntity<ErrorHolder> handle(ResourceNotFoundException e) {
    logger.warn("Teh resource was not found", e);
    return new ResponseEntity<ErrorHolder>(new ErrorHolder("Uh oh"), HttpStatus.NOT_FOUND);
}

Works with Spring 3.2.x at least.

Jukka
  • 4,583
  • 18
  • 14
  • You need to handle that at the client-side. Catch the resulting HttpClientErrorException (404) and react to it accordingly. – Jukka Jun 11 '13 at 13:20
  • I am trying to do a catch in the above code but I dont see how I can get the error message object at that point – user2428795 Jun 11 '13 at 13:36
  • Have a look at the HttpClientErrorException object, it has a method for getting the response body which contains the said error JSON. – Jukka Jun 11 '13 at 13:44
  • 1
    You might also consider implementing a custom ResponseErrorHandler in which case you could throw a custom HttpClientErrorException which would contain a method for getting the error object as a POJO, rather than as a JSON string (the body). – Jukka Jun 11 '13 at 13:49
  • I have to be missing something.. can you some me in the above client code?? please – user2428795 Jun 11 '13 at 13:58
  • HttpClientErrorException.getResponseBodyAsString – Jukka Jun 11 '13 at 16:36
0

i think the main point is how to deal with the right returned object and wrong object. in you client:

try
{
    User jsonreturn = restTemplate.getForObject("http://" + mRESTServer.getHost() + ":8080/json/{name}", User.class, vars);
    LOGGER.debug("return object:  " + jsonreturn.toString());
}
catch(Exception e)
{
    LOGGER.error("error:  " + e.toString());
}

when error happen,the return object is not User,so the messageConverter can not work well。

my solution is : on server side,use response.setStatus(HttpServletResponse.SC_BAD_REQUEST); then the client will not use messageConverter ,instand throw HttpClientErrorException or HttpServerErrorException ,the all have the response body,so you can call their e.getResponseBodyAsString() to get the error message.

EoD
  • 357
  • 1
  • 3
  • 11
user3023874
  • 53
  • 1
  • 3