google / google/guice

Duplicate binding error without any annotation inside private module

Open
#1,290 0 comments 2 reactions 0 assignees View on GitHub
Dominant language
Java
Stars
12.7k
Forks
1.7k
Avg merge
11m
Merged PRs (30d)
2

Description

I stumbled across a weird problem when binding of the same class but with an annotation is available in a parent injector and is bound the same class without an annotation inside a submodule.

I could create a minimal reproducer that shows the problem. I suspect that it's a bug but I could have just missed something. Hopefully someone can shed light onto this problem.

This doesn't work:
```
@Test
public void withoutAnnotation() {
Key key = Key.get(B.class, Names.named("b"));
Injector injector = Guice.createInjector(new AbstractModule() {
@Override protected void configure() {
bind(key).to(B.class).in(Singleton.class); // <-- error says that B is already bound here
PrivateBinder childBinder = binder().newPrivateBinder();
childBinder.bind(Key.get(B.class)).to(key); // <-- and this would be the duplicate binding (no annotation!)
childBinder.bind(A.class);
childBinder.expose(A.class);
}
});
injector.getInstance(A.class);
}

public static class A {
@Inject
public A(B b) {}
}

public static class B {}
```
The error I get is:
```
Unable to create binding for com.test.GuiceTest$B. It was already configured on one or more child injectors or private modules bound at com.test.GuiceTest$1.configure(GuiceTest.java:26)
If it was in a PrivateModule, did you forget to expose the binding?
at com.test.GuiceTest$1.configure(GuiceTest.java:24)
```

If I add an annotation to `B` in `A`'s constructor and, of course, at the binding too then everything works as I expect.
```
@Test
public void withAnnotation() {
Key key = Key.get(B.class, Names.named("b"));
Injector injector = Guice.createInjector(new AbstractModule() {
@Override protected void configure() {
bind(key).to(B.class).in(Singleton.class);
PrivateBinder childBinder = binder().newPrivateBinder();
childBinder.bind(Key.get(B.class, Names.named("c"))).to(key); // <-- just added an annotation
childBinder.bind(A.class);
childBinder.expose(A.class);
}
});
injector.getInstance(A.class);
}

public static class A {
@Inject
public A(@Named("c") B b) {} // <-- just added an annotation here too
}

public static class B {}
```
In the former case the binding of `B` without an annotation is unique too but doesn't work. So I need to add an annotation to `A`'s constructor just to make this case work. Seems kind of odd to me.

Help appreciated. Thanks!

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.