javamavendependency-injectionplexus

Obtaining a Maven-Instance from Plexus


I'm currently attempting to get PlexusContainer to give me an initialized Maven-instance outside of a maven or eclipse execution context.

For that purpose I have following code (simplified):

PlexusContainer container = null;
try {
    container = new DefaultPlexusContainer();
    container.lookup(MavenResolutionTask.class).run();
    container.dispose();
} catch (Exception e) {
    e.printStackTrace();
}

// --- MavenResolutionTask.java:

@Component(role = MavenResolutionTask.class)
// ResolutionTask is an abstract class 
// implementing Runnable and extending CompletableFuture
public class MavenResolutionTask extends ResolutionTask {

    @Requirement
    private Maven maven;
}

Given that I had the standard plexus-component-metadata:process-classes plugin execution in my pom.xml I would've liked if this had worked like this.

Unfortunately running this code results in a LookupException with the following reason (stacktrace omitted for brevity):

WARN Sisu - Error injecting: org.apache.maven.project.DefaultProjectBuildingHelper
com.google.inject.ProvisionException: Guice provision errors:

1) No implementation for org.apache.maven.repository.RepositorySystem was bound.
  while locating org.apache.maven.project.DefaultProjectBuildingHelper

WARN Sisu - Error injecting: org.apache.maven.project.DefaultProjectBuilder
com.google.inject.ProvisionException: Guice provision errors:

1) No implementation for org.apache.maven.repository.RepositorySystem was bound.
  while locating org.apache.maven.project.DefaultProjectBuildingHelper
  at ClassRealm[plexus.core, parent: null]
  at ClassRealm[plexus.core, parent: null]
  while locating org.apache.maven.project.ProjectBuildingHelper
  while locating org.apache.maven.project.DefaultProjectBuilder

...

To remediate the missing bindings and prevent myself from having to go through the trouble of manually registering the complete dependency-graph of maven I attempted to merge the component descriptors included in my dependencies with the one generated for my application.

For that purpose I copied all dependencies into target/dependency and ran some shell-scripts to get a list of all dependencies that include a components.xml.
I pass these dependencies to an execution of dependency:unpack before then passing the extracted locations to the metadata-merger like so:

<plugin>
    <groupId>org.codehaus.plexus</groupId>
    <artifactId>plexus-component-metadata</artifactId>
    <version>1.7.1</version>
    <executions>
        <execution>
            <id>process-classes</id>
            <goals>
                <goal>generate-metadata</goal>
            </goals>
        </execution>
        <execution>
            <id>process-test-classes</id>
            <goals>
                <goal>generate-test-metadata</goal>
            </goals>
        </execution>
        <execution>
            <id>merge-descriptors</id>
            <phase>process-classes</phase>
            <goals>
                <goal>merge-metadata</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <output>${plexus.outputFile}</output>
        <descriptors>
            <descriptor>${plexus.outputFile}</descriptor>
            <!--./aether-transport-wagon-1.1.0.jar.d/META-INF/plexus/components.xml-->
            <descriptor>${project.build.directory}/extracted-sources/aether-transport-wagon/META-INF/plexus/components.xml</descriptor>
            <!--./maven-aether-provider-3.1.0.jar.d/META-INF/plexus/components.xml-->
            <descriptor>${project.build.directory}/extracted-sources/maven-aether-provider/META-INF/plexus/components.xml</descriptor>
            <!--./maven-artifact-manager-2.2.1.jar.d/META-INF/plexus/components.xml-->
            <descriptor>${project.build.directory}/extracted-sources/maven-artifact-manager/META-INF/plexus/components.xml</descriptor>
            <!--./maven-core-3.1.1.jar.d/META-INF/plexus/components.xml-->
            <descriptor>${project.build.directory}/extracted-sources/maven-core/META-INF/plexus/components.xml</descriptor>
            <!--./maven-model-builder-3.1.0.jar.d/META-INF/plexus/components.xml-->
            <descriptor>${project.build.directory}/extracted-sources/maven-model-builder/META-INF/plexus/components.xml</descriptor>
            <!--./maven-plugin-registry-2.2.1.jar.d/META-INF/plexus/components.xml-->
            <descriptor>${project.build.directory}/extracted-sources/maven-plugin-registry/META-INF/plexus/components.xml</descriptor>
            <!--./maven-profile-2.2.1.jar.d/META-INF/plexus/components.xml-->
            <descriptor>${project.build.directory}/extracted-sources/maven-profile/META-INF/plexus/components.xml</descriptor>
            <!--./maven-project-2.2.1.jar.d/META-INF/plexus/components.xml-->
            <descriptor>${project.build.directory}/extracted-sources/maven-project/META-INF/plexus/components.xml</descriptor>
            <!--./maven-settings-builder-3.1.1.jar.d/META-INF/plexus/components.xml-->
            <descriptor>${project.build.directory}/extracted-sources/maven-settings-builder/META-INF/plexus/components.xml</descriptor>
            <!--./org.eclipse.sisu.plexus-0.0.0.M2a.jar.d/META-INF/plexus/components.xml-->
            <descriptor>${project.build.directory}/extracted-sources/sisu-plexus/META-INF/plexus/components.xml</descriptor>
            <!--./plexus-cipher-1.4.jar.d/META-INF/plexus/components.xml-->
            <descriptor>${project.build.directory}/extracted-sources/plexus-cipher/META-INF/plexus/components.xml</descriptor>
            <!--./plexus-interactivity-api-1.0-alpha-6.jar.d/META-INF/plexus/components.xml-->
            <descriptor>${project.build.directory}/extracted-sources/plexus-interactivity-api/META-INF/plexus/components.xml</descriptor>
            <!--./plexus-sec-dispatcher-1.3.jar.d/META-INF/plexus/components.xml-->
            <descriptor>${project.build.directory}/extracted-sources/plexus-sec-dispatcher/META-INF/plexus/components.xml</descriptor>
            <!--./wagon-ssh-1.0.jar.d/META-INF/plexus/components.xml-->
            <descriptor>${project.build.directory}/extracted-sources/wagon-ssh/META-INF/plexus/components.xml</descriptor>
            <!--./wagon-ssh-common-1.0.jar.d/META-INF/plexus/components.xml-->
            <descriptor>${project.build.directory}/extracted-sources/wagon-ssh-common/META-INF/plexus/components.xml</descriptor>
        </descriptors>
    </configuration>
</plugin>

Unfortunately the error message persists So I guess my question is: How do I easily get a Maven instance from Plexus?


P.S. for completeness sake, I'm currently using the following dependencies:

[INFO] com.github.vogel612:dependency-analyzer:jar:0.0.1
[INFO] +- org.projectlombok:lombok:jar:1.16.16:compile
[INFO] +- commons-cli:commons-cli:jar:1.4:compile
[INFO] +- org.slf4j:slf4j-simple:jar:1.7.16:compile
[INFO] |  \- org.slf4j:slf4j-api:jar:1.7.16:compile
[INFO] +- org.codehaus.plexus:plexus-utils:jar:3.0.24:compile
[INFO] +- org.eclipse.aether:aether-api:jar:1.1.0:compile
[INFO] +- org.eclipse.aether:aether-util:jar:1.1.0:compile
[INFO] +- org.eclipse.aether:aether-impl:jar:1.1.0:compile
[INFO] |  \- org.eclipse.aether:aether-spi:jar:1.1.0:compile
[INFO] +- org.eclipse.aether:aether-connector-basic:jar:1.1.0:compile
[INFO] +- org.eclipse.aether:aether-transport-file:jar:1.1.0:compile
[INFO] +- org.eclipse.aether:aether-transport-http:jar:1.1.0:compile
[INFO] |  +- org.apache.httpcomponents:httpclient:jar:4.3.5:compile
[INFO] |  |  +- org.apache.httpcomponents:httpcore:jar:4.3.2:compile
[INFO] |  |  \- commons-codec:commons-codec:jar:1.6:compile
[INFO] |  \- org.slf4j:jcl-over-slf4j:jar:1.6.2:compile
[INFO] +- org.eclipse.aether:aether-transport-wagon:jar:1.1.0:compile
[INFO] |  \- org.apache.maven.wagon:wagon-provider-api:jar:1.0:compile
[INFO] +- org.apache.maven:maven-aether-provider:jar:3.1.0:compile
[INFO] |  +- org.apache.maven:maven-model:jar:3.1.0:compile
[INFO] |  +- org.apache.maven:maven-model-builder:jar:3.1.0:compile
[INFO] |  +- org.apache.maven:maven-repository-metadata:jar:3.1.0:compile
[INFO] |  +- org.eclipse.sisu:org.eclipse.sisu.plexus:jar:0.0.0.M2a:compile
[INFO] |  |  +- javax.enterprise:cdi-api:jar:1.0:compile
[INFO] |  |  |  +- javax.annotation:jsr250-api:jar:1.0:compile
[INFO] |  |  |  \- javax.inject:javax.inject:jar:1:compile
[INFO] |  |  +- com.google.guava:guava:jar:10.0.1:compile
[INFO] |  |  |  \- com.google.code.findbugs:jsr305:jar:1.3.9:compile
[INFO] |  |  +- org.sonatype.sisu:sisu-guice:jar:no_aop:3.1.0:compile
[INFO] |  |  |  \- aopalliance:aopalliance:jar:1.0:compile
[INFO] |  |  \- org.eclipse.sisu:org.eclipse.sisu.inject:jar:0.0.0.M2a:compile
[INFO] |  |     \- asm:asm:jar:3.3.1:compile
[INFO] |  \- org.codehaus.plexus:plexus-component-annotations:jar:1.5.5:compile
[INFO] +- org.apache.maven.wagon:wagon-ssh:jar:1.0:compile
[INFO] |  +- com.jcraft:jsch:jar:0.1.44-1:compile
[INFO] |  \- org.apache.maven.wagon:wagon-ssh-common:jar:1.0:compile
[INFO] |     \- org.codehaus.plexus:plexus-interactivity-api:jar:1.0-alpha-6:compile
[INFO] +- org.apache.maven:maven-core:jar:3.1.1:compile
[INFO] |  +- org.apache.maven:maven-settings:jar:3.1.1:compile
[INFO] |  +- org.apache.maven:maven-settings-builder:jar:3.1.1:compile
[INFO] |  +- org.apache.maven:maven-artifact:jar:3.1.1:compile
[INFO] |  +- org.apache.maven:maven-plugin-api:jar:3.1.1:compile
[INFO] |  +- org.codehaus.plexus:plexus-interpolation:jar:1.19:compile
[INFO] |  +- org.codehaus.plexus:plexus-classworlds:jar:2.5.1:compile
[INFO] |  \- org.sonatype.plexus:plexus-sec-dispatcher:jar:1.3:compile
[INFO] |     \- org.sonatype.plexus:plexus-cipher:jar:1.4:compile
[INFO] \- org.apache.maven:maven-project:jar:2.2.1:compile
[INFO]    +- org.apache.maven:maven-profile:jar:2.2.1:compile
[INFO]    +- org.apache.maven:maven-artifact-manager:jar:2.2.1:compile
[INFO]    |  \- backport-util-concurrent:backport-util-concurrent:jar:3.1:compile
[INFO]    +- org.apache.maven:maven-plugin-registry:jar:2.2.1:compile
[INFO]    \- org.codehaus.plexus:plexus-container-default:jar:1.0-alpha-9-stable-1:compile
[INFO]       +- junit:junit:jar:3.8.1:compile
[INFO]       \- classworlds:classworlds:jar:1.1-alpha-2:compile

Solution

  • It might have been helpful as a start to read the error message closely:

    The missing Component is org.apache.maven.repository.RepositorySystem and not org.eclipse.aether.RepositorySystem. While the former was already included, the latter is only present in org.apache.maven:maven-compat.

    Adding that to the dependencies (and including it's component definitions) fixes the immediate issue here. The intermediate result is currently a NoClassDefFoundError for Lorg/apache/maven/artifact/transform/ArtifactTransformationManager, which can be resolved by actually using the correct version of the dependency.

    As the final step now an instance of org.eclipse.aether.RepositorySystem and one instance of org.eclipse.aether.impl.RemoteRepositoryManager needs to be registered, which can be accomplished using code along the following lines:

    final ServiceLocator serviceLocator = MavenRepositorySystemUtils.newServiceLocator()
            .addService(RepositoryConnectorFactory.class, BasicRepositoryConnectorFactory.class)
            .addService(TransporterFactory.class, FileTransporterFactory.class)
            .addService(TransporterFactory.class, HttpTransporterFactory.class);
    
     // ...
    container.addComponent(serviceLocator.lookup(RepositorySystem.class)
        , RepositorySystem.class
        , "default");
    container.addComponent(serviceLocator.lookup(RemoteRepositoryManager.class)
        , RemoteRepositoryManager.class
        , "default");
    

    And now we can finally have a maven-instance.