Skip to content

Jersey extension installer

CoreInstallersBundle / JerseyProviderInstaller

Installs various jersey extensions, usually annotated with jersey @Provider annotation and installed via environment.jersey().register():

Supplier, ExceptionMapper, ValueParamProvider, InjectionResolver, 
ParamConverterProvider, ContextResolver, MessageBodyReader, MessageBodyWriter, 
ReaderInterceptor, WriterInterceptor, ContainerRequestFilter, 
ContainerResponseFilter, DynamicFeature, ApplicationEventListener, ModelProcessor

Recognition

Detects known jersey extension classes and classes annotated with jersey @jakarta.ws.rs.ext.Provider annotation and register their instances in jersey.

Extensions registered as singletons, when no explicit scope annotation is used. Behaviour could be disabled with option:

.option(InstallerOptions.ForceSingletonForJerseyExtensions, false)

Before guicey 5.7.0 it was required to annotate all extensions with @Provide, but now it is not required - extension would be recognized by implemented interface. But, if you prefer legacy behaviour then it could be reverted with:

.option(InstallersOptions.JerseyExtensionsRecognizedByType, false)

Special @Prototype scope annotation may be used to mark resources in prototype scope. It is useful when guice servlet support is disabled (and so @RequestScoped could not be used).

Due to specifics of HK2 integration, you may need to use:

  • @JerseyManaged to delegate bean creation to HK2
  • @LazyBinding to delay bean creation to time when all dependencies will be available
  • jakarta.inject.Provider as universal workaround (to wrap not immediately available dependency).

Or you can enable HK2 management for jersey extensions by default. Note that this will affect resources too and guice aop will not work on jersey extensions.

Priority

By default, all registered providers are qualified with @org.glassfish.jersey.internal.inject.Custom to prioritize them (be able to override dropwizard defaults). This mimics the default behaviour of manual registration with environment.jersey().register(...).

For example, when you register your own ExceptionMapper<Throwable> it would be used instead of default dropwizard one (due to prioritized qualification).

For more details see org.glassfish.jersey.internal.inject.Providers#getAllServiceHolders( org.glassfish.jersey.internal.inject.InjectionManager, java.lang.Class) which is used by jersey for providers loading.

Tip

Previously (<= 5.2.0) guicey were not qualifying providers and qualification may (unlikely, but can!) introduce behaviour changes on guicey upgrade (due to prioritized custom providers). In this case, auto qualification may be disabled with

.option(InstallerOptions.PrioritizeJerseyExtensions, false) 
to revert to legacy guicey behaviour. @Custom may be used directly in this case on some providers for prioritization.

@Priority annotation may be used for ordering providers. Value should be > 0 (but may be negative, just a convention). For example, 1000 is prioritized before 2000. See jakarta.ws.rs.Priorities for default priority constants.

Note

@Priority may work differently on @Custom qualified providers (all user providers by default) and unqualified (e.g. registered through hk module, like dropwizard defaults). Right now, qualified providers sorted ascending while unqualified sorted descending (due to different selection implementations, see getAllServiceHolders reference above). Probably a jersey bug.

Supplier

Warning

Supplier is used now by hk2 as a replacement to its own Factory interface.

If you were using AbstractContainerRequestValueFactory then use just Supplier<T> instead.

Any class implementing java.util.function.Supplier (or extending abstract class implementing it).

public class MySupplier implements Supplier<MyModel> {
    @Override
    public MyModel get() {
       ...    
    }   
}

Suppliers in essence are very like guice (or jakarta.inject) providers (Provider).

Warning

Previously, factories were used as auth objects providers. Now Function<ContainerRequest, ?> must be used instead:

@Provider
class AuthFactory implements Function<ContainerRequest, User> {

    @Override
    public User apply(ContainerRequest containerRequest) {
        return new User();
    }
}

ExceptionMapper

Any class implementing jakarta.ws.rs.ext.ExceptionMapper (or extending abstract class implementing it). Useful for error handling customization.

public class DummyExceptionMapper implements ExceptionMapper<RuntimeException> {

    private final Logger logger = LoggerFactory.getLogger(DummyExceptionMapper.class);

    @Override
    public Response toResponse(RuntimeException e) {
        logger.debug("Problem while executing", e);
        return Response.status(Response.Status.BAD_REQUEST)
                .type(MediaType.TEXT_PLAIN)
                .entity(e.getMessage())
                .build();
    }

}

Tip

You can also use ExtendedExceptionMapper as more flexible alternative. See example usage in dropwizard-views.

Tip

Default exception dropwizard mappers (registered in io.dropwizard.setup.ExceptionMapperBinder) could be overridden (see priority section) or completely disabled with server.registerDefaultExceptionMappers option.

ValueParamProvider

Any class implementing org.glassfish.jersey.server.spi.internal.ValueParamProvider (or extending abstract class implementing it).

public class AuthFactoryProvider extends AbstractValueParamProvider {

    private final AuthFactory authFactory;

    @Inject
    public AuthFactoryProvider(final jakarta.inject.Provider<MultivaluedParameterExtractorProvider> extractorProvider,
                               final AuthFactory factory) {
        super(extractorProvider, Parameter.Source.UNKNOWN);
        this.authFactory = factory;
    }

    @Override
    protected Function<ContainerRequest, User> createValueProvider(Parameter parameter) {
        final Auth auth = parameter.getAnnotation(Auth.class);
        return auth != null ? authFactory : null;
    }
}

InjectionResolver

Any class implementing org.glassfish.hk2.api.InjectionResolver (or extending abstract class implementing it).

class MyObjInjectionResolver implements InjectionResolver<MyObjAnn> {

    @Override
    public Object resolve(Injectee injectee) {
        return new MyObj();
    }

    @Override
    public Class<MyObjAnn> getAnnotation() {
        return MyObjAnn.class;
    }

    @Override
    public boolean isConstructorParameterIndicator() {
        return false;
    }

    @Override
    public boolean isMethodParameterIndicator() {
        return true;
    }
}

ParamConverterProvider

Any class implementing jakarta.ws.rs.ext.ParamConverterProvider (or extending abstract class implementing it).

public class FooParamConverter implements ParamConverterProvider {

    @Override
    public <T> ParamConverter<T> getConverter(Class<T> rawType, Type genericType, Annotation[] annotations) {
        if (Foo.class.isAssignableFrom(rawType)) {
            return (ParamConverter<T>) new FooConverter();
        }
        return null;
    }

    private static class FooConverter implements ParamConverter<Foo> {
        @Override
        public Foo fromString(String value) {
            return new Foo(value);
        }

        @Override
        public String toString(Foo value) {
            return value.value;
        }
    }
}

ContextResolver

Any class implementing jakarta.ws.rs.ext.ContextResolver (or extending abstract class implementing it).

public class MyContextResolver implements ContextResolver<Context> {

    @Override
    public Context getContext(Class type) {
        return new Context();
    }

    public static class Context {}
}

MessageBodyReader

Any class implementing jakarta.ws.rs.ext.MessageBodyReader (or extending abstract class implementing it). Useful for custom representations.

public class TypeMessageBodyReader implements MessageBodyReader<Type> {

    @Override
    public boolean isReadable(Class<?> type, java.lang.reflect.Type genericType, Annotation[] annotations, MediaType mediaType) {
        return false;
    }

    @Override
    public Type readFrom(Class<Type> type, java.lang.reflect.Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException, WebApplicationException {
        return null;
    }

    public static class Type {}
}

MessageBodyWriter

Any class implementing jakarta.ws.rs.ext.MessageBodyWriter (or extending abstract class implementing it). Useful for custom representations.

public class TypeMessageBodyWriter implements MessageBodyWriter<Type> {

    @Override
    public boolean isWriteable(Class<?> type, java.lang.reflect.Type genericType, Annotation[] annotations, MediaType mediaType) {
        return false;
    }

    @Override
    public long getSize(Type type, Class<?> type2, java.lang.reflect.Type genericType, Annotation[] annotations, MediaType mediaType) {
        return 0;
    }

    @Override
    public void writeTo(Type type, Class<?> type2, java.lang.reflect.Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException, WebApplicationException {
    }

    public static class Type {}
}

ReaderInterceptor

Any class implementing jakarta.ws.rs.ext.ReaderInterceptor (or extending abstract class implementing it).

public class MyReaderInterceptor implements ReaderInterceptor {

    @Override
    public Object aroundReadFrom(ReaderInterceptorContext context) throws IOException, WebApplicationException {
        return null;
    }
}

WriterInterceptor

Any class implementing jakarta.ws.rs.ext.WriterInterceptor (or extending abstract class implementing it).

public class MyWriterInterceptor implements WriterInterceptor {

    @Override
    void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException {
    }
}

ContainerRequestFilter

Any class implementing jakarta.ws.rs.container.ContainerRequestFilter (or extending abstract class implementing it). Useful for request modifications.

public class MyContainerRequestFilter implements ContainerRequestFilter {

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {
    }
}

ContainerResponseFilter

Any class implementing jakarta.ws.rs.container.ContainerResponseFilter (or extending abstract class implementing it). Useful for response modifications.

public class MyContainerResponseFilter implements ContainerResponseFilter {

    @Override
    public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
    }
}

DynamicFeature

Any class implementing jakarta.ws.rs.container.DynamicFeature (or extending abstract class implementing it). Useful for conditional activation of filters.

public class MyDynamicFeature implements DynamicFeature {

    @Override
    public void configure(ResourceInfo resourceInfo, FeatureContext context) {
    }
}

ApplicationEventListener

Any class implementing org.glassfish.jersey.server.monitoring.ApplicationEventListener (or extending abstract class implementing it).

public class MyApplicationEventListener implements ApplicationEventListener {

    @Override
    public void onEvent(ApplicationEvent event) {
    }

    @Override
    public RequestEventListener onRequest(RequestEvent requestEvent) {
        return null;
    }
}

ModelProcessor

Any class implementing org.glassfish.jersey.server.model.ModelProcessor (or extending abstract class implementing it).

public class MyModelProcessor implements ModelProcessor {

    @Override
    public ResourceModel processResourceModel(ResourceModel resourceModel, 
                                              Configuration configuration) {
        return resourceModel;
    }

    @Override
    public ResourceModel processSubResource(ResourceModel subResourceModel, 
                                            Configuration configuration) {
        return subResourceModel;
    }
}