Reputation: 1212
I'm attempting to use Guice to inject dependencies into a ContainerRequestFilter that is being registered via a DynamicFeature. I also need Jersey to inject the HttpServletRequest and I am currently attempting to do this via @Context. This is in a Dropwizard app.
My end goal is to have an AuthenticationFilter that is applied to specific Resources via a DynamicFeature. My AuthenticationFilter has a few dependencies that must be injected and it also needs access to the HttpServletRequest to do its job. This is part of a Dropwizard project and the pattern is based on Dropwizard's AuthDynamicFeature and AuthFilter but modified to support injection.
So my AuthenicationFilter looks like this:
public class AuthFilter implements ContainerRequestFilter {
@Context
private HttpServletRequest httpServletRequest;
@Context
private HttpServletResponse httpServletResponse;
@Inject
private InjectableResource injectableResource;
public void filter(ContainerRequestContext requestContext) throws IOException {
// Do Auth
}
}
And my DynamicFeature looks like this:
public class InjectableAuthDynamicFeature implements DynamicFeature {
// Have tried multiple methods to register fitlers: using Injector,
// using Provider and using the normal Class
@Inject
private Provider<AuthFilter> authFilterProvider;
@Inject
private Injector injector;
@Override
public void configure(ResourceInfo resourceInfo, FeatureContext context) {
// Logic to decide on registering of filter followed by one of the
// following depending on injection method:
context.register(AuthFilter.class);
context.register(this.injector.getInstance(AuthFilter.class);
context.register(this.authFilterProvider.get());
}
}
Unfortunately my AuthFilter never gets created/run with all of the dependencies that I need. If I use this.injector or this.authFilterProvider then my @Inject fields are correct by my @Context fields are not. My understanding is that this is because I'm registering an instance of the object and thus Jersey cannot manage it/inject it's @Context fields. However when I simply register the class my @Context fields are registered but my @Inject fields are not.
What registration/injection process can I do to ensure that both @Context and @Inject are properly filled at runtime?
One other piece of information potentially useful information: if I register a resource with the following line:
// AKA Dropwizard environment.jersey().register(...);
resourceConfig.register(this.injector.getInstance(MyResource.class));
And MyResource contains @Context members and @Inject members both the @Context/@Inject members are filled properly at runtime. So for some reason the Resource registration and Filter registration/management are behaving differently.
Any ideas/insights would be greatly appreciated.
Upvotes: 3
Views: 3396
Reputation: 36
Think i may have an answer here for you.
Are you registering your dynamicFeature with an @Provider annotation?
I believe what could be happening here is that HK2 attempts to register your DynamicFeature, (and thus your Filter), before you have setup the Guice-HK2 Bridge.
In order to work around this, i would attempt manually registering your feature, and remove the @Provider annotation from your Feature/Filter classes.
i.e.
// do your hk2 guice-bridge stuff before this
resourceConfig.register(InjectableAuthDynamicFeature.class)
I will update this later if it actually works.
--EDIT -- was completely wrong w/ above The reason why you are unable to see your guice dependencies in ContainerRequestFilter is because the visiblity of the GuiceScope class is LOCAL.
This basically means that only the parent serviceLocator will be able to correctly service guice dependencies. ContainerRequestFilter/Mappers/Features are all created by child serviceLocators, and thus do not have access to resolve the GuiceScope context.
In order to fix this I have forked hk2 guice-bridge and rewritten GuiceScope to use visibility NORMAL.
Here is a link to the code: https://github.com/hk2-project/hk2/blob/master/guice-bridge/src/main/java/org/jvnet/hk2/guice/bridge/internal/GuiceScopeContext.java#L58
I don't know why anyone hasn't run into this issue, but it seems to limit the guice-bridge for no good reason.
Upvotes: 2