I want to build a Maven project using the Maven Core (version 4.0.0-alpha-5) library. All I want right now is a working proof-of-concept to run the install
phase. However, I have not been able to create a working example and I cannot find a single tutorial or demonstration on the internet.
My main method is quite straightforward, it shouldn't require explanation:
public static void main(String[] args) throws Exception {
Injector injector = Guice.createInjector(new CompleteMavenModule());
Maven maven = injector.getInstance(Maven.class);
MavenExecutionRequestPopulator populator = injector.getInstance(MavenExecutionRequestPopulator.class);
DefaultMavenExecutionRequest request = new DefaultMavenExecutionRequest();
request.setPom(new File("C:\\Users\\lc70844\\eclipse-workspace\\TestProject\\pom.xml"));
request.setGoals(Arrays.asList("install"));
populator.populateDefaults(request);
MavenExecutionResult result = maven.execute(request);
if (result.hasExceptions())
result.getExceptions().stream().forEach(Throwable::printStackTrace);
}
When I run this, I get the following exception:
org.codehaus.plexus.component.repository.exception.ComponentLookupException: java.util.NoSuchElementException
role: org.eclipse.aether.repository.WorkspaceReader
roleHint: reactor
at org.codehaus.plexus.DefaultPlexusContainer.lookup(DefaultPlexusContainer.java:267)
at org.codehaus.plexus.DefaultPlexusContainer.lookup(DefaultPlexusContainer.java:255)
at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:246)
at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:228)
at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:153)
at com.nhbb.test.MavenTest.main(MavenTest.java:43)
Caused by: java.util.NoSuchElementException
at org.eclipse.sisu.inject.LocatedBeans$Itr.next(LocatedBeans.java:141)
at org.eclipse.sisu.inject.LocatedBeans$Itr.next(LocatedBeans.java:1)
at org.eclipse.sisu.plexus.DefaultPlexusBeans$Itr.next(DefaultPlexusBeans.java:76)
at org.eclipse.sisu.plexus.DefaultPlexusBeans$Itr.next(DefaultPlexusBeans.java:1)
at org.codehaus.plexus.DefaultPlexusContainer.lookup(DefaultPlexusContainer.java:263)
... 5 more
Going back to my main method, you'll notice the Guice.createInjector(new CompleteMavenModule())
. The CompleteMavenModule
class is a Guice module I setup to provide me with a DefaultMaven
instance:
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.inject.Named;
import javax.inject.Singleton;
import org.apache.maven.DefaultMaven;
import org.apache.maven.Maven;
import org.apache.maven.WorkspaceReaderModule;
import org.apache.maven.artifact.factory.ArtifactFactory;
import org.apache.maven.artifact.factory.DefaultArtifactFactory;
import org.apache.maven.artifact.handler.ArtifactHandler;
import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
import org.apache.maven.artifact.handler.manager.DefaultArtifactHandlerManager;
import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout;
import org.apache.maven.artifact.repository.layout.DefaultRepositoryLayout;
import org.apache.maven.artifact.repository.metadata.io.DefaultMetadataReader;
import org.apache.maven.artifact.repository.metadata.io.MetadataReader;
import org.apache.maven.classrealm.ClassRealmManager;
import org.apache.maven.classrealm.ClassRealmManagerDelegate;
import org.apache.maven.classrealm.DefaultClassRealmManager;
import org.apache.maven.eventspy.EventSpy;
import org.apache.maven.execution.BuildResumptionAnalyzer;
import org.apache.maven.execution.BuildResumptionDataRepository;
import org.apache.maven.execution.DefaultBuildResumptionAnalyzer;
import org.apache.maven.execution.DefaultBuildResumptionDataRepository;
import org.apache.maven.execution.DefaultMavenExecutionRequestPopulator;
import org.apache.maven.execution.MavenExecutionRequestPopulator;
import org.apache.maven.execution.MojoExecutionListener;
import org.apache.maven.execution.ProjectExecutionListener;
import org.apache.maven.execution.scope.internal.MojoExecutionScopeCoreModule;
import org.apache.maven.extension.internal.CoreExports;
import org.apache.maven.graph.DefaultGraphBuilder;
import org.apache.maven.graph.GraphBuilder;
import org.apache.maven.internal.impl.EventSpyImpl;
import org.apache.maven.lifecycle.LifecycleMappingDelegate;
import org.apache.maven.lifecycle.MojoExecutionConfigurator;
import org.apache.maven.lifecycle.internal.DefaultExecutionEventCatapult;
import org.apache.maven.lifecycle.internal.DefaultLifecycleExecutionPlanCalculator;
import org.apache.maven.lifecycle.internal.DefaultLifecycleMappingDelegate;
import org.apache.maven.lifecycle.internal.DefaultLifecycleTaskSegmentCalculator;
import org.apache.maven.lifecycle.internal.DefaultMojoExecutionConfigurator;
import org.apache.maven.lifecycle.internal.DefaultProjectArtifactFactory;
import org.apache.maven.lifecycle.internal.ExecutionEventCatapult;
import org.apache.maven.lifecycle.internal.LifecycleExecutionPlanCalculator;
import org.apache.maven.lifecycle.internal.LifecycleTaskSegmentCalculator;
import org.apache.maven.lifecycle.internal.ProjectArtifactFactory;
import org.apache.maven.lifecycle.internal.builder.Builder;
import org.apache.maven.lifecycle.internal.builder.multithreaded.MultiThreadedBuilder;
import org.apache.maven.model.building.DefaultModelProcessor;
import org.apache.maven.model.building.DefaultModelSourceTransformer;
import org.apache.maven.model.building.ModelProcessor;
import org.apache.maven.model.building.ModelSourceTransformer;
import org.apache.maven.model.io.DefaultModelReader;
import org.apache.maven.model.io.ModelReader;
import org.apache.maven.model.locator.DefaultModelLocator;
import org.apache.maven.model.locator.ModelLocator;
import org.apache.maven.model.superpom.DefaultSuperPomProvider;
import org.apache.maven.model.superpom.SuperPomProvider;
import org.apache.maven.plugin.BuildPluginManager;
import org.apache.maven.plugin.DefaultBuildPluginManager;
import org.apache.maven.plugin.DefaultExtensionRealmCache;
import org.apache.maven.plugin.DefaultMojosExecutionStrategy;
import org.apache.maven.plugin.DefaultPluginArtifactsCache;
import org.apache.maven.plugin.DefaultPluginDescriptorCache;
import org.apache.maven.plugin.DefaultPluginRealmCache;
import org.apache.maven.plugin.ExtensionRealmCache;
import org.apache.maven.plugin.LegacySupport;
import org.apache.maven.plugin.MavenPluginManager;
import org.apache.maven.plugin.MavenPluginPrerequisitesChecker;
import org.apache.maven.plugin.MojosExecutionStrategy;
import org.apache.maven.plugin.PluginArtifactsCache;
import org.apache.maven.plugin.PluginDescriptorCache;
import org.apache.maven.plugin.PluginRealmCache;
import org.apache.maven.plugin.internal.DefaultLegacySupport;
import org.apache.maven.plugin.internal.DefaultMavenPluginManager;
import org.apache.maven.plugin.internal.DefaultPluginDependenciesResolver;
import org.apache.maven.plugin.internal.MavenPluginInternalModule;
import org.apache.maven.plugin.internal.MavenPluginJavaPrerequisiteChecker;
import org.apache.maven.plugin.internal.MavenPluginMavenPrerequisiteChecker;
import org.apache.maven.plugin.internal.PluginDependenciesResolver;
import org.apache.maven.plugin.prefix.PluginPrefixResolver;
import org.apache.maven.plugin.prefix.internal.DefaultPluginPrefixResolver;
import org.apache.maven.plugin.version.PluginVersionResolver;
import org.apache.maven.plugin.version.internal.DefaultPluginVersionResolver;
import org.apache.maven.project.DefaultProjectBuilder;
import org.apache.maven.project.DefaultProjectBuildingHelper;
import org.apache.maven.project.DefaultProjectDependenciesResolver;
import org.apache.maven.project.DefaultProjectRealmCache;
import org.apache.maven.project.ProjectBuilder;
import org.apache.maven.project.ProjectBuildingHelper;
import org.apache.maven.project.ProjectDependenciesResolver;
import org.apache.maven.project.ProjectRealmCache;
import org.apache.maven.project.RepositorySessionDecorator;
import org.apache.maven.project.artifact.DefaultProjectArtifactsCache;
import org.apache.maven.project.artifact.ProjectArtifactsCache;
import org.apache.maven.project.collector.DefaultProjectsSelector;
import org.apache.maven.project.collector.ProjectsSelector;
import org.apache.maven.repository.RepositorySystem;
import org.apache.maven.repository.internal.MavenResolverModule;
import org.apache.maven.repository.legacy.LegacyRepositorySystem;
import org.apache.maven.rtinfo.RuntimeInformation;
import org.apache.maven.rtinfo.internal.DefaultRuntimeInformation;
import org.apache.maven.session.scope.internal.SessionScopeModule;
import org.apache.maven.settings.crypto.DefaultSettingsDecrypter;
import org.apache.maven.settings.crypto.SettingsDecrypter;
import org.codehaus.plexus.DefaultPlexusContainer;
import org.codehaus.plexus.PlexusContainer;
import org.eclipse.aether.connector.basic.BasicRepositoryConnectorFactory;
import org.eclipse.aether.repository.WorkspaceReader;
import org.eclipse.aether.spi.connector.RepositoryConnectorFactory;
import org.eclipse.aether.spi.connector.transport.TransporterFactory;
import org.eclipse.aether.transport.file.FileTransporterFactory;
import org.eclipse.aether.transport.http.ChecksumExtractor;
import org.eclipse.aether.transport.http.HttpTransporterFactory;
import org.sonatype.plexus.components.cipher.DefaultPlexusCipher;
import org.sonatype.plexus.components.sec.dispatcher.DefaultSecDispatcher;
import org.sonatype.plexus.components.sec.dispatcher.SecDispatcher;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import com.google.inject.name.Names;
import com.google.inject.util.Providers;
@SuppressWarnings("deprecation")
public class CompleteMavenModule extends AbstractModule {
@Override
protected void configure() {
// org.apache.maven.repository.internal.MavenResolverModule does not provide
// bindings for all the necessary dependencies
install(new MavenResolverModule());
install(new SessionScopeModule());
install(new MojoExecutionScopeCoreModule());
install(new MavenPluginInternalModule());
install(new WorkspaceReaderModule());
// make module "complete" by binding things not bound by MavenResolverModule
bind(Maven.class).to(DefaultMaven.class).in(Singleton.class);
bind(EventSpy.class).annotatedWith(Names.named("impl")).to(EventSpyImpl.class);
bind(Builder.class).annotatedWith(Names.named("multithreaded")).to(MultiThreadedBuilder.class);
bind(MojosExecutionStrategy.class).to(DefaultMojosExecutionStrategy.class).in(Singleton.class);
bind(ArtifactRepositoryLayout.class).to(DefaultRepositoryLayout.class).in(Singleton.class);
bind(ArtifactHandlerManager.class).to(DefaultArtifactHandlerManager.class).in(Singleton.class);
bind(BuildResumptionAnalyzer.class).to(DefaultBuildResumptionAnalyzer.class).in(Singleton.class);
bind(BuildResumptionDataRepository.class).to(DefaultBuildResumptionDataRepository.class).in(Singleton.class);
bind(GraphBuilder.class).annotatedWith(Names.named(GraphBuilder.HINT)).to(DefaultGraphBuilder.class)
.in(Singleton.class);
bind(ExecutionEventCatapult.class).to(DefaultExecutionEventCatapult.class).in(Singleton.class);
bind(LifecycleExecutionPlanCalculator.class).to(DefaultLifecycleExecutionPlanCalculator.class)
.in(Singleton.class);
bind(LifecycleMappingDelegate.class).annotatedWith(Names.named("default"))
.to(DefaultLifecycleMappingDelegate.class).in(Singleton.class);
bind(MojoExecutionConfigurator.class).annotatedWith(Names.named("default"))
.to(DefaultMojoExecutionConfigurator.class).in(Singleton.class);
bind(LifecycleTaskSegmentCalculator.class).to(DefaultLifecycleTaskSegmentCalculator.class).in(Singleton.class);
bind(ProjectArtifactFactory.class).to(DefaultProjectArtifactFactory.class).in(Singleton.class);
bind(ArtifactFactory.class).to(DefaultArtifactFactory.class).in(Singleton.class);
bind(ModelLocator.class).to(DefaultModelLocator.class).in(Singleton.class);
bind(ModelReader.class).to(DefaultModelReader.class).in(Singleton.class);
bind(ModelProcessor.class).to(DefaultModelProcessor.class).in(Singleton.class);
bind(SuperPomProvider.class).to(DefaultSuperPomProvider.class).in(Singleton.class);
bind(ModelSourceTransformer.class).to(DefaultModelSourceTransformer.class).in(Singleton.class);
bind(BuildPluginManager.class).to(DefaultBuildPluginManager.class).in(Singleton.class);
bind(LegacySupport.class).to(DefaultLegacySupport.class).in(Singleton.class);
bind(MavenPluginManager.class).to(DefaultMavenPluginManager.class).in(Singleton.class);
bind(MavenPluginPrerequisitesChecker.class).annotatedWith(Names.named("java"))
.to(MavenPluginJavaPrerequisiteChecker.class);
bind(MavenPluginPrerequisitesChecker.class).annotatedWith(Names.named("maven"))
.to(MavenPluginMavenPrerequisiteChecker.class);
bind(ClassRealmManager.class).to(DefaultClassRealmManager.class).in(Singleton.class);
bind(ExtensionRealmCache.class).to(DefaultExtensionRealmCache.class).in(Singleton.class);
bind(PluginArtifactsCache.class).to(DefaultPluginArtifactsCache.class).in(Singleton.class);
bind(PluginDescriptorCache.class).to(DefaultPluginDescriptorCache.class).in(Singleton.class);
bind(PluginRealmCache.class).to(DefaultPluginRealmCache.class).in(Singleton.class);
bind(PluginDependenciesResolver.class).to(DefaultPluginDependenciesResolver.class).in(Singleton.class);
bind(PluginPrefixResolver.class).to(DefaultPluginPrefixResolver.class).in(Singleton.class);
bind(MetadataReader.class).to(DefaultMetadataReader.class).in(Singleton.class);
bind(PluginVersionResolver.class).to(DefaultPluginVersionResolver.class).in(Singleton.class);
bind(ProjectBuilder.class).to(DefaultProjectBuilder.class);
bind(ProjectBuildingHelper.class).to(DefaultProjectBuildingHelper.class).in(Singleton.class);
bind(ProjectDependenciesResolver.class).to(DefaultProjectDependenciesResolver.class);
bind(ProjectRealmCache.class).to(DefaultProjectRealmCache.class).in(Singleton.class);
bind(ProjectArtifactsCache.class).to(DefaultProjectArtifactsCache.class).in(Singleton.class);
bind(ProjectsSelector.class).to(DefaultProjectsSelector.class).in(Singleton.class);
bind(RepositorySystem.class).to(LegacyRepositorySystem.class).in(Singleton.class);
bind(RuntimeInformation.class).to(DefaultRuntimeInformation.class).in(Singleton.class);
bind(SettingsDecrypter.class).to(DefaultSettingsDecrypter.class).in(Singleton.class);
bind(PlexusContainer.class).to(DefaultPlexusContainer.class).in(Singleton.class);
bind(WorkspaceReader.class).annotatedWith(Names.named("ide")).toProvider(Providers.of(null))
.in(Singleton.class);
bind(SecDispatcher.class).annotatedWith(Names.named("maven"))
.toInstance(new DefaultSecDispatcher(new DefaultPlexusCipher()));
bind(MavenExecutionRequestPopulator.class).to(DefaultMavenExecutionRequestPopulator.class).in(Singleton.class);
bind(CoreExports.class).toInstance(new CoreExports(null, Collections.emptySet(), Collections.emptySet()));
bind(RepositoryConnectorFactory.class).annotatedWith(Names.named("basic"))
.to(BasicRepositoryConnectorFactory.class);
bind(TransporterFactory.class).annotatedWith(Names.named("file")).to(FileTransporterFactory.class);
bind(TransporterFactory.class).annotatedWith(Names.named("http")).to(HttpTransporterFactory.class);
}
@Provides
@Singleton
List<RepositorySessionDecorator> getRepositorySessionDecorators() {
// No implementations exist for
// org.apache.maven.project.RepositorySessionDecorator
return Collections.emptyList();
}
@Provides
@Singleton
List<ClassRealmManagerDelegate> getClassRealmManagerDelegates() {
// No implementations exist for
// org.apache.maven.classrealm.ClassRealmManagerDelegate
return Collections.emptyList();
}
@Provides
@Singleton
List<MavenPluginPrerequisitesChecker> getMavenPluginPrerequisitesCheckers(
@Named("java") MavenPluginPrerequisitesChecker java,
@Named("maven") MavenPluginPrerequisitesChecker maven) {
return Arrays.asList(java, maven);
}
@Provides
@Singleton
List<MojoExecutionListener> getMojoExecutionListeners(MojoExecutionListener listener) {
return Arrays.asList(listener);
}
@Provides
@Singleton
Map<String, MojoExecutionConfigurator> provideMojoExecutionConfigurators(
@Named("default") MojoExecutionConfigurator defaultConfigurator) {
return Stream.of(defaultConfigurator).collect(Collectors.toMap(k -> "default", v -> v));
}
@Provides
@Singleton
Map<String, LifecycleMappingDelegate> provideLifecycleMappingDelegates(
@Named("default") LifecycleMappingDelegate defaultDelegate) {
return Stream.of(defaultDelegate).collect(Collectors.toMap(k -> "default", v -> v));
}
@Provides
@Singleton
Map<String, ArtifactHandler> provideArtifactHandlers() {
// No implementations exist for CompleteResolverModule.provideArtifactHandlers()
return Collections.emptyMap();
}
@Provides
@Singleton
Map<String, ArtifactRepositoryLayout> provideRepositoryLayouts(ArtifactRepositoryLayout defaultLayout) {
return Stream.of(defaultLayout).collect(Collectors.toMap(k -> "default", v -> v));
}
@Provides
@Singleton
List<ProjectExecutionListener> provideProjectExecutionListeners() {
// No listeners
return Collections.emptyList();
}
@Provides
@Singleton
Map<String, Builder> provideLifecycleBuilders(@Named("multithreaded") Builder multi) {
return Stream.of(multi).collect(Collectors.toMap(k -> "multithreaded", v -> v));
}
@Provides
@Singleton
List<EventSpy> provideEventSpies(@Named("impl") EventSpy impl) {
return Arrays.asList(impl);
}
@Provides
@Singleton
Map<String, ChecksumExtractor> provideChecksumExtractors() {
return Collections.emptyMap();
}
@Provides
@Singleton
Set<RepositoryConnectorFactory> provideRepositoryConnectorFactories(
@Named("basic") RepositoryConnectorFactory basic) {
Set<RepositoryConnectorFactory> factories = new HashSet<>();
factories.add(basic);
return Collections.unmodifiableSet(factories);
}
@Provides
@Singleton
Set<TransporterFactory> provideTransporterFactories(@Named("file") TransporterFactory file,
@Named("http") TransporterFactory http) {
Set<TransporterFactory> factories = new HashSet<>();
factories.add(file);
factories.add(http);
return Collections.unmodifiableSet(factories);
}
}
Right off the bat, I know that I am not doing this correctly. You'll notice these two lines:
install(new MavenPluginInternalModule());
install(new WorkspaceReaderModule());
I had to create these modules to setup bindings for ReadOnlyPluginParametersValidator
, DefaultMavenPluginValidator
, and ReactorReader
, which are all package-private classes (the binding for ReactorReader was my attempt at addressing the error above). If these classes are private, it leads me to believe that some Maven class is supposed to setup these bindings for me. Judging by the fact that I have to create the bindings myself, I suspect that I am taking an improper approach to the dependency injection.
I noticed that Maven does not use Guice directly, but is working with the PlexusContainer
interface in conjunction with Plexus Classworlds and Guice for dependency injection. I do not have a solid understanding of what these "Plexus" libraries are or how work, and I believe this is the root of my problem. Again, I cannot find documentation, examples, or demonstrations on how to use these libraries with Maven.
The exception I pasted above originated from this line in the DefaultMaven class:
try {
WorkspaceReader reactorReader = container.lookup(WorkspaceReader.class, ReactorReader.HINT);
repoSession.setWorkspaceReader(reactorReader);
} catch (ComponentLookupException e) {
return addExceptionToResult(result, e);
}
In this snippet, container
is a PlexusContainer instance, not a Guice injector. I am quite convinced at this point that I need to be setting up my dependency injection with this "Plexus" library rather than Guice, but how? There is nothing I can find explaining how to do this.
EDIT: Here is my pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example.test</groupId>
<artifactId>core-maven-test</artifactId>
<version>0.0.1</version>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<version>5.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
<version>4.0.0-alpha-5</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-compat</artifactId>
<version>4.0.0-alpha-5</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-resolver-provider</artifactId>
<version>4.0.0-alpha-5</version>
</dependency>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-connector-basic</artifactId>
<version>1.9.7</version>
</dependency>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-transport-file</artifactId>
<version>1.9.7</version>
</dependency>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-transport-http</artifactId>
<version>1.9.7</version>
</dependency>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-spi</artifactId>
<version>1.9.7</version>
</dependency>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-util</artifactId>
<version>1.9.7</version>
</dependency>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-impl</artifactId>
<version>1.9.7</version>
</dependency>
</dependencies>
</project>