I was able to find out what the problem was. One of the private
modules had a constructor-injected dependency to a concrete class
which was logically part of another private module. But since implicit
bindings are created for concrete classes, the other class from the
other private module became accidentally part of the this private
module.

Here a test to reproduce (also in http://pastebin.com/wt3YrkEx). The
problem was that Foo had a direct dependency to Bar. The solution that
I'll try is to create an interface for Bar, so that bindings are not
created implicitly for it, and then expose Bar's interface from the
other private module.


import com.google.inject.*;
import com.google.inject.name.Names;
import org.junit.Test;

import static org.junit.Assert.assertEquals;

public class PrivateModuleBugTest {

    @Test
    public void
private_modules_should_not_see_each_others_private_bindings() {
        Injector injector = Guice.createInjector(new FooModule(), new
BarModule());
        PrivateValue foo =
injector.getInstance(Key.get(PrivateValue.class, Names.named("Foo")));
        Bar bar = ((Foo) foo).bar;

        assertEquals("Foo", foo.getClass().getSimpleName());
        assertEquals("Foo-private", foo.getPrivateValue());
        assertEquals("Bar", bar.getClass().getSimpleName());
        assertEquals("Bar-private", bar.getPrivateValue()); //
actually returns "Foo-private"
    }
}

class FooModule extends PrivateModule {
    protected void configure() {
        bind(String.class).toInstance("Foo-private");
        bind(PrivateValue.class).to(Foo.class);

 
bind(PrivateValue.class).annotatedWith(Names.named("Foo")).to(Foo.class);
        expose(PrivateValue.class).annotatedWith(Names.named("Foo"));
    }
}

class BarModule extends PrivateModule {
    protected void configure() {
        bind(String.class).toInstance("Bar-private");
        bind(PrivateValue.class).to(Bar.class);

 
bind(PrivateValue.class).annotatedWith(Names.named("Bar")).to(Bar.class);
        expose(PrivateValue.class).annotatedWith(Names.named("Bar"));
    }
}

class Foo implements PrivateValue {
    private final String privateValue;
    public final Bar bar;

    @Inject
    public Foo(String privateValue, Bar bar) { // there is no warning
about this dependency to Bar
        this.privateValue = privateValue;
        this.bar = bar;
    }

    public String getPrivateValue() {
        return privateValue;
    }
}

class Bar implements PrivateValue {
    private final String privateValue;

    @Inject
    public Bar(String privateValue) {
        this.privateValue = privateValue;
    }

    public String getPrivateValue() {
        return privateValue;
    }
}

interface PrivateValue {
    String getPrivateValue();
}

-- 
You received this message because you are subscribed to the Google Groups 
"google-guice" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/google-guice?hl=en.

Reply via email to