Reputation: 3382
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
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
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
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
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