Reputation: 3682
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
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
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