javajerseyexceptionmapper

Jersey ExceptionMapper, rely on another ExceptionMapper


I have an ExceptionMapper which is part of a generic common library:

@Provider
public class GenericExceptionMapper implements ExceptionMapper<GenericException> {
    ...
}

Now, in my specific project, I have my own ExceptionMapper:

@Provider
public class SomeAdHocExceptionMapper implements ExceptionMapper<SomeAdHocException> {
    ...
}

I would like to convert the SomeAdHocException to GenericException and let GenericExceptionMapper be responsible for further processing. I tried the following two options, but both are not working:

[1] throw GenericException in SomeAdHocExceptionMapper:

@Provider
public class SomeAdHocExceptionMapper implements ExceptionMapper<SomeAdHocException> {
    public Response toResponse(SomeAdHocException e) {
        throw new GenericException(e);
    }
}

[2] inject GenericExceptionMapper into SomeAdHocExceptionMapper:

@Provider
public class SomeAdHocExceptionMapper implements ExceptionMapper<SomeAdHocException> {
    @Inject
    private GenericExceptionMapper mapper;

    public Response toResponse(SomeAdHocException e) {
        return mapper.toResponse(new GenericException(e));
    }
}

Both options are giving dependency excpetions.

How do I solve this?


Solution

  • Your first attempt won't work because only one exception mapper can be called for a single request. This is a safety feature to ensure that we don't run into infinite loops. Imagine XExceptionMapper throws a YException during processing and YExceptionMapper throws a XException during processing.

    Your second attempt won't work because the mapper isn't injectable. You could just instantiate it though.

    @Provider
    public class SomeAdHocExceptionMapper implements ExceptionMapper<SomeAdHocException> {
    
        private final GenericExceptionMapper mapper = new GenericExceptionMapper();
    
        public Response toResponse(SomeAdHocException e) {
            return mapper.toResponse(new GenericException(e));
        }
    }
    

    Assuming there is such a constructor and that the generic mapper doesn't require any injections of it's own. If it does, you could make the mapper injectable.

    public class AppConfig extends ResourceConfig {
        public AppConfig() {
            register(new AbstractBinder() {
                @Override
                protected void configure() {
                    bindAsContract(GenericExceptionMapper.class);
                }
            });
        }
    }
    

    Then you would be able to inject it.