Skip to content

Injecting Jersey request-scoped services for explicit bindings#87

Closed
vvondra wants to merge 1 commit into
HubSpot:masterfrom
vvondra:jersey_service_provider
Closed

Injecting Jersey request-scoped services for explicit bindings#87
vvondra wants to merge 1 commit into
HubSpot:masterfrom
vvondra:jersey_service_provider

Conversation

@vvondra
Copy link
Copy Markdown
Contributor

@vvondra vvondra commented Aug 21, 2016

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 baseInjector not having the JerseyGuiceModule installed. The child injectors used for AutoConfig, the one in getInjector and 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()) into baseInjector however breaks two existing tests.

Do you see any solution how to be able to inject Providers for Jersey-backed services?

private final Provider<SecurityContext> securityContextProvider;

@Inject
public JerseyService(Provider<SecurityContext> securityContextProvider) {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the injection I would like to make work

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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";
    }
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@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?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@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.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also depending on this.

Copy link
Copy Markdown
Contributor Author

@vvondra vvondra Jan 22, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@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)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

@vvondra vvondra force-pushed the jersey_service_provider branch from 7015b47 to 657268e Compare January 22, 2017 20:54
@vvondra vvondra changed the title Injecting Jersey request-scoped services Injecting Jersey request-scoped services for explicit bindings Jan 22, 2017
@vvondra vvondra force-pushed the jersey_service_provider branch from 657268e to 5fb8bd5 Compare January 22, 2017 21:20
@vvondra
Copy link
Copy Markdown
Contributor Author

vvondra commented Jan 22, 2017

@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 getInjector when all the necessary parts are ready.

Now it passes all the existing test cases in the project + my new one.

I've kept the addModule behaviour the same for backward compatibility.

@vvondra vvondra force-pushed the jersey_service_provider branch from 5fb8bd5 to 00b33cb Compare January 22, 2017 21:24
@vvondra vvondra closed this Jan 23, 2018
@vvondra vvondra deleted the jersey_service_provider branch January 23, 2018 18:56
@vvondra
Copy link
Copy Markdown
Contributor Author

vvondra commented Jan 23, 2018

Not going anywhere I suppose, and definitely out of my scope now, let's cleanup.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants