Safari
Safari

Reputation: 3382

Custom Http Status Code in Spring

I am using Spring Boot and I am using Exception Classes thoughout my business logic code. One might look like this:

@ResponseStatus(HttpStatus.BAD_REQUEST)
public class ExternalDependencyException extends RuntimeException {

    public ExternalDependencyException() {
        super("External Dependency Failed");
    }
    public ExternalDependencyException(String message) {
        super(message);
    }

}

Well now there are Exception, where no predefined Http Status code is fitting, so I would like to use a status code like 460 or similar, which is still free, but the annotation ResponseStatus just accepts values from the enum HttpStatus. Is there a way to achieve an Exception class with a custom status code in the java spring boot environment?

Upvotes: 7

Views: 22341

Answers (4)

Axzial
Axzial

Reputation: 11

Yes, sendError() will use Spring default Template. You also need to use RestControllerAdvice instead of ControllerAdvice, then setStatus() will do the trick :)

@RestControllerAdvice
public class ExceptionService {

    @SneakyThrows
    @ExceptionHandler({CustomException.class})
    public CustomExceptionDto handle(HttpServletResponse resp, CustomException e) {
        resp.setStatus(e.getStatus().value()); //Using Spring HttpStatus
        return e.toDto();
    }

}

Upvotes: 1

Volodymyr Kret
Volodymyr Kret

Reputation: 1529

In general, @mdeterman answer is good, but I believe the right thing to do is setStatus to response, not sendError directly. Example:

@RestControllerAdvice
public class CustomExceptionHandler { 
    @ExceptionHandler(CustomException.class)
    public String handleException(Exception ex, HttpServletResponse response) {
        response.setStatus(460);
        return ex.getMessage();
    }
}

It seems to be possible only because of @RestControllerAdvice. @ControllerAdvice reset status code on view resolver level (for some strange reason). Also it is important to understand: any custom status code (not mentioned in org.apache.http.HttpStatus - RFC1945, RFC2616 , and RFC2518) will cause UnknownHttpStatusCodeException if client service is based on spring.

Upvotes: 3

MiguelPuyol
MiguelPuyol

Reputation: 439

In Spring Boot 2.1.8.RELEASE I did something similar but without using the HttpServletResponse:

@RestControllerAdvice
public class RestExceptionHandler {

    @ExceptionHandler(MyCustomException.class)
    @ResponseStatus(HttpStatus.NOT_ACCEPTABLE)
    public ApiErrorResponse handleTemplateEngineException(MyCustomException ex) {

        //custom ApiErrorResponse class
        return ApiErrorResponse.builder()
                .status(HttpStatus.NOT_ACCEPTABLE)
                .errorCode("NOT_ACCEPTABLE")
                .message(ex.getLocalizedMessage()).build();
    }
}

Upvotes: 0

mdeterman
mdeterman

Reputation: 4389

I'm not aware of a way to do this with @ResponseStatus.

One way to solve is this issue is with @RestControllerAdvice. This will allow you to customize how you return your Exception.

@RestControllerAdvice
public class WebRestControllerAdvice  {

    @ExceptionHandler(ExternalDependencyException.class)
    public String handleGitlabException(ExternalDependencyException ex, HttpServletResponse response) {
        try {
            response.sendError(460);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ex.getMessage();
    }
}

Upvotes: 10

Related Questions