Multibinding of the same type in different modules

532 views
Skip to first unread message

Willi Schönborn

unread,
Jan 25, 2010, 1:51:25 PM1/25/10
to google...@googlegroups.com
Hi,

i have a Service (marker) interface which i wanted to use to multibind all
services using multibinding. What i did:

Multibinder.newSetBinder(binder(),
Service.class).addBinding().to(HibernateService.class);

and in other different (independent) modules something like:

Multibinder.newSetBinder(binder(),
Service.class).addBinding().to(BillingService.class);

etc.

No guice fails with the following exception:

A binding to java.util.Set<de.cosmocode.palava.core.service.Service> was
already configured at
de.cosmocode.palava.core.service.ServiceModule.configure(ServiceModule.java:40).
at
com.thelabelfinder.professional.services.SecondaryModule.configure(SecondaryModule.java:29)

Is it possible to bind multiple services from different and independent
modules
using multibinding without having to give the multibinder instance to
every module?

Greetings
Willi

Willi Schönborn

unread,
Jan 25, 2010, 1:53:32 PM1/25/10
to google...@googlegroups.com

I just found the following note in the wiki:

When you use PrivateModules with multibindings, all of the elements must
be bound in the same environment. You cannot create collections whose
elements span private modules. Otherwise injector creation will fail.

Looks like the cause to my problem, right?

Willi Schönborn

unread,
Jan 25, 2010, 1:56:17 PM1/25/10
to google...@googlegroups.com
Me again ;)

To talk in guice language:

What i might need is "Multibinding Robot Legs". Is that possible?
Dirty hacks would be acceptable ;)

Leigh Klotz

unread,
Jan 26, 2010, 5:41:36 PM1/26/10
to google-guice
I think you've got one problem and two possible solutions, each to
different problems. So once you figure out what problem you have you
can find the solution.

Problem 1:
Multiple modules have Services. One has a BillingService, and the
other has a HibernateService. One piece of code would like to @Inject
Set<Service> and get both of them.

Problem 2:
Multiple modules have Services. One has a BillingService, and the
other has a HibernateService. One piece of code would like to @Inject
Set<Service> and get just one of them (the "right" one). Another
piece of code would like to @Inject Set<Service> and get just one of
them (the other "right" one).

If you have Problem 1: it works for me just fine without passing the
multibinder instance around; perhaps it has to do with private
modules, as you point out.

If you have Problem 2: this is robot legs. You can see from the
problem statement that trying to figure out which one is "right" for
each module is a problem. If you're trying to use private modules to
scope it and that's not working for you, then you might try an
annotation. You can have a multibibder for @Named("left") and one for
@Named("right"), using the annotation arg to newSetbinder. Then, your
code does @Inject @Named("right") and will get the "right" one. For
better encapsulation, define your own annotation instead of using
@Named. Now your Set is scoped to the module that knows about that
annotation type; sadly, it's a public interface, but at least you can
see by imports (or perhaps even classpaths) who is using it.

Leigh.


Reply all
Reply to author
Forward
0 new messages