I use Jersey 2 on a standalone Grizzly webserver. HK2 is used for CDI. I'd like to get a service with @PerLookup
-scope injected into a jersey ContainerRequestFilter
.
The service:
import org.glassfish.hk2.api.PerLookup;
import org.jvnet.hk2.annotations.Service;
@Service
@PerLookup
public class SessionManager {
[...]
}
The filter:
import javax.annotation.Priority;
import javax.inject.Inject;
import javax.ws.rs.Priorities;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.PreMatching;
import javax.ws.rs.ext.Provider;
@Provider
@Priority(Priorities.AUTHENTICATION)
@PreMatching
public class HttpSessionFilter implements ContainerRequestFilter {
@Inject
private javax.inject.Provider<org.glassfish.grizzly.http.server.Request> requestProvider;
@Inject
private SessionManager sessionManager;
[...]
}
My problem is this:
Question: how can I get the service injected per-request?
Update
The suggested approach using @Inject javax.inject.Provider<SessionManager> sessionManagerProvider
makes logical sense to me, but sessionManagerProvider.get()
returns null.
The hk2 serviceLocator is populated through the inhabitant-generator. It reports:
SystemDescriptor(
implementation=com.skalio.skaliopush.http.SessionManager
contracts={com.skalio.skaliopush.http.SessionManager}
scope=org.glassfish.hk2.api.PerLookup
qualifiers={}
descriptorType=CLASS
descriptorVisibility=NORMAL
metadata=
rank=0
loader=null
proxiable=null
proxyForSameScope=null
analysisName=null
id=31
locatorId=0
identityHashCode=494317290
reified=false)
And if I add the explicit binding, then it is also found like this:
SystemDescriptor(
implementation=com.skalio.skaliopush.http.SessionManager
contracts={com.skalio.skaliopush.http.SessionManager}
scope=org.glassfish.jersey.process.internal.RequestScoped
qualifiers={}
descriptorType=CLASS
descriptorVisibility=NORMAL
metadata=
rank=0
loader=org.glassfish.hk2.utilities.binding.AbstractBinder$2@78b729e6
proxiable=null
proxyForSameScope=null
analysisName=null
id=39
locatorId=0
identityHashCode=2041416495
reified=false)
2nd Update
I am using two service locators: One created explicitly, and populated through the HK2 inhabitant generator; and the one that Jersey creates. They are joined through a BridgingInjectionResolver.
@peeskillet's response works, when I add the explicit binding to Jersey's service locator. Adding the binding to the other service locator results in the above (sessionManagerProvider.get()
returns null).
It should work if you also use javax.inject.Provider<SessionMananger>
. The default scope is per lookup. But I guess you need to load it lazily.
Not sure how it differs functionally from RequestScoped
in Jersey. I thought that in a PerLookup
scope, it would get created twice if I inject it once into the filter and once into the resource class, but just testing right now, even in PerLookup
scope, it was still only created once for each request.
Alternatively, just to be sure, you may just want to bind it in a RequestScoped
if that is what you really want.
register(new AbstractBinder(){
protected void configure() {
bind(SessionManager.class).to(SessionManager.class)
.in(RequestScoped.class);
}
});