Marten, first off, thanks very much for your replies. I really appreciate you taking time.
Ok, the use case is this... No views being rendered from any of the @Controller methods. Pure REST-style web services returning only data objects using @ResponseBody.
I have an abstract base class (WebApiResponse) for all my response objects. This base class contains a couple of common fields. All other subclasses (UserResponse below) add their own specific typed objects that will be in the method returns.
All I wanted to do is for this object to get serialized in the response body, and I wanted the HttpResponse status code to be set to the same code as the one in my serialized return object.
This is my controller method in question:
Code:
@RequestMapping (value="/{userId}", method = RequestMethod.GET)
public @ResponseBody WebApiResponse getUser (@PathVariable String userId)
{
UserResponse resp = null;
User u = realmSrv.getUser (userId);
if (u == null) {
String msg = "Unable to locate user by ID: " + userId;
resp = new UserResponse (HttpStatus.NOT_FOUND, msg);
} else {
resp = new UserResponse (u);
}
return resp;
}
My problem is that with the above mechanism, whether or not the user object is found, the HttpStatus is set to 200 since I'm not throwing any exceptions of any kind. I simply wanted the above UserResponse object to get serialized regardless, then I'd handle the setting the response status in an interceptor.
BTW, just to update you further... Based on your hint about @ResponseStatus, it led me to the docs for @ExceptionHandler that one can register in any controller. I gave it a try, and it achieves the effect I want, but not as clean as I would have liked it.
I wrote the following method in the same controller:
Code:
@ExceptionHandler
public String handleNotFoundException (NotFoundException ex, HttpServletResponse resp)
{
WebApiResponse webResp = ex.getWebResp ();
if (webResp != null) {
try {
resp.getWriter ().print (objMapper.writeValueAsString (webResp));
resp.setStatus (webResp.getHttpStatusCode ());
resp.setHeader ("Content-Type", "application/json");
} catch (Exception e) {
e.printStackTrace ();
}
}
return null;
}
then added the throwing of that exception to the previous getUser method:
Code:
if (u == null) {
String msg = "Unable to locate user by ID: " + userId;
resp = new UserResponse (HttpStatus.NOT_FOUND, msg);
throw new NotFoundException (resp);
} else {
resp = new UserResponse (u);
}
By doing this I've achieved the desired effect, but as you can see, the @ExceptionHandler method assumes Content-Type="application/json". I suppose I could inject the HttpRequest in there as well and examine the "Accept" header and use the proper object serializer to do the job.
So, my question is... Is this the correct Spring way of achieving the effect I'm looking for?
BTW, my NotFoundException is annotated with "@ResponseStatus (value = HttpStatus.NOT_FOUND)". But if I simply throw that exception WITHOUT declaring my own @ExceptionHandler, Tomcat writes to the response stream its standard 404/NOT FOUND page HTML page contents, which is very ugly and unusable as a standard data return.
Thanks again in advance for your help on this.
-Jac