1

Trying to handle the global exception handling in Micronaut, but the exception stack trace and cause are not thrown to the ExceptionHandler.

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());
    }
}

Controller

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));});
    }

The actual error are not mapped in GlobalExceptionHandler. exception.getLocalizedMessage() is null and LOG.error(exception.getCause().getCause().getMessage()) is throwing null pointer exception

San Jaisy
  • 15,327
  • 34
  • 171
  • 290

1 Answers1

2

GlobalException's constructor has a Throwable parameter and it's swallowing it (not doing anything with it). RuntimeException also has a single argument constructor that takes a Throwable, so GlobalException(Throwable throwable) is effectively hiding RuntimeException(Throwable throwable).

Thus when your controller gets to:

return Maybe.error(new GlobalException(error));
  1. error is being swallowed
  2. exception.getLocalizedMessage() returns null since the RuntimeException(Throwable throwable) constructor can't propogate throwable to Exception(Throwable throwable) (RuntimeException extends Exception) and GlobalException doesn't override Exception#getLocalizedMessage()
  3. LOG.error(exception.getCause().getCause().getMessage()) is throwing a NullPointerException because exception.getCause() is returning null due to error being swallowed (from list item 1)

In conclusion, either don't hide RuntimeException(Throwable throwable) in GlobalException, via:

public class GlobalException extends RuntimeException {}

Or just invoke RuntimeException(Throwable throwable) from GlobalException(Throwable throwable), via:

public class GlobalException extends RuntimeException {
     public GlobalException(Throwable throwable) {
         super(throwable);
     }
}
Jonny Henly
  • 4,023
  • 4
  • 26
  • 43