Retrieving Maven Artifact from Repository using Maven Java API - java

If I have a Maven Artifact information (GroupId, ArtifactId, Version) how can I programmatically (using Java) retrieve that Artifact from my local repository?
Specifically, I need to be able to connect to the Maven Repository and create/retrieve a org.apache.maven.artifact.Artifact so I can retrieve the file associated with the Artifact.
I have looked into m2e source code, but the MavenImpl.java (which provides Artifact resolution) is way more complex than what I need and it is difficult to understand how the connection to the repository works.

You'll probably want to look at Aether. See the Wiki for examples.

You can construct a URL from the given information and download the file (note, replace the '.' in the <groupId> with '/'):
<repositoryUrl>/<groupId>/<artifactId>/<version>/<artifactId>-<version>.<type>

This is how we do it in jcabi-aether:
final File repo = this.session.getLocalRepository().getBasedir();
final Collection<Artifact> deps = new Aether(this.getProject(), repo).resolve(
new DefaultArtifact("junit", "junit-dep", "", "jar", "4.10"),
JavaScopes.RUNTIME
);
Give it a list of remote repositories, a location of a local repo, and Maven coordinates of the artifact. As the name shows, the library uses Apache Aether from Sonatype.

Related

Generate Dependency Graph for specific groupId

I am using the Depgraph Maven Plugin and I'd like to ask if there's a way to limit the generated graph file (dot or gml) with those with a specific groupId e.g. com.mycompany.* pattern where only the dependencies within this package would be part of the graph.
I have tried both depgraph:aggregate and depgraph:aggregate-by-groupid but both results contains all the dependencies only organized into groupId
Which generated this:
According to the README of the depgraph plugin (bottom of the page), you can use the includes/excludes parameters similar to Maven's dependency plugin. The plugin also provides more information on this in their filtering wiki page.
Parameters in Maven are provided with -D, or in the configuration of your plugin. In case of command line you would use:
mvn depgraph:graph -Dincludes=com.mycompany*

Zeppelin does not see dependencies from custom repository

I want to add company artifactory to Zeppelin spark interpreter and try to use this document.
So, the URL of our artifactory looks like
http://artifactory.thecompany.com:8081/artifactory/
The access is not restricted to specific user and artifacts are downloadable both from my machine and from machine where Zepplin is running (I tried this with curl).
I've copied the artifact ID from by build.gradle, so I am pretty sure it is correct. However when I try to add the artifact that should be found in my company's artifactory I get error
Error setting properties for interpreter 'spark.spark': Could not find
artifact
com.feedvisor.dataplatform:data-platform-schema-scala:jar:3.0.19-SNAPSHOT
in central (http://repo1.maven.org/maven2/)
This error message sounds like Zeppelin did not try to look for my dependency in custom repository.
I tried to play with artifactory URL using:
http://artifactory.thecompany.com:8081/artifactory/
http://artifactory.thecompany.com:8081/
as well as with "snapshot" property of "Add New Repository" form (using true and false) but nothing helped. The error message does not disappear and classes from the referenced artifact are not found.
Thanks in advance.
For Zeppelin to use your company's repo by default you can set ZEPPELIN_INTERPRETER_DEP_MVNREPO in your ${Z_HOME}/conf/zeppelin-env.sh:
export ZEPPELIN_INTERPRETER_DEP_MVNREPO=http://artifactory.thecompany.com:8081/artifactory/
Alternatively, you can use Dynamic Dependency Loading feature of the notebook:
%dep
z.reset()
z.addRepo("Artifactory").url("http://artifactory.thecompany.com:8081/artifactory/").snapshot()
z.load("com.feedvisor.dataplatform:data-platform-schema-scala:3.0.19-SNAPSHOT")

Load Maven Artifact via Classloader

Is it possible to load remote artifacts via Maven during runtime, e.g. using a specific (Maven) ClassLoader?
For my use case, a legacy software is using an URLClassLoader to pull a JAR containing some resources files during start-up of a test framework.
Problem is that we currently just use a fixed URL pointing to the repository and not actually using Maven artifact resolution at all.
Adding this to the projects dependency is no option because we want to refer to a specific version from an external configuration file (to run the test framework with different versions of our packaged use cases without changing code).
I hope you get what I want to achieve - it doesn't have to be the prettiest solution because we currently rely on a fixed URL pattern, I'd like to be dependent from the local maven setup instead.
You may use Eclipse Aether (http://www.eclipse.org/aether) to resolve and download the JAR artifacts from maven repositories using GAV coordinates.
Then use a regular URLClassLoader with the JAR you've downloaded.
You can find some examples there: https://github.com/eclipse/aether-demo/blob/master/aether-demo-snippets/
But basically, what you should do is the following:
DefaultServiceLocator locator = MavenRepositorySystemUtils.newServiceLocator();
locator.addService(RepositoryConnectorFactory.class, BasicRepositoryConnectorFactory.class);
locator.addService(TransporterFactory.class, FileTransporterFactory.class);
locator.addService(TransporterFactory.class, HttpTransporterFactory.class);
RepositorySystem system = locator.getService(RepositorySystem.class);
DefaultRepositorySystemSession session = MavenRepositorySystemUtils.newSession();
LocalRepository localRepo = new LocalRepository("/path/to/your/local/repo");
session.setLocalRepositoryManager(system.newLocalRepositoryManager(session, localRepo));
// Set the coordinates of the artifact to download
Artifact artifact = new DefaultArtifact("<groupId>", "<artifactId>", "jar", "<version>");
ArtifactRequest artifactRequest = new ArtifactRequest();
artifactRequest.setArtifact(artifact);
// Search in central repo
artifactRequest.addRepository(new RemoteRepository.Builder("central", "default", "http://repo1.maven.org/maven2/").build());
// Also search in your custom repo
artifactRequest.addRepository(new RemoteRepository.Builder("your-repository", "default", "http://your.repository.url/").build());
// Actually resolve (and download if necessary) the artifact
ArtifactResult artifactResult = system.resolveArtifact(session, artifactRequest);
artifact = artifactResult.getArtifact();
// Create a classloader with the downloaded artifact.
ClassLoader classLoader = new URLClassLoader(new URL[] { artifact.getFile().toURI().toURL() });

Get all the dependencies of a MavenProject (including transitive ones) using Aether

How can you get all the dependencies of a MavenProject (including transitive ones) using Aether?
I have seen numerous examples where you specify the gav and it resolves the artifact and all it's dependencies. This is all fine. However, if your plugin is supposed to be invoked from the same project whose dependencies you're trying to resolve, this does not seem to work (or perhaps I am doing it wrong). Could somebody please give me a working example of how to do it?
I have tried the example with jcabi-aether shown in this SO post.
Try to use an utility class Classpath from jcabi-aether:
Collection<File> jars = new Classpath(
this.getProject(),
new File(this.session.getLocalRepository().getBasedir()),
"test" // the scope you're interested in
);
You will get a list of JARs and directories which are in "test" scope in the current Maven project your plugin is in.
If you're interested to get a list of Artifacts instead of Files, use Aether class directly:
Aether aether = new Aether(this.getProject(), repo);
Set<Artifact> artifacts = new HashSet<Artifact>();
for (Artifact dep : this.getProject().getDependencyArtifacts()) {
artifacts.addAll(aether.resolve(dep, JavaScopes.COMPILE));
}

How can I programmatically get SCM connection URL of a dependency?

I'm trying to write a custom Maven plugin that will parse the SCM changelog of the current Maven project, as well as any of its direct dependencies.
I know that MavenProject.getScm().getConnection() returns the connection URL of the current project.
However, I would also like to retrieve the connection URL of any direct dependencies. (They are already defined in each dependency's pom.xml)
I looked at MavenProject.getDependencies(), but it returns a List of Dependency objects which doesn't seem to contain the information I need.
Does anyone know how I can retrieve this information?
You will have to get instance of MavenProject for each of the dependencies, e.g. obtain instance of the MavenProjectBuilder and build MavenProject instance with it.
See the following question for a sample code snippet for resolving an individual dependency.

Categories