Squarespace / jersey2-guice

Jersey 2.0 w/ Guice
92 stars 33 forks source link

Guice binding annotations not working #34

Open mumrah opened 8 years ago

mumrah commented 8 years ago

Copied from a Guice issue I previously filed (and closed): https://github.com/google/guice/issues/966#issuecomment-159332325

I have two modules that bind a set of strings like:

In FooModule:

Multibinder<String> fooThingsBinder = Multibinder.newSetBinder(binder(), String.class, Foo.class);
...
for(String foo: fooThings) {
  fooThingsBinder.addBinding().toInstance(foo);
}

And something similar in BarModule. Then elsewhere in the code I get these sets injected like:

public class FooResource(@Foo Set<String> fooThings, ...) { ... }

and something similar in BarResource.

What I'm seeing is that one of these sets non-deterministically gets injected to both resource classes. E.g., the foo things end up in FooResource and BarResource, or vice-versa.

I have tried using the @Named binding annotation as well, with the same results. I have another multi-binding that uses different types instead binding annotations, and it is working fine.

I'll try to come up with a test case later today/this week as time allows. I've worked around this for now by creating separate sub-types for the foo/bar things.

rkapsi commented 8 years ago

@mumrah: Do you have FooResource and BarResource bound in Guice?

@Override
protected void configure() {
  bind(FooResource.class);
  bind(BarResource.class);
}

I wonder if one of the resources is being initialized by HK2.

stevesea commented 8 years ago

I'm seeing what might a similar issue -- intermittently an incorrect binding is injected into a resource. (generally, I have to restart my application to get different behavior)

I'm trying to inject a JDBI DBI object into my resource. I have two annotated bindings for DBI Providers in my injector, one for a persistent database (@DbPersist), another for a in-memory database (@DbMem)


@Path("/mypath")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class MyResource {
    private final DBI dbi;
    @Inject
    public StoragePortResource(@DbMem DBI dbi) {
        this.dbi = dbi;
    }
}

Most of the time, the correct DBI is injected. Intermittently the wrong DBI is injected.

my stack: Dropwizard 0.8.5, dropwizard-guice 0.8.4, jersey2-guice 0.10, guice 4.0

I can debug where my DBI provider is being called, and from the callstack it looks like the call from jersey into the GuiceServiceLocator knows the source annotation on the constructor (@DbMem). But, 16+ calls later the call from GuiceBindingDescriptor into the Guice injector is asked for the DBI with the wrong binding annotation (@DbPersist)

(continued spelunking)

looking at it further... it seems like maybe it's happening during reflection, trying to get the constructor's parameters qualifiers...

(more spelunking)

in hk2-locator(2.4.0-b31), method org.jvnet.hk2.internal.Utilities#getConstructorInjectees is called, and has my @DbMem annotation as a paramAnnotation. It calls getParamInformation(paramAnnotation), and returns an empty set for the qualifiers.

(additional spelunking) and that investigation led me to this bug: https://github.com/Squarespace/jersey2-guice/issues/22

I'm still not sure why it sometimes works, and sometimes doesn't.

Adding @Qualifier to my @DbMem / @DbPersist annotations appears to make my resource behave consistently.

chriskessel commented 8 years ago

I'm having a very similar issue. I have two @Provides for the same class, both with a custom annotation. So one @Provides @Foo, the other @Provides @Bar. The providers are in different modules, but both modules are part of the same application.

However, sometimes it injects @Bar where @Foo is specified in the constructor! It's random and unpredictable. It's driving me crazy. I'm having to wrap things in small unique classes to get things to work. Near as I can tell, custom bindings are broken or have some race condition.

bar commented 8 years ago

@chriskessel I don't think anyone is injecting me :/

jylin commented 8 years ago

I'm seeing the same issue. I have an object annotated with @Named, and I get an instance of a random type each time. Also if I do @Named("something_i_didnt_bind"), it still gives me an instance, though random as well. Normally, that should throw an exception because I didn't bind anything with that name.

chriskessel commented 8 years ago

@jylin Are you using Dropwizard and Guice? I created this issue with the dropwizard-guice library, which is where the problem seems to lie, I think... https://github.com/HubSpot/dropwizard-guice/issues/91

bar commented 8 years ago

@chriskessel uhh?

jylin commented 8 years ago

@chriskessel No, I'm not using any framework. I just have a main function that initializes guice, jersey and this bridge.

jylin commented 8 years ago

I switched to using HK2 guice-bridge, and that seems to support Named injections better (though not perfect).

tusharbhasme commented 7 years ago

I am experiencing a very similar issue. I have a module that binds various BindingAnnotations with string values. In a jersey module, I am injecting one of those BindingAnnotations. Each time I start the server, in jersey module, I am getting any of the values from the various BindingAnnotation at random. These BindingAnnotations work fine in other modules of the application. It's just the jersey module that's facing this issue.