com.netflix.jersey.guice.providers.exception.ThrowableExceptionMapper Maven / Gradle / Ivy
The newest version!
package com.netflix.jersey.guice.providers.exception;
import java.util.Set;
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;
/**
* Jersey does not provide a mechanism for multiple exception mappers to exist for the same
* Exception type. Consequently it is not possible to implement context specific mapping
* customizations. This is needed for multi-tenant http servers with a single server context
* where each resource may wish to implement a different exception format.
*
* ThrowableExceptionMapper solves this by exposing a Guice multi-binding based 'plugin'
* architecture where a custom mapper can be added via simple Guice binding. When an
* exception occurs each CustomThrowableExceptionMapper is asked to determine if it
* can/should map the exception. A CustomThrowableExceptionMapper may inspect the request
* context (url, content type, etc...) as well as the actual exception and even stack trace
* to determine if it should map the exception and format the response. A
* DefaultThrowableExceptionMapper is called if no custom mapper is matched.
*
* Note that this should ONLY be used for the catch all exception mapping. Specific exceptions
* should be mapped by creating a specific {@code ExceptionMapper. }
*
* To enable a custom mapper just add a binding when bootstrapping guice.
*
* {@code
* new AbstractModule() {
* void configuration() {
* Multibinder mappers = Multibinder.newSetBinder(binder(), CustomThrowableExceptionMapper.class);
* mappers.addBinding().to(MyCustomExceptionMapper.class);
* }
* }
* }
*
*
* The default mapper may also be replaced via the following Guice binding.
*
*
* {@code
* new AbstractModule() {
* void configuration() {
* bind(DefaultThrowableExceptionMapper.class).to(MyDefaultThrowableExceptionMapper.class);
* }
* }
* }
*
*
* @see GsonExceptionMapper
* @author elandau
*
*/
@Provider
@Singleton
public class ThrowableExceptionMapper implements ExceptionMapper {
private final DefaultThrowableExceptionMapper defaultMapper;
private final Set mappers;
@Context
ThreadLocal request = new ThreadLocal() ;
@Inject
public ThrowableExceptionMapper(Set mappers, DefaultThrowableExceptionMapper defaultMapper) {
this.mappers = mappers;
this.defaultMapper = defaultMapper;
}
@Override
public Response toResponse(Throwable exception) {
HttpServletRequest request = this.request.get();
for (CustomThrowableExceptionMapper mapper : mappers) {
try {
if (mapper.canMap(exception, request)) {
return mapper.toResponse(exception);
}
}
catch (Throwable t) {
// OK to ignore
}
}
return defaultMapper.toResponse(exception);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy