mavendependency-injectionguicesisu

Custom Bindings with Eclipse Sisu/Guice in Maven Plugins


I've tried to add custom injection bindings to a Maven plugin, but apparently is doen't work. Somehow the "EagerSingleton"-annotated Class "MyModule" does not get initialized. But it is supposed to be initialized on container startup.

And just annotating the Module with @Named, as it is described in https://wiki.eclipse.org/Sisu/PlexusMigration#Custom_Bindings doen't work either.

The value of the "config" is not even null. It's just an empty string.

Mojo:

@Mojo(
    name = "echo",
    requiresProject = false
)
public class EchoMojo extends AbstractMojo {

    @Inject
    private Logger logger;

    @Parameter(property = "echo.message", required = true)
    private String message;

    @Inject
    @Config
    private String config;

    @Override
    public void execute() throws MojoExecutionException, MojoFailureException {
        logger.info(message + " / " + config);
    }
}

MyModule:

@Named
@EagerSingleton
public class MyModule extends AbstractModule {

    public MyModule() {
        System.out.println("MyModule::init");
    }

    @Override
    protected void configure() {
        bindConstant().annotatedWith(Config.class).to("My Value"); //$NON-NLS-1$
    }
}

Annotation:

@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD, ElementType.PARAMETER })
@BindingAnnotation
@Documented
public @interface Config {
}

Sourcecode of example: https://github.com/fripi89/maven-sisu-example


Solution

  • As @khmarbaise said, you seem to mix a lot of things in your example.
    I will try to first answer to the main question:
    Why your module is not wired up ? Because Maven has a classLoader hierarchy, and the Guice API is not exported by default to plugins (your module code is part of your plugin's classWorld)

    The documentation you were pointing was unfortunately wrong (see here). I have contributed by creating the following documentation: https://eclipse-sisu.github.io/sisu-project/plexus/index.html As you can see in this new documentation, there is a mention:

    Note that extensions does not have access to the API by default, you need to expose it yourself using the extension.xml config file. See the example here for more details.

    In order to modify the exposed APIs from maven core to plugins, you need to define a core extension, where you modify the exported APIs list using the extension.xml file.

    If you add the following file in the src/resources/META-INF/maven/ folder of a core extension:

    <extension>
      <exportedPackages>
        <exportedPackage>com.google.inject.*</exportedPackage>
        <exportedPackage>com.google.inject.binder.*</exportedPackage>
        <exportedPackage>com.google.inject.matcher.*</exportedPackage>
        <exportedPackage>com.google.inject.name.*</exportedPackage>
        <exportedPackage>com.google.inject.spi.*</exportedPackage>
        <exportedPackage>com.google.inject.util.*</exportedPackage>
        <exportedPackage>com.google.inject.internal.*</exportedPackage>
      </exportedPackages>
    </extension>
    

    Then activate this extension of yours in your project where you want to us the Guice API, It will be exposed to the plugins in the classLoader hierarchy, and your Guice module and your custom bindings will be picked up by SISU.

    If you want to read about Maven ClassLoader hierarchy, you can have a look to this blog post I have written which is a good entry point.


    UPDATE: You do not need to do that yourself anymore, just use this existing extension guice-exporter-maven-extension

    To activate it, simply put the content below in a file under .mvn/extension.xml file.

    <extensions xmlns="http://maven.apache.org/EXTENSIONS/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/EXTENSIONS/1.1.0 https://maven.apache.org/xsd/core-extensions-1.0.0.xsd">
      <extension>
        <groupId>com.homeofthewizard</groupId>
        <artifactId>guice-exporter-maven-extension</artifactId>
        <version>1.0.1-alpha</version>
      </extension>
    </extensions>