简体   繁体   中英

Unable to nest custom Jersey providers

Jersey throws an exception when I try to reference one custom provider from another.

This test case

public class NestedProvidersTest extends JerseyTest {
    public NestedProvidersTest() throws TestContainerException {
        super(new LowLevelAppDescriptor.Builder(new DefaultResourceConfig(Resource.class, ParentProvider.class, ChildProvider.class)).build());
    }

    @Test public void test() {
        resource().path("/").get(String.class);
    }

    @Path("/") public static class Resource {
        @Context private Parent parent;

        @GET public String get() {
            return "hello";
        }
    }

    public interface Parent {}
    public interface Child {}

    @Provider public static class ParentProvider extends PerRequestTypeInjectableProvider<Context, Parent> {
        @Context private Child child;

        public ParentProvider() {
            super(Parent.class);
        }

        @Override public Injectable<Parent> getInjectable(ComponentContext ic, Context context) {
            return new Injectable<Parent>() {
                @Override public Parent getValue() {
                    return new Parent(){};
                }
            };
        }
    }

    @Provider public static class ChildProvider extends PerRequestTypeInjectableProvider<Context, Child> {
        public ChildProvider() {
            super(Child.class);
        }

        @Override public Injectable<Child> getInjectable(ComponentContext ic, Context context) {
            return new Injectable<Child>() {
                @Override public Child getValue() {
                    return new Child(){};
                }
            };
        }
    }
}

gives me the exception

Apr 05, 2013 7:02:41 PM com.sun.jersey.test.framework.spi.container.grizzly2.GrizzlyTestContainerFactory$GrizzlyTestContainer <init>
INFO: Creating low level grizzly2 container configured at the base URI http://localhost:9998/
Apr 05, 2013 7:02:41 PM com.sun.jersey.server.impl.application.WebApplicationImpl _initiate
INFO: Initiating Jersey application, version 'Jersey: 1.17.1 02/28/2013 12:47 PM'
Apr 05, 2013 7:02:43 PM com.sun.jersey.spi.inject.Errors processErrorMessages
SEVERE: The following errors and warnings have been detected with resource and/or provider classes:
  SEVERE: Missing dependency for field: private NestedProvidersTest$Child NestedProvidersTest$ParentProvider.child

com.sun.jersey.test.framework.spi.container.TestContainerException: com.sun.jersey.spi.inject.Errors$ErrorMessagesException
    at com.sun.jersey.test.framework.spi.container.grizzly2.GrizzlyTestContainerFactory$GrizzlyTestContainer.<init>(GrizzlyTestContainerFactory.java:106)
    at com.sun.jersey.test.framework.spi.container.grizzly2.GrizzlyTestContainerFactory.create(GrizzlyTestContainerFactory.java:77)
    at com.sun.jersey.test.framework.JerseyTest.getContainer(JerseyTest.java:345)
    at com.sun.jersey.test.framework.JerseyTest.<init>(JerseyTest.java:220)
    at NestedProvidersTest.<init>(NestedProvidersTest.java:22)
[snip]
Caused by: com.sun.jersey.spi.inject.Errors$ErrorMessagesException
    at com.sun.jersey.spi.inject.Errors.processErrorMessages(Errors.java:170)
    at com.sun.jersey.spi.inject.Errors.postProcess(Errors.java:136)
    at com.sun.jersey.spi.inject.Errors.processWithErrors(Errors.java:199)
    at com.sun.jersey.server.impl.application.WebApplicationImpl.initiate(WebApplicationImpl.java:770)
    at com.sun.jersey.api.container.ContainerFactory.createContainer(ContainerFactory.java:172)
    at com.sun.jersey.api.container.ContainerFactory.createContainer(ContainerFactory.java:134)
    at com.sun.jersey.test.framework.spi.container.grizzly2.GrizzlyTestContainerFactory$GrizzlyTestContainer.<init>(GrizzlyTestContainerFactory.java:102)
    ... 29 more

Am I doing something wrong, or is this behaviour not supported by Jersey?

More appropriate question should be: is this behavior not supported by Jersey 1.17?

I don't want to play guessing game, so I can only tell you that it can be done with Jersey 2.

Why it does not work in 1.17? Maybe because that Child dependency is not available during registration of providers.

Jersey 2 uses JSR-330 that is @Inject and all that and the way to do something you want to do is to use javax.inject.Provider .

Then you would use some kind of binder to register injectables but skipping all the details when you use Provider you don't expect T to be injected during registration. It will be retrieved later during Provider#get

Example from request scoped filter:

@Inject
private Provider<ResourceInfo> resourceInfo;

If I would like to do just these:

@Inject
ResourceInfo resourceInfo

then it would fail just like it failed for you.

If you can upgrade to 2 then I think it's worth it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM