-1

I'm just designing the exception handling for the REST interface on our Spring server.

As we will have multiple REST controllers, a central exception handling is desired. Spring offers the solution via @ControllerAdvice. This works well, except that I need to add a dependency to the MVC part of Spring, which I don't use elsewhere (If anybody knows a better solution without this dependency, I'd be more than happy).

My Idea is to create different exceptions like NotFoundException and BadRequestException. This exceptions can be used in a rest controller to intentionally provoke a certain error response with a Http status according to the exception. Also, any unchecked exception which will be caught within my @ControllerAdvice exception handler, will also re thrown such a custom http status exception.

It seems to me that this way, I can combine a central exception handling with well readable code. Are there any issues or thoughts about that?

Example of a REST controller

@RestController
@RequestMapping(ExampleRest.EXAMPLE_URI)
public class ExampleRest {

    public static final String EXAMPLE_URI = "/examples";

     @ Autowired
    private ExampleService exampleService;

     @ RequestMapping(value = "/{id}", method = GET)
    public ExampleDto get( @ PathVariable long id) {
        ExampleDto resultingExampleDto = exampleService.findById(id);
        if (resultingExampleDto != null) {
            return resultingExampleDto;
        }
        throw new NotFoundException(); //<- throwing the NotFound (404) exception
    }
}

Central error handler

@EnableWebMvc
@ControllerAdvice
public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {

//Exception handling
    @ExceptionHandler(value = {ConstraintViolationException.class})
    protected void handleConstraintViolation(ConstraintViolationException ex, WebRequest request) {
    throw new BadRequestException(ex.getMessage());
    }
//Exception handling
    @ExceptionHandler(value = IllegalArgumentException.class)
    protected void handleIllegalArgument(IllegalArgumentException ex, WebRequest request) {
    throw new BadRequestException(ex.getMessage());
    }

//actual request answer
    @ExceptionHandler(value = BadRequestException.class)
    protected ResponseEntity<Object> returnBadRequest(Exception ex, WebRequest request) {
    return handleExceptionInternal(ex, ex.getMessage(), new HttpHeaders(), HttpStatus.BAD_REQUEST, request);
    }

//actual request answer
    @ExceptionHandler(value = NotFoundException.class)
    protected ResponseEntity<Object> returnNotFound(Exception ex, WebRequest request) {
    return handleExceptionInternal(ex, ex.getMessage(), new HttpHeaders(), HttpStatus.NO_CONTENT, request);
    }

}
  • 2
  • @gnat I have to guess that you are referring that in certain cases I should return 204 and not 404. I'll change that. Otherwise this link does not answer much of my question. – Herr Derb Aug 28 '17 at 8:47
  • This's pettry much what I do in my developments. A centralized error handler who catch RuntimeExceptions (500 mostly), IllegalArgumentException (422),Exception (500) and my business exceptions (409). I have this set in several APIs in production and works fine. Remember that the response body and the httpstatus can be informed in ResponseEntiry<>. This should allow you to develop different scenarios for a given exception. – Laiv Aug 28 '17 at 17:52
2

I would generally avoid this approach. I tend to feel that the type of an exception should provide semantic information about the cause of the exception which should usually be in terms of your problem domain. By restricting exception types to the HTTP response codes that will be generated, you restrict the information provided by the exception to only the small portion of the domain information that has direct equivalence to HTTP error conditions.

Consider, for example, that there is a difference between a client ID not being found and a product ID -- you may well want to be able to handle those differently at the client end, and potentially log them differently too on the server side. Therefore it makes sense to have NoSuchClientException and NoSuchProductException, both of which would produce a 404 response when handled by the framework. A generic NotFoundException wouldn't be able to encode the difference between these in a useful fashion.

  • I think I'll get you. I actually still could work with a generic NotFoundException but I'll just extend it for each service or resource. This way I also could guarantee specific error messages provided. – Herr Derb Aug 28 '17 at 9:20
  • And the errorHandler still can map one method for the generic and as many as you deem necessary for the concrete exceptions. – Laiv Aug 28 '17 at 18:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.