简体   繁体   中英

Jersey - Register ExceptionMapper for Resource Methods

The question Exception Handling/Mapping for a particular class brought me to the question of how to register an ExceptionMapper to a particular resource Method .

I've tried to use a DynamicFeature like this:

DynamicFeature

@Provider
public class ExceptionMapperDynamicFeature implements DynamicFeature {

    @Override
    public void configure(final ResourceInfo resourceInfo, final FeatureContext context) {
        if(!resourceInfo.getResourceMethod().isAnnotationPresent(BindExceptionMapper.class))
            return;
        BindExceptionMapper bem = resourceInfo.getResourceMethod().getAnnotation(BindExceptionMapper.class);
        context.register(bem.mapper());
    }

}

Annotation

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface BindExceptionMapper {
    Class<? extends ExceptionMapper<?>> mapper() default WebApplicationExceptionMapper.class;
}

Resource

@GET
@Produces(MediaType.APPLICATION_JSON)
@BindExceptionMapper 
public Response test() {
    // do something that throws an exception
}

The result was disillusioning:

WARNING: The given contract (interface javax.ws.rs.ext.ExceptionMapper) of class ...WebApplicationExceptionMapper provider cannot be bound to a resource method.

Then I was searching for other possibilities without luck and ended up with a AspectJ implementation, which you can see as a part of my answer to the linked question above.

So the complete question:

Is there a way to successfully register an ExceptionMapper to a resource Method?

And of course,

  • if yes then: how?
  • if no then: why?

I'm curious about the answers :)

Please notice:
This question is not about to register an ExceptionMapper to a resource Class like...

public class ApplicationResourceConfig extends ResourceConfig {
    public ApplicationResourceConfig() {
        register(WebApplicationExceptionMapper.class, TestResource.class);
    }
}

and especially not about to register them at all.

It's not exactly what you asked, but it's the only way I've found to do something like you want:

@Provider
public class ErrorExceptionHandler implements ExceptionMapper<Throwable> {

    @Context
    private ResourceInfo resourceInfo;

    @Override
    public Response toResponse(final Throwable exception) {
        // this is an example of how to do something custom based on an annotation
        if(!resourceInfo.getResourceClass().isAnnotationPresent(SomeCustomAnnotation.class) && !resourceInfo.getResourceMethod().isAnnotationPresent(SomeCustomAnnotation.class))
            return null; // do some custom thing here based on your annotation, maybe call another ExceptionMapper not annotated with @Provider ?
        return Response.status(500).entity("ERROR").build();
    }
}

It works for my purposes anyway.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM