Can I put the packaged file into another directory? - java

I am wondering if I can put a packaged JAR or WAR into another directory using Maven. How can I do that?

You could specify a directory as your delivery location:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.myspotontheweb.demo</groupId>
<artifactId>demo</artifactId>
<version>1.0</version>
<distributionManagement>
<repository>
<id>internal.repo</id>
<name>MyCo Internal Repository</name>
<url>file:///home/me/path/to/my/repo</url>
</repository>
</distributionManagement>
</project>
Just run maven as follows
mvn clean deploy
I suspect this is not what you're looking for...It's kinda pointless.... Running the install goal places the same artifact in the following default location
$HOME/.m2/repository
Some further guidance on why you want to do this might furnish a better answer

Related

How to "bootstrap" parent POM in GCP Artifact Registry

I followed the instructions to configure a maven client to use an Artifact Registry. I was able to deploy my root pom to it successfully; however, when I have a separate project that inherits from that root pom, it fails to build because it doesn't know where to find the root pom. This makes sense: the child project has no way of knowing that the parent pom is to be found in a random Artifact Registry repo. What is the standard practice for this?
What i've done before is in every programmer's computer, configure the <repository> in their settings.xml but this doesn't scale well + it needs human intervention + it's very cumbersome when dealing with CI since now you need to configure the settings.xml of the build robot. Considering there's so many CI systems nowadays I imagine there's a convention by now. Is there a better way to accomplish this? some way that's committed in the repo and where everything works right out of the box? git clone... mvn package... done. I ask specifically about Artifact Registry because it doesn't use a static username/password but uses the maven wagon to authenticate
One potential solution is to not put the <repository> in the root pom but in every project's pom but that leads to a lot of duplication since the config + the wagon is pretty verbose
Assuming your child and parent share a common .mvn/ folder, you can add:
.mvn/extensions.xml:
<extensions xmlns="http://maven.apache.org/EXTENSIONS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/EXTENSIONS/1.0.0 http://maven.apache.org/xsd/core-extensions-1.0.0.xsd">
<!--This has to be declared here in order to allow child modules to be able to fetch older parent POMs.-->
<extension>
<groupId>com.google.cloud.artifactregistry</groupId>
<artifactId>artifactregistry-maven-wagon</artifactId>
<version>2.1.1</version>
</extension>
<!--project-settings-extension allows using project-specific .mvn/settings.xml-->
<extension>
<groupId>com.github.gzm55.maven</groupId>
<artifactId>project-settings-extension</artifactId>
<version>0.1.1</version>
</extension>
</extensions>
.mvn/settings.xml (don't forget to use your actual artifactregistry URL):
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 https://maven.apache.org/xsd/settings-1.0.0.xsd">
<profiles>
<profile>
<id>default</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<repositories>
<!--This has to be declared here in order to allow child modules to be able to fetch older parent POMs.-->
<repository>
<id>cloud-artifacts</id>
<url>artifactregistry://...</url> <!--use actual full URL here-->
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
</snapshots>
</repository>
</repositories>
</profile>
</profiles>
</settings>
The repository in settings.xml informs Maven to consider that location when searching for artifacts. The artifactregistry-maven-wagon extension allows Maven to access artifacts via the artifactregistry:// protocol.
The other extension (com.github.gzm55.maven) causes Maven to look at the project-specific settings.xml file (you could also just pass --settings=<path to file>, perhaps in .mvn/maven.config, but that would override any user settings).

Why does Maven want to download a module from a remote repository

Given the following modules in my pom.xml
<modules>
<module>core</module>
<module>middle-layer</module>
<module>top-layer</module>
<modules>
Where top-layer depends on middle-layer which depends on core.
When I run clean install it will build and install core and middle-layer successfully, but not top-layer. It tries to download middle-layer from a remote repository instead of using the freshly built one in the local repository.
I do have a custom remote repository specified in my pom.xml:
<repositories>
<repository>
<id>custom</id>
<url>http://someaddress/maven2/</url>
<snapshots>
<updatePolicy>never</updatePolicy>
</snapshots>
<releases>
<updatePolicy>never</updatePolicy>
</releases>
</repository>
</repositories>
Why does it want to grab middle-layer from the remote repository?
Currently, everything is in SNAPSHOT-mode.
Middle layer dependency:
<dependencies>
<dependency>
<groupId>mygroup</groupId>
<artifactId>core</artifactId>
<version>2.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
Top layer dependency:
<dependencies>
<dependency>
<groupId>mygroup</groupId>
<artifactId>middle-layer</artifactId>
<version>2.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
They all inherent their versions from the parent (currently at 2.0.1-SNAPSHOT) and I'm calling install from the parent pom.
Maven frequently prints messages about downloading things that it is not, in fact, downloading. It is considering the possibility that there is a newer snapshot available remotely than the last one build locally. This is why uploading snapshots is often a really bad idea.
I found the answer.
It was a typical problem between keyboard and chair.
The middle-layer is actually historically a WAR, not a JAR, that is to say: it includes some classes I needed in my top-layer. (It's not really called middle-layer of course).
So top-layer searches for middle-layer.jar and can't find it (because it's a WAR).
So I have to refactor some stuff to get the things I need from middle-layer into a new library JAR and make both middle-layer and top-layer depend on that instead.
Sorry to waste your time. :)

How to configure distinct distributionManagement repositories to plugins and libs?

I'm trying to configure the distributionManagement section of a parent POM to enable the upload of libs and plugins to distinct Artifactory repositories, but maven 3 only supports one section of distributionManagement configuration.
As I use differente repositories to download plugins and libs and it's not usable to create one parent POM to each type of artifact, is it possible to configure distinct repositories to let Artifactory, or simply maven, identify the type of artifact and deploy to the correct repository?
Here is this current pom:
<?xml version="1.0" encoding="UTF-8"?>
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.ornanization</groupId>
<artifactId>corporative-parent</artifactId>
<packaging>pom</packaging>
<distributionManagement>
<repository>
<id>artifactoryRelease</id>
<name>artifactory-libs-releases<name>
<url>${artifactory.url}/libs-release-local</url>
</repository>
<snapshotRepository>
<id>artifactorySnapshot</id>
<name>artifactory-libs-snapshots</name>
<url>${artifactory.url}/libs-snapshot-local</url>
</snapshotRepository>
</distributionManagement>
</project>
And this is the entry I'd like to add:
<distributionManagement>
<repository>
<id>artifactoryRelease</id>
<name>artifactory-plugins-releases</name>
<url>${artifactory.url}/plugins-release-local</url>
</repository>
<snapshotRepository>
<id>artifactorySnapshot</id>
<name>artifactory-plugins-snapshots</name>
<url>${artifactory.url}/plugins-snapshot-local</url>
</snapshotRepository>
</distributionManagement>
p.s.: as stated on this page of the Artifactory's User Guide, it's not possible to "deploy build artifacts to remote or virtual repositories" only to local repositories, so it's not possible to let Artifactory's layout management identify the artifact's type.
Just don't use the <distributionManagement> and use the Artifactory Maven Plugin instead.
The <repoKey> tag of the configuration allows you to use variables (both environment and project defined). Just define a variable that will represent plugin and lib repositories and set the values in the corresponding projects.
Also, you'll get the full Build Info BOM on deployment as a bonus.
Thanks to #JBaruch tip to "define a variable that will represent plugin and lib repositories", I first did a research on maven profiles to activate from a variable and realize that it's possible to activate a profile if a certain condition is matched, so I ended up with the following solution:
<profile>
<id>plugins-deploy-artifactory</id>
<activation>
<file>
<exists>target/classes/META-INF/maven/plugin.xml</exists>
</file>
</activation>
<distributionManagement>
<repository>
<id>artifactoryRelease</id>
<name>artifactory-corporativo-releases</name>
<url>${artifactory.url}/plugins-release-local</url>
</repository>
<snapshotRepository>
<id>artifactorySnapshot</id>
<name>artifactory-corporativo-snapshots</name>
<url>${artifactory.url}/plugins-snapshot-local</url>
</snapshotRepository>
</distributionManagement>
</profile>
So when the artifact is a plugin, the profile above is activated, otherwise, the default distributionManagement is used.

Maven Release Patterns

I'm new to maven, and trying to understand how to release my project. I have the following project setup in svn:
trunk
|-deployer
| |-pom.xml
|-webapp
| |-pom.xml
|-utils
|-pom.xml
While developing webapp, I always want to develop against the latest snapshot version of utils, so I declare the dependency on utils in webapp/pom.xml via:
com.company
utils
1.0-SNAPSHOT
Webapp itself is also currently versioned at version 1.0-SNAPSHOT. It's pom.xml has the declaration:
<artifactId>webapp</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>Sample Webapp</name>
So everything is working great, but now I want to release my software. In deployer, I have the following in 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 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.company</groupId>
<artifactId>deployer</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<name>Project Release</name>
<modules>
<module>externals/webapp</module>
</modules>
<properties>
<url.svn>http://<my-server>/<project>/trunk</url.svn>
</properties>
<scm>
<connection>scm:svn:${url.svn}</connection>
</scm>
<build>
<plugins>
<plugin>
<artifactId>maven-release-plugin</artifactId>
<version>2.3</version>
<configuration>
<tagBase>
http://<my-server>/<project>/tags
</tagBase>
</configuration>
</plugin>
</plugins>
</build>
<distributionManagement>
<repository>
<id>Releases</id>
<name>Releases</name>
<url>http://<nexus-server>/nexus/content/repositories/releases</url>
</repository>
<snapshotRepository>
<id>Snapshots</id>
<name>Snapshots</name>
<url>http://<nexus-server>/nexus/content/repositories/snapshots</url>
</snapshotRepository>
</distributionManagement>
</project>
Within the deployer folder itself I have a folder called "externals" which has an svn-externals set to check out my webapp project (I added this because maven complained about not being able to find it), so my modules path should be correct.
Questions
1.) I want to release a version of my web app, but when I run a mvn release:prepare and mvn release:perform in my deployer project, my only tangible output is my trunk tagged in svn and a pom uploaded to my nexus repository. This makes sense in that my deployer artifact packaging is type "pom", but it also doesn't get the job done of getting me a war of my webapp (I should note here that if a do a release in the webapp project by itself though, that I will get the war). I need to release multiple modules, and so I thought I could use maven aggregation from the deployer project to accomplish this, but it doesn't seem to be working.
2.) Is there a better way to achieve what I am trying to do?
Thank you for any insights you can provide.
You should run the maven-release-plugin against each module that you intend to release. I've never seen someone have a special "deployer" module that releases the other modules, this is not how things are commonly done.
Normally to release the webapp module you would run the commands against the webapp module, and to release the utils module you would run the commands against the utils module.
If you have a parent module that ties webapp and util together then I believe you can just run the release commands against that.
As matt b says, simply adding a maven-release-plugin entry at the top pom will probably do what you want. If you want to collect several artifacts into a proper release bundle, you want to create a module for this, but then you want to look at the maven assembly plugin. It can collect various jars (wether from modules or external dependencies) and resources into a directory, zip file or similar.

Distributing application with its Maven POM only

Is it possible to distribute my application with its POM only ?
I have deployed my application in a remote repository and I think it would be nice if I can distribute only its POM, instead of asking the users to download the complete source first and use the POM to build the application afterwards.
The idea is that users would be able to install the application using the POM and a single Maven command.
I tried adding to the POM a downloadURL in a distributionManagement section without success. Here my experiment:
<?xml version="1.0" encoding="UTF-8"?>
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>aGroupId</groupId>
<artifactId>anArtifactId</artifactId>
<version>0.0.1</version>
<distributionManagement>
<downloadUrl>anURL</downloadUrl>
</distributionManagement>
<repositories>
<repository>
<id>someId</id>
<url>anURL</url>
</repository>
</repositories>
</project>
Thanks in advance for any feedback
If you're distributing source, then you should look at the bootstrap POM method: http://maven.apache.org/scm/maven-scm-plugin/examples/bootstrapping-with-pom.html
where the 'scm' element is key. The user has only to run scm:bootstrap to then receive the project source tree from which to build the project.
-tim
You can use the dependency:get mojo to download an artifact to a specified location:
mvn dependency:get -Dartifact=<groupid>:<artifactid>:<version> /
-Ddest=path/to/destination.jar

Categories

Resources