Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I override Dropwizard's default resource exception handling?

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:

  1. Logs the stack trace (I use slf4j but I assume it would work for whatever)
  2. Returns a general purpose error response, which does not expose potentially privileged information about my server!

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?

like image 531
Richard Rast Avatar asked Dec 16 '16 21:12

Richard Rast


People also ask

How do you overcome exception handling?

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.

What is default exception handling?

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.

Can we show default exceptions to user?

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!


2 Answers

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!

like image 141
Richard Rast Avatar answered Sep 28 '22 03:09

Richard Rast


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

like image 38
sallu Avatar answered Sep 28 '22 02:09

sallu