“Deep” Binding Annotations

29 views
Skip to first unread message

glenviewjeff

unread,
Jul 15, 2011, 10:27:27 AM7/15/11
to google...@googlegroups.com
Also posted on stack overflow

I have a class A that holds a class B like this:
class A {
private final B;
@Inject
A(B b) {
this.b = b;
}
}

interface B {}
class B1 {}
class B2 {}

I'm using annotations to construct different flavors of A classes that each hold the available B classes (@B1, @B2). The binding configurations look like this:

@Provides @B1 A provideAwithB1(B1 b1) {
return new A(b1)
}
@Provides @B2 A provideAwithB2(B2 b2) {
return new A(b2)
}

Right now the only module configuration I can come up with prevents me from making A's constructor private, and it seems more complex and verbose than need be. Is there a Guice extension or technique that I am unaware of that solves this problem more concisely? Ideally I'd write something like this instead:

bindChildren(A.class).annotatedWith(B1annotation.class).to(B1.class);
bindChildren(A.class).annotatedWith(B2annotation.class).to(B2.class);

Sam Berlin

unread,
Jul 15, 2011, 10:47:31 AM7/15/11
to google...@googlegroups.com
The typical way of doing something like this is using AssistedInject (http://code.google.com/p/google-guice/wiki/AssistedInject).  B would be an @Assisted parameter to A, and there'd be an AFactory class with a method that returns A and takes a B as a parameter.  Users would inject AFactory and construct their A by passing the appropriate B.  It's possible that you can fold that functionality into a specialized provider for annotated As, also.

(Alternately, you could use reflection to get at the constructor & call it, if that's your only limitation.)

sam

--
You received this message because you are subscribed to the Google Groups "google-guice" group.
To view this discussion on the web visit https://groups.google.com/d/msg/google-guice/-/DE3K51hdk_AJ.
To post to this group, send email to google...@googlegroups.com.
To unsubscribe from this group, send email to google-guice...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/google-guice?hl=en.

glenviewjeff

unread,
Jul 15, 2011, 12:57:00 PM7/15/11
to google...@googlegroups.com
Sam:

Thanks for the quick response!  I hadn't yet used AssistedInject, but unless I'm missing something, in this case AssistedInject appears to me to be overkill and substantially increases the complexity rather than decreasing complexity like I had hoped. 

As shown in the sample code, I have no other "automatic" injections, and am already manually injecting the necessary parameter as I would in the AssistedInject case.  Is there some benefit to using AssistedInject that I am missing?

Thanks,
Jeff

Sam Berlin

unread,
Jul 15, 2011, 1:10:18 PM7/15/11
to google...@googlegroups.com
Yah, exposing the factory definitely adds complexity for the user.  You can hide the complexity by continuing to use the @Provides methods and using the factory within those.  That leaves the complexity just within your code and it never leaks to the user.

As far as what AssistedInject gets you... the main benefit is that everything lives in Guice-land.  You get better error messages if things go wrong, checks for null injections, support for AOP on the assisted class, etc..

sam

--
You received this message because you are subscribed to the Google Groups "google-guice" group.
To view this discussion on the web visit https://groups.google.com/d/msg/google-guice/-/QuZRkxeF9VcJ.

Jared Bunting

unread,
Jul 15, 2011, 1:21:24 PM7/15/11
to google...@googlegroups.com
I might be misunderstanding the intent here, but would this FAQ solve the problem?

http://code.google.com/p/google-guice/wiki/FrequentlyAskedQuestions#How_do_I_build_two_similar_but_slightly_different_trees_of_objec

The way I read it, replace bind(Foot.class).toInstance(new Foot("leftie")); with bind(B.class).to(B1.class); and you have a solution.�

It makes the module setup slightly complex, but makes things really simple for the user.

On 07/15/2011 12:10 PM, Sam Berlin wrote:
Yah, exposing the factory definitely adds complexity for the user. �You can hide the complexity by continuing to use the @Provides methods and using the factory within those. �That leaves the complexity just within your code and it never leaks to the user.

As far as what AssistedInject gets you... the main benefit is that everything lives in Guice-land. �You get better error messages if things go wrong, checks for null injections, support for AOP on the assisted class, etc..

sam

On Fri, Jul 15, 2011 at 12:57 PM, glenviewjeff <glenvi...@gmail.com> wrote:
Sam:

Thanks for the quick response!� I hadn't yet used AssistedInject, but unless I'm missing something, in this case AssistedInject appears to me to be overkill and substantially increases the complexity rather than decreasing complexity like I had hoped.�

As shown in the sample code, I have no other "automatic" injections, and am already manually injecting the necessary parameter as I would in the AssistedInject case.� Is there some benefit to using AssistedInject that I am missing?


Thanks,
Jeff

--
You received this message because you are subscribed to the Google Groups "google-guice" group.
To view this discussion on the web visit https://groups.google.com/d/msg/google-guice/-/QuZRkxeF9VcJ.

To post to this group, send email to google...@googlegroups.com.
To unsubscribe from this group, send email to google-guice...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/google-guice?hl=en.

glenviewjeff

unread,
Jul 15, 2011, 4:59:00 PM7/15/11
to google...@googlegroups.com
Thanks very much Jared, I am pretty sure your solution is what I am looking for.  However, I while trying to implement this I was getting "binding already exists on a child injector" errors, which are proving too difficult to debug right now, so I'm going to come back to this later.
Reply all
Reply to author
Forward
0 new messages