Compatibilidad de Jersey 2 y Guice

La implementación de referencia de JAX-RS, Jersey, utiliza internamente una libreria de inyección de dependencias llamada HK2.

HK2 forma parte del ecosistema de Oracle / Glassfish igual que Jersey así que, en parte, tiene sentido. Sin embargo todo ese ecosistema no cuenta entre sus mejores cualidades con la interoperabilidad.

Uno de los problemas que he encontrado es la necesidad de trabajar junto con Guice, la libreria de inyección de dependencia de Google, que es la que suelo utilizar en mis proyectos.

Por suerte la gente de HK2 proporcionan un puente, guice-bridge, para trabajar junto con Guice: una pequeña libreria que permite la inyección en ambos sentidos por separado o de manera simultanea.

En mi caso concreto suelo necesitar sólo un sentido: inyectar objetos creados con Guice en recursos Jersey (y por tanto creados por HK2). Para ello tan sólo he de añadir un fragmento de código en el inicializador del API REST (la clase que hace el bootstrap de Jersey).

@ApplicationPath("api")
public class ApiRest extends ResourceConfig {  
    private static final Logger log = LoggerFactory.getLogger(ApiRest.class);

    @Inject
    public ApiRest(ServiceLocator serviceLocator, ServletContext servletContext) {
        log.debug("Inicialitzant Jersey.");
        packages("net.sargue.app.api.providers");
        packages("net.sargue.app.api");
        packages("org.glassfish.jersey.examples.multipart");
        register(MultiPartFeature.class);

        GuiceBridge.getGuiceBridge().initializeGuiceBridge(serviceLocator);
        GuiceIntoHK2Bridge guiceBridge = serviceLocator.getService(GuiceIntoHK2Bridge.class);
        Injector injector = (Injector) servletContext.getAttribute(Injector.class.getName());
        if (injector == null)
            throw new RuntimeException("Guice Injector not found");
        guiceBridge.bridgeGuiceInjector(injector);

        register(RolesAllowedDynamicFeature.class);
    }
}