Трассировка стека исключений и причина, не сопоставленные с пользовательской глобальной обработкой исключений в Micronaut 2.5.8

#java #micronaut #micronaut-client #micronaut-rest

Вопрос:

Пытаюсь обработать глобальную обработку исключений в Micronaut, но трассировка стека исключений и причина не передаются обработчику исключений.

 public class GlobalException extends RuntimeException{
    public GlobalException(Throwable throwable){}
}



@Produces
@Singleton
@Requires(classes = {GlobalException.class, ExceptionHandler.class})
public class GlobalExceptionHandler implements ExceptionHandler<GlobalException, HttpResponse> {
    private static final Logger LOG = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    @Override
    public HttpResponse handle(HttpRequest request, GlobalException exception) {
        LOG.error(exception.getLocalizedMessage());
        LOG.error(exception.getCause().getCause().getMessage());
        Arrays.stream(exception.getStackTrace()).forEach(item ->  LOG.error(item.toString()));
        return HttpResponse.serverError(exception.getLocalizedMessage());
    }
}
 

Контроллер

 public Maybe<FindProductCommand> get(ProductSearchCriteriaCommand searchCriteria) {
        LOG.info("Controller --> Finding all the products");
        return iProductManager.find(searchCriteria)
                .onErrorResumeNext(error ->  { return Maybe.error(new GlobalException(error));});
    }
 

Фактическая ошибка не отображается в GlobalExceptionHandler. exception.getLocalizedMessage() является нулевым и LOG.error(exception.getCause().getCause().getMessage()) создает исключение нулевого указателя

Ответ №1:

GlobalException у конструктора есть Throwable параметр, и он проглатывает его (ничего с ним не делая). RuntimeException также имеет конструктор с одним аргументом , который принимает a Throwable , поэтому GlobalException(Throwable throwable) эффективно скрывается RuntimeException(Throwable throwable) .

Таким образом, когда ваш контроллер доберется до:

 return Maybe.error(new GlobalException(error));
 
  1. error проглатывается
  2. exception.getLocalizedMessage() возвращает null , так RuntimeException(Throwable throwable) как конструктор не может перейти throwable к Exception(Throwable throwable) ( RuntimeException расширяется Exception ) и GlobalException не переопределяет Exception#getLocalizedMessage()
  3. LOG.error(exception.getCause().getCause().getMessage()) бросает, NullPointerException потому exception.getCause() что возвращается null из error -за того, что его проглотили (из элемента списка 1 )

В заключение, либо не прячьтесь RuntimeException(Throwable throwable) в GlobalException , через:

 public class GlobalException extends RuntimeException {}
 

Или просто вызовите RuntimeException(Throwable throwable) из GlobalException(Throwable throwable) , через:

 public class GlobalException extends RuntimeException {
     public GlobalException(Throwable throwable) {
         super(throwable);
     }
}