Reputation: 21
Trying to setup a global custom exception handling mechanism which relies on @RestControllerAdvice which can handle exceptions.
@RestControllerAdvice** exception handler not firing at all. Here, I am using low-level client.
I had the following controller advice set up, to return an APIs contract for error conditions:
I tried to add below
@ExceptionHandler(value = { ResponseException.class })
public ApiErrorResponse noHandlerFoundException(Exception ex) {
LOG.error(ex.getCause().toString());
int status = ((ResponseException) ex).getResponse().getStatusLine().getStatusCode();
return new ApiErrorResponse(status, "<some message depending on status code>");
}
but seeing same result
pom.xml:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
</parent>
<properties>
<java.version>1.8</java.version>
</properties>
GlobalControllerExceptionHandler:
@RestControllerAdvice
public class GlobalControllerExceptionHandler extends ResponseEntityExceptionHandler{
private static final Logger LOG = Logger.getLogger(GlobalControllerExceptionHandler.class);
@ExceptionHandler(value = { ConstraintViolationException.class })
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ApiErrorResponse constraintViolationException(ConstraintViolationException ex) {
LOG.error(ex.getCause().toString());
return new ApiErrorResponse(400, "Bad Request");
}
@ExceptionHandler(value = { NoHandlerFoundException.class })
@ResponseStatus(HttpStatus.NOT_FOUND)
public ApiErrorResponse noHandlerFoundException(Exception ex) {
LOG.error(ex.getCause().toString());
return new ApiErrorResponse(404, "Resource Not Found");
}
@ExceptionHandler(value = { Exception.class })
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public ApiErrorResponse unknownException(Exception ex) {
LOG.error(ex.getCause().toString());
return new ApiErrorResponse(500, "Internal Server Error");
}
}
ApiErrorResponse:
public class ApiErrorResponse {
private int status;
private String message;
public ApiErrorResponse(int status, String message) {
this.status = status;
this.message = message;
}
public int getStatus() {
return status;
}
public String getMessage() {
return message;
}
@Override
public String toString() {
return new ToStringBuilder(this).append(status)
.append(message)
.toString();
}
}
The problem with this is when I use a 3rd party library to do something.
Upvotes: 1
Views: 13609
Reputation: 8371
It's due to the fact that you're trying to handle a nested exception via javax.validation.ConstraintViolationException;
ConstraintViolationException is a nested exception of org.springframework.transaction.TransactionSystemException;
Change the handler to @ExceptionHandler(TransactionSystemException.class)
TransactionSystemException is not an ideal resolution, but it works. This bug is fixed in the latest version of Spring Boot version: >= 2.4.0
In the link below, you can see how they unwrapped the ConstraintViolationException
Unwrap ConstraintViolationException from TransactionSystemException
Alternatively you can upgrade to:
// Gradle Config
plugins {
id 'org.springframework.boot' version '2.4.0'
id 'io.spring.dependency-management' version '1.0.10.RELEASE'
id 'java'
}
As of Spring Boot version: >= 2.4.0 you're now able to handle nested exceptions.
Upvotes: 1
Reputation: 15908
Make sure that your controller advice is being scanned.
For that, you can put your controller advice class in the inner package from the spring boot application main class so that spring boot will automatically scan all the inner packages.
Or
Try adding @EnableWebMvc
annotation to your configuration class.
Refer this example
Upvotes: 2