Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Quick way to programmatically deploy artifacts to Nexus (in Java)

I currently write a Java program that deploys a lot of legacy jars to Nexus. My approach is to invoke a process that starts the deploy:deploy-file goal on the command line

mvn deploy:deploy-file ...

This is quite slow. I wonder if there is a faster way to do this?

like image 268
J Fabian Meier Avatar asked Aug 08 '16 14:08

J Fabian Meier


2 Answers

If you specifically target Nexus, you might find simpler to use their REST API to perform the upload:

Here are some examples using curl.

  1. Uploading an artifact and generating a pom file:

    curl -v -F r=releases -F hasPom=false -F e=jar -F g=com.test -F a=project -F v=1.0 -F p=jar -F [email protected] -u admin:admin123 http://localhost:8081/nexus/service/local/artifact/maven/content
    
  2. Uploading an artifact with a pom file:

    curl -v -F r=releases -F hasPom=true -F e=jar -F [email protected] -F [email protected] -u admin:admin123 http://localhost:8081/nexus/service/local/artifact/maven/content
    

In a Java program, you can then use HttpURLConnection to make that POST call (example of that here with authentication here and documentation of cURL here). Basically, in the POST parameters, you need to have r=releases, hasPom=true (or false if you're uploading a POM with it), e for the extension of the artifact, g, a, v and p for the coordinates (groupId, artifactId, version and packaging) and finally file for the file to deploy.

Note that you won't be able to upload snapshots because it is explicitely disabled.


If you want a more generic solution, that would work for whatever artifact, and for whatever remote repository (even a local one), you can directly use the Aether API, which is used under the scenes by Maven 3.1 and higher. The team has an example of such a task in the DeployArtifacts sample.

Add to your project the Aether dependencies:

<dependencies>
    <dependency>
        <groupId>org.eclipse.aether</groupId>
        <artifactId>aether-impl</artifactId>
        <version>${aetherVersion}</version>
    </dependency>
    <dependency>
        <groupId>org.eclipse.aether</groupId>
        <artifactId>aether-connector-basic</artifactId>
        <version>${aetherVersion}</version>
    </dependency>
    <dependency>
        <groupId>org.eclipse.aether</groupId>
        <artifactId>aether-transport-file</artifactId>
        <version>${aetherVersion}</version>
    </dependency>
    <dependency>
        <groupId>org.eclipse.aether</groupId>
        <artifactId>aether-transport-http</artifactId>
        <version>${aetherVersion}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.maven</groupId>
        <artifactId>maven-aether-provider</artifactId>
        <version>${mavenVersion}</version>
    </dependency>
</dependencies>
<properties>
    <aetherVersion>1.1.0</aetherVersion>
    <mavenVersion>3.3.9</mavenVersion>
</properties>

And then you can have the following code to deploy artifacts:

public static void main(String[] args) throws DeploymentException {
    RepositorySystem system = newRepositorySystem();
    RepositorySystemSession session = newSession(system);

    Artifact artifact = new DefaultArtifact("groupId", "artifactId", "classifier", "extension", "version");
    artifact = artifact.setFile(new File("/path/to/file"));

    // add authentication to connect to remove repository
    Authentication authentication = new AuthenticationBuilder().addUsername("username").addPassword("password").build();

    // creates a remote repo at the given URL to deploy to
    RemoteRepository distRepo = new RemoteRepository.Builder("id", "default", "url").setAuthentication(authentication).build();

    DeployRequest deployRequest = new DeployRequest();
    deployRequest.addArtifact(artifact);
    deployRequest.setRepository(distRepo);

    system.deploy(session, deployRequest);
}

private static RepositorySystem newRepositorySystem() {
    DefaultServiceLocator locator = MavenRepositorySystemUtils.newServiceLocator();
    locator.addService(RepositoryConnectorFactory.class, BasicRepositoryConnectorFactory.class);
    locator.addService(TransporterFactory.class, FileTransporterFactory.class);
    locator.addService(TransporterFactory.class, HttpTransporterFactory.class);
    return locator.getService(RepositorySystem.class);
}

private static RepositorySystemSession newSession(RepositorySystem system) {
    DefaultRepositorySystemSession session = MavenRepositorySystemUtils.newSession();
    LocalRepository localRepo = new LocalRepository("target/local-repo");
    session.setLocalRepositoryManager(system.newLocalRepositoryManager(session, localRepo));
    return session;
}

This code will deploy a single artifact having the given coordinates (groupId, artifactId, type, classifier and version) to the configured remote repository:

  • In the coordinates, you can pass an empty String to leave it blank. For example, to deploy without a classifier, you can use "" as the classifier.
  • The file to deploy is set with the method setFile on the Artifact.
  • The remote repository is configured with its ID, layout and URL. The "default" layout is the one used by Maven 2 repository (in contrast to the "legacy" layout for Maven 1). The URL is the same one as you would use inside the deploy-file goal, so file:///C:/m2-repo or scp://host.com/path/to/repo.
  • If necessary, you can create an Authentication to connect to the remote repository (as shown in the snippet).

If you wish to deploy attached artifacts with it, like a POM file, you can create a SubArtifact with:

Artifact pomArtifact = new SubArtifact(artifact, "", "pom");
pomArtifact = pomArtifact.setFile(new File("pom.xml"));

This would attach a POM artifact, without classifier, to the artifact configured above. Then you can add it to the deploy request like the main one:

deployRequest.addArtifact(artifact).addArtifact(pomArtifact);

and the both of them will be deployed.

like image 183
Tunaki Avatar answered Nov 09 '22 18:11

Tunaki


You can do it programmatically in Java with the Eclipse Aether API. Check out the source of my Maven Repository Tools for more detail. In fact you might be able to use it straight out of the box for your needs if all your artifacts are already in a local folder in Maven repository format.

Specifically the deployment related code is in

https://github.com/simpligility/maven-repository-tools/blob/master/maven-repository-provisioner/src/main/java/com/simpligility/maven/provisioner/MavenRepositoryDeployer.java

like image 43
Manfred Moser Avatar answered Nov 09 '22 18:11

Manfred Moser