Suppose I've got an endpoint in Dropwizard, say
@GET
public Response foo() { throw new NullPointerException(); }
When I hit this endpoint it logs the exception and everything, which is great! I love it. What I love less is that it returns a big status object to the user with status: ERROR
(which is fine) as well as a gigantic stack trace, which I'm less excited about.
Obviously it's best to catch and deal with exceptions on my own, but from time to time they're going to slip through. Writing a try catch block around the entire resource every time is fine, but (a) it's cumbersome, and (b) I always prefer automated solutions to "you have to remember" solutions.
So what I would like is something that does the following:
I feel like there must be a built-in way to do this -- it already handles exceptions in a relatively nice way -- but searching the docs hasn't turned up anything. Is there a good solution for this?
The try-catch is the simplest method of handling exceptions. Put the code you want to run in the try block, and any Java exceptions that the code throws are caught by one or more catch blocks. This method will catch any type of Java exceptions that get thrown. This is the simplest mechanism for handling exceptions.
The default exception handler method, which is called as a final handler to take care of any exceptions not caught by the thread in the run() method. This is a method of the ThreadGroup class. The default exception handler is a method of the ThreadGroup class.
No, exceptions shouldn't be shown directly in error messages directly to the user, they're low level technical details and the user almost always wants something more understandable, even if it doesn't provide as much information as a stack trace would!
As alluded to by reek in the comments, the answer is an ExceptionMapper
. You'll need a class like this:
@Provider
public class RuntimeExceptionMapper implements ExceptionMapper<RuntimeException> {
@Override
public Response toResponse(RuntimeException runtime) {
// ...
}
}
You can do whatever logging or etc. you like in the toResponse
method, and the return value is what is actually sent up to the requester. This way you have complete control, and should set up sane defaults -- remember this is for errors that slip through, not for errors you actually expect to see! This is also a good time to set up different behaviors depending on what kind of exceptions you're getting.
To actually make this do anything, simply insert the following line (or similar) in the run
method of your main dropwizard application:
environment.jersey().register(new RuntimeExceptionMapper());
where environment
is the Environment
parameter to the Application's run
method. Now when you have an uncaught RuntimeException
somewhere, this will trigger, rather than whatever dropwizard was doing before.
NB: this is still not an excuse not to catch and deal with your exceptions carefully!
Add the following to your yaml file. Note that it will remove all the default exception mappers that dropwizard adds.
server:
registerDefaultExceptionMappers: false
Write a custom exception mapper as below:
public class CustomExceptionMapper implements ExceptionMapper<RuntimeException> {
@Override
public Response toResponse(RuntimeException runtime) {
// ...
}
}
Then register the exception mapper in jersey:
environment.jersey().register(new CustomExceptionMapper());
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With