dev@jersey.java.net

Re: [Jersey] GuiceComponentProviderFactory seems to eagerly support resources that are not explicitly bound in the given Injector.

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Wed, 23 Sep 2009 14:26:58 +0200

Hi,

What is happening is the implicit instantiation is kicking in, namely
Guice instantiates and Jersey manages.

See JavaDoc (last para):

   https://jersey.dev.java.net/nonav/apidocs/1.1.2-ea/contribs/jersey-guice/com/sun/jersey/guice/spi/container/servlet/package-summary.html


I did not realize there would be a use case of two independent
injectors being registered.

Do you know if it is possible to use some form of injector aggregation
in Guice? e.g. an injector that aggregates injector1 or injector2 ?

The GuiceComponentProviderFactory does support deferral to parent
injectors so if you make, say, injector2 a parent of injector1 it
should work.


Otherwise if this is not appropriate we will require a feature to turn
off the implicit instantiation.

Paul.

On Sep 23, 2009, at 2:12 AM, Jae Lee wrote:

> Hi all,
>
> I've came across the problem with GuiceComponentProviderFactory,
> when there are multiple of those registered in IoCResourceFactory.
> GuiceComponentProviderFactory will always support any resource
> classes that are not explicitly bound in the Injector that the
> ProviderFactory is constructed with, resulting in the first
> GuiceComponentProviderFactory will always be used to construct any
> resource.
>
> I've got two resources that are managed by two different Injectors,
> and thus two different GuiceComponentProviderFactories. However when
> IoCResourceFactory is constructed with those two
> GuiceComponentProviderFactories it always use the first one to
> construct any resources. And the test fails...
>
> any thought?
>
> public class GuiceComponentProviderFactoryForMultipleInjectorsTest {
> public static interface Message {}
>
> public static class HelloWorld implements Message {}
>
> public static class HelloMe implements Message {}
>
> @Path("mail/world")
> public static class MailWorld {
> private Message message;
>
> @Inject
> public MailWorld(Message message) {
> this.message = message;
> }
> }
>
> @Path("mail/me")
> public static class MailMe {
> private Message message;
>
> @Inject
> public MailMe(Message message) {
> this.message = message;
> }
> }
>
> private ResourceFactory buildResourceFactory(Injector...
> injectors) {
> ResourceConfig resourceConfig = new DefaultResourceConfig();
>
> List<IoCComponentProviderFactory> factories = new
> ArrayList<IoCComponentProviderFactory>();
> for(Injector injector : injectors) {
> factories.add(new
> GuiceComponentProviderFactory(resourceConfig, injector));
> }
>
> return new IoCResourceFactory(resourceConfig, new
> ServerInjectableProviderFactory(), factories);
> }
>
> @Test
> public void shouldSupportMultipleInjectors() {
> Injector injector1 = Guice.createInjector(new
> AbstractModule(){
> @Override
> protected void configure() {
> bind(Message.class).to(HelloWorld.class);
> bind(MailWorld.class);
> }
> });
>
> Injector injector2 = Guice.createInjector(new
> AbstractModule(){
> @Override
> protected void configure() {
> bind(Message.class).to(HelloMe.class);
> bind(MailMe.class);
> }
> });
>
> HttpContext httpContext = mock(HttpContext.class);
> ResourceComponentProvider componentProvider =
> buildResourceFactory(injector1,
> injector2).getComponentProvider(MailWorld.class);
> componentProvider.init(new AbstractResource(MailWorld.class));
>
>
> assertThat
> (((MailWorld)componentProvider.getInstance(httpContext)).message,
> is(HelloWorld.class));
>
> componentProvider = buildResourceFactory(injector1,
> injector2).getComponentProvider(MailMe.class);
> componentProvider.init(new AbstractResource(MailMe.class));
>
>
> assertThat
> (((MailWorld)componentProvider.getInstance(httpContext)).message,
> is(HelloMe.class));
> }
> }
>
>
>