zakaria amine
zakaria amine

Reputation: 3682

Jersey 2 and Guice integration: where is .getServiceLocator() method

I am trying to migrate an existing Rest API based on Jersey 1.19 that uses Guice for DI to Jersey 2.26. I did not find much topics online dealing with the subject. The few I came across mention that Jersey 2 has its own DI mechanism called HK2 and that a bridge needs to be created between Guice and HK2, like mentioned in this repository here: https://github.com/caberger/jerseyguice and this article here http://www.aberger.at/en/blog/design/2016/11/17/bridge-jersey2-guice.html. The example uses Jersey 2.24 and in the DI logic here there is this statement:

ServletContainer servletContainer = (ServletContainer)container;
        ServiceLocator serviceLocator = container.getApplicationHandler().getServiceLocator();
        GuiceBridge.getGuiceBridge().initializeGuiceBridge(serviceLocator);
        GuiceIntoHK2Bridge guiceBridge = serviceLocator.getService(GuiceIntoHK2Bridge.class);
        Injector injector = (Injector) servletContainer.getServletContext().getAttribute(Injector.class.getName());
        guiceBridge.bridgeGuiceInjector(injector);

The problem is that the container.getApplicationHandler().getServiceLocator(); statement does not work anymore because the method .getServiceLocator() has been removed from Jersey 2.24 to 2.26 without any mention.

If anybody has any insight on how to do the same action or has a different idea on how to wire Guice to Jersey 2.26, that would be really appreciated.

Upvotes: 4

Views: 2024

Answers (2)

zakaria amine
zakaria amine

Reputation: 3682

I ended up not using jerseyguice bridge. I am posting an answer to my own question, maybe this this will help somebody. What I did is using com.google.inject.Inject in all the services, and the reason for this is that com.google.inject.Inject is not catched by HK2. For all the resource classes (annotated with @Path), I used javax.inject.Inject annotation. I kept my original Guice module, and then I created a bridge HK2 module:

  @ApplicationPath("/app")
public class Application extends ResourceConfig {

 public Application() {
    packages("com.app");
   Injector injector = Guice.createInjector(
     new MyOriginalGuiceModule(),
     new MyOriginalGuiceModule2());

   register(new HK2BridgeModule(injector));
  }
}

and then :

public class HK2BridgeModule extends AbstractBinder {

  private final Injector guiceInjector;

  public HK2BridgeModule(Injector guiceInjector) {
    this.guiceInjector = guiceInjector;
  }

  @Override
  protected void configure() {

    //Here are only the services needed by the resources, they are pulled from guice injector using the factory
    bindFactory(new ServiceFactory<Service1>(guiceInjector, Service1.class)).to(Service1.class);
    //...all your services here
  }

  //this will allow HK2 to pull dependencies from guice injector
  private static class ServiceFactory<T> implements Factory<T> {

    private final Injector guiceInjector;

    private final Class<T> serviceClass;

    public ServiceFactory(Injector guiceInjector, Class<T> serviceClass) {

      this.guiceInjector = guiceInjector;
      this.serviceClass = serviceClass;
    }

    @Override
    public T provide() {
      return guiceInjector.getInstance(serviceClass);
    }

    @Override
    public void dispose(T versionResource) {
    }
  }
}

It does the job.

Upvotes: 1

sasa
sasa

Reputation: 2443

You do not need Guice-HK2 bridge in order to integrate Guice and Jersey. Here is the web server implementation without bridge - https://github.com/sorskod/webserver.

However, if you still want to use bridge, note that starting from Jersey 2.26 you need to explicitly provide DI implementation, and currently only HK2 is fully supported. Maybe adding jersey-hk2 can you help rid of exceptions.

<dependency>
    <groupId>org.glassfish.jersey.inject</groupId>
    <artifactId>jersey-hk2</artifactId>
    <version>2.26</version>
</dependency>

Upvotes: 0

Related Questions