-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Enable Jersey/Guice integration via HK2 Guice Bridge #2222
Comments
Reported by @jwells131313 |
Issue-Links: |
cowwoc said: To reiterate, here is what we had in Jersey 1.0:
In other words, we created a Guice injector first and initialized Jersey second. In Jersey 2.0 we have a circular reference. We need to initialize Injector before ServletContainer (otherwise @RequestScoped isn't initialized), but we need to initialize ServletContainer before Injector (otherwise we can't get a reference to ServiceLocator). |
vokiel said: If I just use the bridge as is and install a JpaPersistModule into the HK2 bridge, shouldn't it be able to inject an EntityManager from the Guice definition in my resources afterward? All that without having to use GuiceFilter & the Servlet plumbing of Guice? Isn't this just adaptation? What sm I missing or what's the status? |
cowwoc said: Development is being held up on the Jersey end of things, not HK2. Anyone wishing to help should take a look at how Spring integration was added in #2229 and try to replicate the technique for Guice. |
cowwoc said: 1. Add GuiceFilter and ServletContainer to web.xml:
2. Note that GuiceFilter must show up before ServletContainer.
4. Define a Guice module as follows:
5. ServletModule defines the "request" scope. GuiceFilter creates/destroys the scope on each incoming request. Let's begin by amending the documentation, and then we can follow up by adding a sample application and unit tests that mirror the Spring module. |
@jwells131313 said: |
reinert said: I don't like the idea of two DI containers working together. I would rather prefer just using Guice for managing every DI issue in my application. |
cowwoc said: I am beyond frustrated with this, having spent days trying to get it to work. @JWells, please contact me by email (cowwoc at bbs.darktech.org). I'd like to resolve this issue once and for all over chat. Playing tag over the issue tracker is not working out. |
cowwoc said: Now both Guice and HK2 are happy. This moves us in the right direction but it's still not a working solution: 1. There is no clean way to pass the root Injector into the Application class due to http://stackoverflow.com/q/19596592/14731. Currently I'm passing the variable using a public singleton, which is ugly. I will continue working to resolve this. |
jontro said: Would you mind trying out the solution outlined in https://java.net/jira/browse/HK2-121 ? |
cowwoc said:
The beauty of this is that Jersey would depend on JSR 330 instead of HK2 directly, and wouldn't need to manage any DI frameworks (as it did in 1.0). Jersey committers: what do you think of this proposal? |
cowwoc said: |
jontro said: Is it possible to reach a consensus on how this should move forward? |
bowenwr said: |
djxak said: For example I have a maven module in my application with JPA persistence classes. Entities and DAOs. DAOs implemented with Guice. They receive request-scoped EntityManager by Guice DI, have methods with @transactional annotation (by guice-persist) etc. Now I want to use this DAOs in my new REST module. For this I need to inject them to appropriate Jersey Resources. I don't want to rewrite all my DAOs with HK2. They already used in another UI module of my application. And HK2 doesn't provide functionality similar to guice-persist (request scoped UnitOfWork, @transactional interceptor). |
jitterted said: |
aldenquimby said: |
natros said: |
jkidd said: |
gmussi said: Why is Jersey so dependent of HK2? Shouldnt DI and Rest be two different things? Do I miss something here? My vote is for an official and well-maintained Guice support, as in the previous version |
superbull said: |
@mpotociar said: I can see two options how to get this feature in: |
cowwoc said: This issue cannot be solved without design-level changes in Jersey. Even if someone from the community were to contribute such a pull request, you wouldn't accept it (you implied as much in past mailing list discussion). There is no magical way to provide a Guice implementation that is completely abstracted away by HK2 without Jersey needing to be aware of it (the HK2 and Guice designs do not match and it causes the problems mentioned above). I already tried and gave up for this reason. |
sugis said: |
aythus said: I can argue, that with HK2 it is not Jersey anymore. This is a different product, and it is altogether misleading to call it Jersey 2. It would better be called HKersey. Marek, you need to admit to us and to yourself Jersey is dead, so that we can move one and you can continue developing HKersey. It is easier to migrate from Jersey to RestEasy than to HKersey. I am not being sarcastic, but your two points above are offensive to all the people on this thread. Lot's of people tried to find a way to integrate Guice with HKersey, and all failed due to tight coupling of HK2. So rather than admitting, that the way HK2 was built into Jersey was shambles you are coming with inadequate excuses. I don't even mention you suggesting Guice owners to contribute. Come on... Really, so it's Guice is guilty now. |
@jwells131313 said: Perhaps this is just a documentation issue? If there are specific features that do not work they should probably be broken out into separate bugs. |
sugis said: Say you were trying to port a small application from a Jersey 1.x+Guice codebase to Jersey2.x+Guice – the very first thing you'll find, a number of previously working constructor injections fail: Fails because HK2 and Guice don't have exactly the same bindings. (In fact, Guice expects the set of bindings to be immutable, whereas HK2 changes it dynamically.) Opened in 2013. Blocked on a Guice RFE, no real hope of getting the Guice team to change this, and even if they do it wouldn't be in a release until who-knows-when. Guice is infamously slow to evolve, or even release desperately-needed bugfix versions. Even if it does get fixed – you're still in the bizarre position of running two competing DI frameworks. There's going to be more problems. It's bizarre to me that Jersey even depends on HK2 so strongly. The whole point of JSR330 is to be DI-framework independent until the end consumer selects a product to use. But instead Jersey integrates HK2 to tightly that we suddenly can't use our existing Guice-based code – which we have a lot of time invested in and expertise with – we must instead start looking at replacing Guice, or fixing the subtly-broken bridge. Another option, that I (and sounds like cowwoc) personally think is better, would be if Jersey was separated from HK2 somewhat and could run inside of Guice. The OSGI features and whatnot that require dynamism are great, but a lot of people (very intentionally) don't run e.g. OSGI and prefer immutable service configurations. But making that separation is a lot of work, and we have day-jobs... RESTEasy offered us a path out, and we took it. I remember after spending a number of hours on this, I started to wonder how easy switching was. Turned out to be a relatively easy upgrade path. So we switched and stopped looking. Sounds like cowwoc did too (by moving to Pouch instead of Guice). Just reading through the tickets there's a ton of specialized Guice and HK2 knowledge both required to tackle the problem, so the number of people who could possibly contribute it is very small. Any work I did at least is now somewhere on the dusty shelf. Anyway sorry for the long-winded comment, was just hoping to better explain how I saw the situation. |
@jwells131313 said: Because of the essential failure of JSR-330 to be comprehensive enough to support any complex use cases JSR-299 (CDI) was created. It is a lot better and a lot more complete but has other issues such as only truly working in a container environment (which is being fixed). A lot (but certainly not all) of hk2 is based on the CDI model. So I would say that the whole point of JSR-330 was not really to allow for DI framework independence, or if it was, that it failed at that. The only purpose JSR-330 serves now is to provide a few (a very few!) common annotations and API that other specs can use (such as CDI). |
cowwoc said: I have a lot of respect for jwells and his work, but there is absolutely no technical way to get Jersey's current design to integrate perfectly against any other engine but HK2, and that is simply not okay. There is no technical reason for Jersey to bind itself so tightly against HK2. The arrangement we had in Jersey1 worked perfectly well. We aren't asking Oracle to support multiple DI engines. We are asking for Jersey to operate against an interface and allow the community to contribute different implementations of that interface. Final point: it is unreasonable for you to expect other DI engines (such as Guice) to add features whose main purpose is to help users to migrate away (use other engines). No one in their right mind would waste their time implementing this... Every DI engine I have ever encountered operates under two basic assumptions: 1. It is the only DI engine being used. Jersey's design needs to internalize these points and provide a solution that works accordingly. |
jhesse said: I define a JerseyModule for my apps:
This module defines the custom components and provides an easy way to add Jersey bindings to guice that are resolvable at injector creation time (by delegating to the service locator). The SecurityContext and UriInfo bindings are the only ones that I needed to port our existing code. The ServiceLocatorContainer is simple:
As is the InjectorContainer:
Then, finally, there is a JerseyServletContainer that binds the guice bridge and pieces everything together:
Then you just have to pass an injector supplier to the JerseyModule, which is pretty straight forward, eg:
I chose not to support the reload() method in the JerseyServletContainer, but it seems possible to do so. Everything should just work for an existing Jersey app that relies on guice if you follow a few rules:
That's pretty much it. If you need additional jersey bindings to be available to guice at module creation time, just create new ones that delegate to the ServiceLocator again. |
cowwoc said: Check if constructor injection works, especially if the constructor parameters contain some types that are injected by HK2 and others injected by Guice. |
jhesse said: This code base uses only constructor injection. Pretty much all of the objects injected in resources are regular, pojos defined in guice modules. The HK2 -> guice delegation works fine. The guice -> HK2 (ServiceLocator) delegation seems to work fine too as a means to provide bindings to guice for Jersey based services. |
cplummer said: |
jhesse said:
Then I configure it in a Jetty server like:
The webInjector is passed to the GuiceServletContextListener in my case. But, you should be able to create it from within a guice context listener implementation, as well. |
This issue was imported from java.net JIRA JERSEY-1950 |
The HK2 Guice Bridge is available, but there may be more work needed in Jersey in order to enable it.
Affected Versions
[2.0]
The text was updated successfully, but these errors were encountered: