gene b.
gene b.

Reputation: 11984

Spring ExceptionHandler for Caused By / Wrapped Exception

I couldn't find a good solution: In my Spring Boot app, as an @ExceptionHandler method, I need to define a handler not for a specific exception, but for any exception caused by a specific exception (i.e. a wrapped exception).

Example: Sometimes I get this:

org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Error while committing the transaction
    at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:541) ~[spring-orm-5.1.4.RELEASE.jar:5.1.4.RELEASE]
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:746) ~[spring-tx-5.1.4.RELEASE.jar:5.1.4.RELEASE]    
    ... 121 common frames omitted
Caused by: custom.TechRoleException: My custom TechRoleException
    at myapp.method1[..]
    at myapp.methodOuter[..]

My custom TechRoleException is an exception I throw inside some Hibernate EventListener's pre-update method, and the direct exception is that Persistence couldn't occur.

However, the following method that tries to use my custom exception is never reached:

@ControllerAdvice
public class GlobalExceptionHandler {

  @ExceptionHandler(TechRoleException.class)
  public String techRoleException(HttpServletRequest request, Exception ex) {
    System.out.println("Got here");
    return "home";
  }
}

Here's a similar thread where the answer is wrong and didn't answer this question: @ExceptionHandler for Wrapped Exception / getCause() in Spring

Upvotes: 2

Views: 3507

Answers (2)

gene b.
gene b.

Reputation: 11984

My final working answer is to handle a General Exception, and then use Apache ExceptionUtils.getRootCause() to detect the specific Caused-By I'm looking for within this general handler.

(Other specific Exceptions won't come to this method if they have their dedicated Handlers. But if there's no dedicated Handler, the exception will come here.) This is the only way to detect some target Caused-By.

@ExceptionHandler(Exception.class)
public String handleGeneralException(HttpServletRequest request, Exception ex) {

    Throwable rootCause = ExceptionUtils.getRootCause(ex);
    if (rootCause != null && "com.myapp.TechRoleException".equals(rootCause.getClass().getName())
    {       
        //... handle this Caused-By Exception here
        // ...
    }
    // All other exceptions that don't have dedicated handlers can also be handled below...
    // ...

}

Upvotes: 1

Failed
Failed

Reputation: 298

Maybe something like that?

@ExceptionHandler(Exception.class)
public String techRoleException(HttpServletRequest request, Exception ex) {
if(ex instanceof TechRoleException) {
    System.out.println("Got here");
    return "home";
} else {
    throw ex; //or something else
}
}

Upvotes: 1

Related Questions