Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Empty Multibinder/MapBinder in Guice

In the process of building a plugin architecture using Guice's MapBinder, using Guice 3.0, I've run into the issue that Guice throws a CreationException when stripped of all modules, which is a viable configuration in this application. Is there a way to get Guice to inject an empty Map? Or, by extension, an empty set with Multibinder?

For example:

interface PlugIn {
    void doStuff();
}

class PlugInRegistry {
    @Inject
    public PlugInRegistry(Map<String, PlugIn> plugins) {
        // Guice throws an exception if OptionalPlugIn is missing
    }
}

class OptionalPlugIn implements PlugIn {
    public void doStuff() {
        // do optional stuff
    }
}

class OptionalModule extends AbstractModule {
    public void configure() {
        MapBinder<String, PlugIn> mapbinder =
            MapBinder.newMapBinder(binder(), String.class, PlugIn.class);
        mapbinder.addBinding("Optional").to(OptionalPlugIn.class);
    }
}
like image 538
ExFed Avatar asked Oct 18 '25 16:10

ExFed


1 Answers

In the documentation for MapBinder, it says:

Contributing mapbindings from different modules is supported. For example, it is okay to have both CandyModule and ChipsModule both create their own MapBinder, and to each contribute bindings to the snacks map. When that map is injected, it will contain entries from both modules.

So, what you do is, don't even add the entry in your basic module. Do something like this:

private final class DefaultModule extends AbstractModule {
  protected void configure() {
    bind(PlugInRegistry.class); 

    MapBinder.newMapBinder(binder(), String.class, PlugIn.class);
    // Nothing else here
  }
}

interface PlugIn {
  void doStuff();
}

Then, when you create your injector, if the additional modules exist, great! Add them. If they don't exist, then don't add them. In your class, do this:

class PlugInRegistry {
  @Inject
  public PlugInRegistry(Map<String, PlugIn> plugins) {
    PlugIn optional = plugins.get("Optional");
    if(optional == null) {
        // do what you're supposed to do if the plugin doesn't exist
    }
  }
}

Note: You have to have the empty MapBinder, or the Map injection won't work if there are no optional modules present.

like image 66
durron597 Avatar answered Oct 20 '25 07:10

durron597