Parsed allover the whole internet, but can't figure out why this happens. I've got a simplest possible project (over jersey-quickstart-grizzly2 archetype) with one Jersey resource. I'm using Guice as DI because CDI doesn't want to work with Jersey either. The problem is that Guice can't resolve the class to use when injecting in Jersey's resources. It works great outside, but not with Jersey. Here is the Jersey resource:
import com.google.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
@Path("api")
public class MyResource {
private Transport transport;
@Inject
public void setTransport(Transport transport) {
this.transport = transport;
}
@GET
@Produces(MediaType.TEXT_PLAIN)
public String getIt() {
return transport.encode("Got it!");
}
}
Transport interface:
public interface Transport {
String encode(String input);
}
And it's realization:
public class TransportImpl implements Transport {
@Override
public String encode(String input) {
return "before:".concat(input).concat(":after");
}
}
Following Google's GettingStarted manual, I've inherited AbstractModule
and bound my classes like this:
public class TransportModule extends AbstractModule {
@Override
protected void configure() {
bind(Transport.class).to(TransportImpl.class);
}
}
I get injector in main()
with this, but don't really need it here:
Injector injector = Guice.createInjector(new TransportModule());
Btw, there's no problem when I try to do smth like this:
Transport transport = injector.getInstance(Transport.class);
Jersey 2 already has a DI framework, HK2. You can either use it, or if you want, you can use the HK2/Guice bridge to bride your Guice module with HK2.
If you want to work with HK2, at the most basic level, it's not much different from the Guice module. For example, in your current code, you could do this
public class Binder extends AbstractBinder {
@Override
public void configurer() {
bind(TransportImpl.class).to(Transport.class);
}
}
Then just register the binder with Jersey
new ResourceConfig().register(new Binder());
One difference is the the binding declarations. With Guice, it "bind contract to implementation", while with HK2, it's "bind implementation to contract". You can see it's reversed from the Guice module.
If you want to bridge Guice and HK2, it's little more complicated. You need to understand a little more about HK2. Here's an example of how you can get it to work
@Priority(1)
public class GuiceFeature implements Feature {
@Override
public boolean configure(FeatureContext context) {
ServiceLocator locator = ServiceLocatorProvider.getServiceLocator(context);
GuiceBridge.getGuiceBridge().initializeGuiceBridge(locator);
Injector injector = Guice.createInjector(new TransportModule());
GuiceIntoHK2Bridge guiceBridge = locator.getService(GuiceIntoHK2Bridge.class);
guiceBridge.bridgeGuiceInjector(injector);
return true;
}
}
Then register the feature
new ResourceConfig().register(new GuiceFeature());
Personally, I would recommend getting familiar with HK2, if you're going to use Jersey.
See Also:
Sorry, I forgot to add that to use the Guice Bridge, you need to dependency.
<dependency>
<groupId>org.glassfish.hk2</groupId>
<artifactId>guice-bridge</artifactId>
<version>2.4.0-b31</version>
</dependency>
Note that this is the dependency that goes with Jersey 2.22.1. If you are using a different version of HK2, you should make sure to use the same HK2 version that your Jersey version is using.
Yes, in my opinion the answer above is correct. A very good way is to bridge Guice to HK2. I am not 100% sure if it neccessary to create a new TransportModule in the code above. Indeed Guice registers its injector in the ServletContext with the class name of Injector anyway, so it can be fetched from there:
register(new ContainerLifecycleListener() {
public void onStartup(Container container) {
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);
}
public void onReload(Container container) {
}
public void onShutdown(Container container) {
}
});
Beside that it is not trivial how to configure the REST Endpoints in that way, so I wrote detailled blog about that here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With