I have a service implemented with Dropwizard and I need to dump incorrect requests somewhere.
I saw that there is a possibility to customise the error message by registering ExceptionMapper<JerseyViolationException>
. But I need to have the complete request (headers, body) and not only ConstraintViolations
.
You can inject ContainerRequest
into the ExceptionMapper
. You need to inject it as a javax.inject.Provider
though, so that you can lazily retrieve it. Otherwise you will run into scoping problems.
@Provider
public class Mapper implements ExceptionMapper<ConstraintViolationException> {
@Inject
private javax.inject.Provider<ContainerRequest> requestProvider;
@Override
public Response toResponse(ConstraintViolationException ex) {
ContainerRequest request = requestProvider.get();
}
}
In the ContainerRequest
, you can get headers with getHeaderString()
or getHeaders()
. If you want to get the body, you need to do a little hack because the entity stream is already read by Jersey by the time the mapper is reached. So we need to implement a ContainerRequestFilter
to buffer the entity.
public class EntityBufferingFilter implements ContainerRequestFilter {
@Override
public void filter(ContainerRequestContext containerRequestContext) throws IOException {
ContainerRequest request = (ContainerRequest) containerRequestContext;
request.bufferEntity();
}
}
You might not want this filter to be called for all requests (for performance reasons), so you might want to use a DynamicFeature
to register the filter just on methods that use bean validation (or use Name Binding).
Once you have this filter registered, you can read the body using ContainerRequest#readEntity(Class)
. You use this method just like you would on the client side with Response#readEntity()
. So for the class, if you want to keep it generic, you can use String.class
or InputStream.class
and convert the InputStream
to a String.
ContainerRequest request = requestProvider.get();
String body = request.readEntity(String.class);