Reputation: 1059
Suppose I have the following classes defined:
public interface A {}
public class A1 implements A {}
public class A2 implements A {}
public class XServlet<T extends A> extends HttpServlet {
public XServlet(T delegate){}
}
Additionally in one of my Guice modules I have the foollowing bindings:
bind(A.class).annotatedWith(Names.named("a1")).to(A1.class);
bind(A.class).annotatedWith(Names.named("a2")).to(A2.class);
Now I need to create a ServletModule that defines two instances of "XServlet" with different arguments. For "/x" pattern I want it to use whatever is bound to A.class annotated with "a1", and for "/y" pattern whatever is bound to A.class and annotated with "a2". Something like:
serve("/x").with(???);
serve("/y").with(???);
What should be there instead of '???'? Is it possible at all?
Upvotes: 2
Views: 177
Reputation: 95614
Two problems here: One is varying the binding annotation of XServlet with the serve
method, and the other is varying the binding of A based on the annotation of XServlet.
The serve method half is pretty straightforward to solve: Manually create a Key
. This binds "/x" to @Named("a1") XServlet
.
serve("/x").with(Key.get(XServlet.class, Names.named("a1")));
The second half is known as the "robot legs problem" and is fixable using private modules:
install(new PrivateModule() {
@Override void configure() {
// These are only bound within this module, and are not visible outside.
bind(A.class).to(A1.class);
bind(XServlet.class).annotatedWith(Names.named("a1"));
// But you can expose bindings as you'd like.
expose(XServlet.class).annotatedWith(Names.named("a1"));
}
});
UPDATE: If the named bindings you mentioned before cannot be moved to the private module, you can always bind the non-annotated binding in the private module to the annotated binding in another module. The binding in the private module should look like this:
// Fulfill requests for an unannotated A by looking up @Named("a1") A,
// though @Named("a1") A is bound elsewhere.
bind(A.class).to(Key.get(A.class, Names.named("a1")));
If you're trying to bind a dozen of these, you may find it easier to create a private static function that looks like:
private static Module moduleForServlet(
final Class<? extends A> aClass, final String namedAnnotationString) {
return new PrivateModule() { /* see above */ };
}
Docs:
Upvotes: 1