Plugin installer

CoreInstallersBundle / PluginInstaller

Allows automatic gathering of multiple implementations of some interface into bindable set or map (dynamic plugins case).

Recognition

Detects classes annotated with guicey @Plugin annotation and bind them into set or map using guice multibindings mechanism.

Suppose you have plugin interface public interface PluginInterface.

Annotate plugin implementations with @Plugin:

@Plugin(PluginInterface.class)
public class PluginImpl1 implements PluginInterface

Now all implementations could be autowired as

@Inject Set<PluginInterface> plugins;

Warning

At least one implementation must be provided because otherwise guicey will not be able to register Set binding and guice startup will fail. If no plugins situation is possible, then you will have to manually register empty (default) plugins binding:

public class MyModule extends AbstractModule {    
    @Override
    protected configure() {
        Multibinder.newSetBinder(binder(), PluginInterface.class);
    }
}
Guicey can't register empty plugin set for you because it's impossible to know what plugins are you expecting.

Named plugins

Sometimes it's required to have named plugin mapping: to bind, Map instead of simple set. For example, when you have multiple authorization providers and each provider implementation must be registered with name.

Most likely, you would use enum for keys:

public enum PluginKey {
    FIRST, SECOND
}

Custom plugin annotation needs to be defined to use new keys:

@Plugin(PluginInterface.class)
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyPlugin {
    PluginKey value();
}

Note

Annotation itself is annotated with @Plugin, defining target plugin interface. Guicey will detect your custom annotation usage by analyzing its annotations.

Annotating plugin implementation:

@MyPlugin(PluginKey.FIRST)
public class PluginImpl1 implements PluginInterface

All plugins could be referenced as map:

@Inject Map<PluginKey, PluginInterface> plugins;

Note

It's not required to use enum as key. Any type could be set in your custom annotation. For example, string key could be used:

public @interface MyPlugin {
    String value();
}

@MyPlugin("first")
public class PluginImpl1 implements PluginInterface

@Inject Map<String, PluginInterface> plugins;

Warning

As with simple plugin bindings, at least one plugin must be registered so guice could create map binding. Otherwise, you need to manually declare empty (default) plugnis map binding:

MapBinder.newMapBinder(binder, keyType, pluginType);