Module overrides don't work with MapBinder

1,390 views
Skip to first unread message

unguiculus

unread,
Jan 18, 2011, 2:27:39 AM1/18/11
to google-guice
I just discovered that bindings created with a MapBinder cannot be
overridden. Here's an example:

Module module1 = new AbstractModule() {
@Override
protected void configure() {
MapBinder<String, String> mapBinder =
MapBinder.newMapBinder(binder(), String.class,
String.class);
mapBinder.addBinding("foo").toInstance("foo1");
}
};

Module module2 = new AbstractModule() {
@Override
protected void configure() {
MapBinder<String, String> mapBinder =
MapBinder.newMapBinder(binder(), String.class,
String.class);
mapBinder.addBinding("foo").toInstance("foo2");
}
};

Guice.createInjector(Modules.override(module1).with(module2));


Executing the above code yields the following error in Guice 2.0 and
3.0-rc2:

Exception in thread "main" com.google.inject.CreationException: Guice
creation errors:

1) Map injection failed due to duplicated key "foo"
at com.google.inject.multibindings.MapBinder$RealMapBinder
$1.initialize(MapBinder.java:355)
at spielplatz.TestApp$2.configure(TestApp.java:31)

1 error
at
com.google.inject.internal.Errors.throwCreationExceptionIfErrorsExist(Errors.java:
416)
at
com.google.inject.internal.InternalInjectorCreator.injectDynamically(InternalInjectorCreator.java:
175)
at
com.google.inject.internal.InternalInjectorCreator.build(InternalInjectorCreator.java:
109)
at com.google.inject.Guice.createInjector(Guice.java:95)
at com.google.inject.Guice.createInjector(Guice.java:72)
at com.google.inject.Guice.createInjector(Guice.java:62)
at spielplatz.TestApp.main(TestApp.java:36)


Is this intended behavior? It looks like a bug to me, or am I missing
something?

Reinhard

Sam Berlin

unread,
Jan 18, 2011, 12:40:26 PM1/18/11
to google...@googlegroups.com
In Guice 2.0, Modules.override didn't play nicely with MapBinder/Multibinder at all -- any attempt to use a Multibinder/MapBinder in the 'override module' broke everything.

Guice 3.0 fixes this so that you *can* use MapBinder/Multibinder in the override module.  The behavior is limited to appending more info to the Map/Multibinder, though... it doesn't overwrite existing elements in the Map/Multibinder (mainly because it's not exactly clear how this would/should work).  You can emulate overriding the elements by using linked bindings and overriding the linked binding.  For example:
   core module:
         bind(Foo.class).toInstance(originalInstance);
         mapBinder.addBinding("foo").to(Foo.class);

 override module:
         bind(Foo.class).toInstance(otherInstance);

sam


--
You received this message because you are subscribed to the Google Groups "google-guice" group.
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.


unguiculus

unread,
Jan 20, 2011, 3:28:00 AM1/20/11
to google-guice
Thanks, Sam. I was not aware of the power of linked bindings. I think
documentation in this area could be improved. And please also document
that Multibindings cannot be overriden.

Reinhard
> > google-guice...@googlegroups.com<google-guice%2Bunsu...@googlegroups.com>
> > .

Rchytas

unread,
Jan 16, 2017, 6:52:14 PM1/16/17
to google-guice
I was wondering where does override go (Sorry if its a dumb question, I'm new to Guice). I've module deployed in web app as below -


import com.google.inject.multibindings.MapBinder;

public class ExternalDatabaseModule extends AbstractModule implements com.abc.Module {
  public void configure() {
    MapBinder<String, ExternalDatabaseConnection> m = MapBinder.newMapBinder(binder(), String.class, ExternalDatabaseConnection.class);
    m.addBinding("DBServer1).to(ExternalDBServer1Connection.class);
    m.addBinding("DBServer2").to(ExternalDBServer2Connection.class);
        
  }  
}

I then created another module and exported this to a jar file and then added this jar to tomcat/web-inf/lib. But my new binding did not get discovered

public class ABCExternalDatabaseModule extends AbstractModule implements
com.abc.Module {
@Override
public void configure() {
MapBinder<String, ExternalDatabaseConnection> m = MapBinder
.newMapBinder(binder(), String.class,
ExternalDatabaseConnection.class);
m.addBinding("DBServer3").to(ExternalDBServer3Connection.class);

}

public ABCExternalDatabaseModule() {
Guice.createInjector(Modules.override(
new ExternalDatabaseModule()).with(
new ABCExternalDatabaseModule()));
}

}

Stephan Classen

unread,
Jan 16, 2017, 7:19:14 PM1/16/17
to google...@googlegroups.com

If you only want to add server to the MapBinder then there is no need to overwrite modules.

From the JavaDoc [1]:
Contributing mapbindings from different modules is supported. For example, it is okay to have both CandyModule and ChipsModule both create their own MapBinder<String, Snack>, and to each contribute bindings to the snacks map. When that map is injected, it will contain entries from both modules.

[1] http://google.github.io/guice/api-docs/latest/javadoc/com/google/inject/multibindings/MapBinder.html

--
You received this message because you are subscribed to the Google Groups "google-guice" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-guice...@googlegroups.com.

To post to this group, send email to google...@googlegroups.com.

Rchytas

unread,
Jan 17, 2017, 12:39:43 PM1/17/17
to google-guice
Thanks
Reply all
Reply to author
Forward
0 new messages