Я не смог найти хорошего решения: в моем приложении 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
Просто не работает для причинно-следственных связей, работает во всех остальных случаях
Может быть, что-то в этом роде?
@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 в этом случае, если вы не хотите также перехватывать ошибки утверждения. Используйте Исключение.
Да, это работает. Мне даже не нужно «выбрасывать ex» для других, потому что другие выделенные обработчики для определенных исключений пропускают этот метод.
Я думал об этом, и я не знаю, как это работает: D Я не уверен, но я думаю, что мы должны использовать: if (ex.getCause() instanceof TechRoleException). Или, в конечном итоге, используйте метод библиотеки Apache - Throwable getRootCause (Throwable throwable) для получения rootCause, а затем проверьте instanceof. Как вы думаете? Если приложение выдает исключение (TransactionSystemException), как instanceof с TechRoleException может дать нам истину? Я думаю, что мы должны использовать ex.getCause() или эту библиотеку apache, чтобы найти основную причину. Проверьте это, если хотите
Да, я использовал Apache ExceptionUtils getRootCause(). Я опубликую полный ответ.
Мой окончательный рабочий ответ — обработать исключение Общий, а затем использовать Апачи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...
// ...
}
ControllerAdvice не работает вообще или только в некоторых случаях?