Spring ExceptionHandler для вызванного / обернутого исключения

Я не смог найти хорошего решения: в моем приложении Spring Boot в качестве метода @ExceptionHandler мне нужно определить обработчик не для конкретного исключения, а для любого исключения вызванный определенного исключения (т.е. обернутого исключения).

Пример: Иногда я получаю это:

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[..]

Мой пользовательский TechRoleException — это исключение, которое я выбрасываю внутри некоторого метода предварительного обновления Hibernate EventListener, и прямое исключение заключается в том, что Persistence не может произойти.

Однако следующий метод, который пытается использовать мое пользовательское исключение, никогда не достигается:

@ControllerAdvice
public class GlobalExceptionHandler {

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

Вот похожая тема, где ответ неверен и не ответил на этот вопрос: @ExceptionHandler для упакованного исключения/getCause() в Spring

ControllerAdvice не работает вообще или только в некоторых случаях?

kaba713 18.04.2019 09:41

Просто не работает для причинно-следственных связей, работает во всех остальных случаях

gene b. 18.04.2019 16:58
1
2
1 566
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Может быть, что-то в этом роде?

@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
}
}

Пожалуйста, не используйте Throwable в этом случае, если вы не хотите также перехватывать ошибки утверждения. Используйте Исключение.

kaba713 18.04.2019 09:35

Да, это работает. Мне даже не нужно «выбрасывать ex» для других, потому что другие выделенные обработчики для определенных исключений пропускают этот метод.

gene b. 18.04.2019 15:32

Я думал об этом, и я не знаю, как это работает: D Я не уверен, но я думаю, что мы должны использовать: if (ex.getCause() instanceof TechRoleException). Или, в конечном итоге, используйте метод библиотеки Apache - Throwable getRootCause (Throwable throwable) для получения rootCause, а затем проверьте instanceof. Как вы думаете? Если приложение выдает исключение (TransactionSystemException), как instanceof с TechRoleException может дать нам истину? Я думаю, что мы должны использовать ex.getCause() или эту библиотеку apache, чтобы найти основную причину. Проверьте это, если хотите

Failed 18.04.2019 15:59

Да, я использовал Apache ExceptionUtils getRootCause(). Я опубликую полный ответ.

gene b. 18.04.2019 16:58

Мой окончательный рабочий ответ — обработать исключение Общий, а затем использовать АпачиExceptionUtils.getRootCause() для обнаружения конкретных 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...
    // ...

}

Другие вопросы по теме