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
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));
error
is being swallowedexception.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()
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);
}
}