I have a custom exception class annotated to return a given HttpStatus
:
@ResponseStatus(value=HttpStatus.BAD_REQUEST, reason=\"Invalid parameter\")
The "reason" is optional, so you can omit that and implements the abstract method public String reason passing the Error. Link: http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/web/bind/annotation/ResponseStatus.html
Since spring 5.0, you can use the ResponseStatusException
which is available
// From https://www.baeldung.com/spring-response-status-exception @GetMapping("/actor/{id}") public String getActorName(@PathVariable("id") int id) { try { return actorService.getActor(id); } catch (ActorNotFoundException ex) { throw new ResponseStatusException( HttpStatus.NOT_FOUND, "Actor Not Found", ex); } }
The easiest way to just set the response.setStatus()
. Easy and clean, you can change it to any status you want just instead of ex.getStatusCode()
add your code.
The return type is also of your choice, I'm using String b/c displaying this later.
By the way, the sendError
is not a good idea, because JBoss for instance is adding a lot of HTML to the response.
@ExceptionHandler(CommunicationException.class)
@ResponseBody()
public String handleCommunicationException(CommunicationException ex, HttpServletResponse response) throws IOException{
response.setStatus(ex.getStatusCode());
return ex.getStatusMessage();
}
The correct way is to introduce exception handler in your controller, then you can set response body of any status code:
@Controller
@RequestMapping(produces = MediaType.APPLICATION_JSON_VALUE)
public class SomeController {
...
@ExceptionHandler(BadRequestException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public @ResponseBody
Map<String,Object> handleIndexNotFoundException(BadRequestException bre,
HttpServletRequest request, HttpServletResponse resp) {
HashMap<String, Object> result = new HashMap<>();
result.put("error", true);
result.put("error_message", bre.getMessage());
return result;
}
}
Move over you don't have to pollute your model/exception classes with any Spring Web MVC annotations and dependency.
If you want to share the handler with all controller look into @ControllerAdvice.
You can use HttpServletResponse
's sendError
function to achieve that.
Here is an example of how to use it:
@RequestMapping(value = "some/url", method = RequestMethod.POST)
public void doAction(final HttpServletResponse response) throws IOException {
response.sendError(HttpStatus.BAD_REQUEST.value(), "custom error message");
}
If you omit the 'reason' attribute in the @ResponseStatus annotation on a custom exception,
@ResponseStatus(value = HttpStatus.CONFLICT) // 409
public class ChildDataExists extends RuntimeException {
...
then throw the exception
throw new ChildDataExists("Can't delete parent if child row exists.");
The exception's message comes through as the 'message' of the 'data' in the JSON output. It seems the 'reason' in the annotation overrides the custom behavior.