Injecting Jersey request-scoped services for explicit bindings#87
Injecting Jersey request-scoped services for explicit bindings#87vvondra wants to merge 1 commit into
Conversation
| private final Provider<SecurityContext> securityContextProvider; | ||
|
|
||
| @Inject | ||
| public JerseyService(Provider<SecurityContext> securityContextProvider) { |
There was a problem hiding this comment.
This is the injection I would like to make work
There was a problem hiding this comment.
I am able to inject a Provider<SecurityContext> into the existing projects com.hubspot.dropwizard.guice.objects.JitDAO class. See changes below. Running the com.hubspot.dropwizard.guice.InjectedIntegrationTest works with this change to JitDAO. It will NOT work in other tests because this use case requires the com.google.inject.servlet.GuiceFilter which is only setup in InjectedIntegrationTest which uses the io.dropwizard.testing.junit.DropwizardAppRule to spin up a full server.
Let me know if you aren't able to duplicate this successful test.
package com.hubspot.dropwizard.guice.objects;
import com.google.common.base.Preconditions;
import javax.inject.Inject;
import javax.inject.Provider;
import javax.ws.rs.core.SecurityContext;
public class JitDAO {
private final Provider<SecurityContext> securityContextProvider;
@Inject
public JitDAO(Provider<SecurityContext> securityContextProvider) {
this.securityContextProvider = securityContextProvider;
}
public String getMessage() {
Preconditions.checkNotNull(securityContextProvider.get());
return "this DAO was bound just-in-time";
}
}
There was a problem hiding this comment.
@vvondra have you fixed your problem without this pull request changes? Just wondering because I have same issue(need to inject javax.ws.rs.ext.Provider), seems this pull request won't be merged?
There was a problem hiding this comment.
@pavelkokush I haven't fixed it so far.
I come back to this migration attempt every once in a while but so far I just included a patched GuiceBundle in my app code.
I'm trying to put together another minimal working example, but I don't have much time for it.
There was a problem hiding this comment.
@heldeen see my stacktrace, as you see, I'm actually using the DropwizardAppRule:
Some of the Guice Modules I register in GuiceBundle have a dependency to Provider<SecurityContext> and in the stack trace below you can see the error comes when I try to bind those services. They're initialized with the baseInjector, which doesn't have the JerseyGuiceModule enabled
I'm not using JIT binding and I can't, since there's no way to do Multibindings (https://github.com/google/guice/wiki/Multibindings) without explicit bindings
ERROR [2017-01-22 16:59:40,839] com.hubspot.dropwizard.guice.GuiceBundle: Exception occurred when creating Guice Injector - exiting
! com.google.inject.CreationException: Unable to create injector, see the following errors:
!
! 1) No implementation for javax.ws.rs.core.SecurityContext was bound.
! while locating com.google.inject.Provider<javax.ws.rs.core.SecurityContext>
! for the 2nd parameter of com.foodpanda.auth.access.AuthorizationChecker.<init>(AuthorizationChecker.java:33)
! while locating com.foodpanda.service.FooService
! for the 2nd parameter of com.foodpanda.service.FooService.<init>(FooService.java:46)
! at com.foodpanda.services.FooModule.configure(FooModule.java:49)
!
! 1 error
! at com.google.inject.internal.Errors.throwCreationExceptionIfErrorsExist(Errors.java:470)
! at com.google.inject.internal.InternalInjectorCreator.initializeStatically(InternalInjectorCreator.java:155)
! at com.google.inject.internal.InternalInjectorCreator.build(InternalInjectorCreator.java:107)
! at com.google.inject.Guice.createInjector(Guice.java:99)
! at com.hubspot.dropwizard.guice.InjectorFactoryImpl.create(InjectorFactoryImpl.java:13)
! at com.hubspot.dropwizard.guice.GuiceBundle.initInjector(GuiceBundle.java:122)
! at com.hubspot.dropwizard.guice.GuiceBundle.initialize(GuiceBundle.java:101)
! at io.dropwizard.setup.Bootstrap.addBundle(Bootstrap.java:148)
! at com.foodpanda.services.FooApplication.initialize(FooApplication.java:81)
! at io.dropwizard.testing.DropwizardTestSupport.startIfRequired(DropwizardTestSupport.java:185)
! at io.dropwizard.testing.DropwizardTestSupport.before(DropwizardTestSupport.java:112)
! at io.dropwizard.testing.junit.DropwizardAppRule.before(DropwizardAppRule.java:128)
! at org.junit.rules.ExternalResource$1.evaluate(ExternalResource.java:46)
! at org.junit.rules.RunRules.evaluate(RunRules.java:20)
! at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
! at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
! at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
! at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51)
! at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:237)
There was a problem hiding this comment.
Why is injector created in initialize instead of run? Only to support injecting into Bundles and ConfiguredBundles?
It's tricky already with the hack to setEnvironment on run, wouldn't it be more convenient to add a possibility to register modules which should be available during initialize and a separate list for when run runs? I already see this is part of #46
I think this would fix it, since then the modules that are failing for me would get initialized later when GuiceFilter is already registered together with the JerseyGuiceModule
7015b47 to
657268e
Compare
657268e to
5fb8bd5
Compare
|
@heldeen I've rewritten this PR a bit See what I meant above in this comment #87 (comment) I am not able to explicitly bind anything which relies on Provider (or something else provided by the JerseyModule), since the initialization happens too early. Now this PR adds a possibility to add Guice modules which are only added in the childInjector called in Now it passes all the existing test cases in the project + my new one. I've kept the |
5fb8bd5 to
00b33cb
Compare
|
Not going anywhere I suppose, and definitely out of my scope now, let's cleanup. |
In the PR merging support for DW 1.0 I commented that injecting a
Provider<SecurityContext>into our Guice bound services does not work anymore.#86 (comment)
It's due to the
baseInjectornot having theJerseyGuiceModuleinstalled. The child injectors used for AutoConfig, the one ingetInjectorand the one bridged to HK2 have it installed however.The code in the PR is more of an example of the set up we had (in the tests). The little hack installing
new JerseyGuiceModule(JerseyGuiceUtils.newServiceLocator())intobaseInjectorhowever breaks two existing tests.Do you see any solution how to be able to inject Providers for Jersey-backed services?