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).
Related
Actually, I'm executing my maven code on a different remote machine. My Java code depends upon some of the customs dependencies which are downloading from jFrog artifactory.
I can't set up my user-name and password on every machine. Is there any way we can do it through code i.e pom.xml or cmd.
Ex:setting.xml
<settings>
<servers>
<server><id>central</id><username>USER_NAME</username><password>$USER_PWD</password></server>
<server><id>snapshot</id><username>USER_NAME</username><password>$USER_PWD</password></server>
</servers>
</settings>
If you problem is about sharing your settings.xml across your different machine (like bamboo agent, etc), you may as well use:
mvn -s /path/to/settings.xml
The location of the settings.xml differs from your context; for example, if you put the settings.xml alongside the pom.xml, this would be:
mvn -s settings.xml clean install
I'd advise not to put this settings.xml in the same repository than the pom.xml, because you would otherwise put password in a GIT repository which you probably don't want.
And if you only want to share this settings with your personal computers, you could probably use GIT as well: create a repository directly in the ~/.m2 with the advert effect that you should not touch the path to the localRepository (path is OS dependent).
The repository should contains a .gitignore with this minimal line:
repository
This is only to NOT store in the repository the cached dependencies.
It seems what you did is similar to my setup. Once you added the server credentials in the settings.xml, you just need to add the repository as a profile that is always activated/running. Like this:
<profiles>
<profile>
<id>artifactory</id>
<repositories>
<repository>
<snapshots>
<enabled>true</enabled>
</snapshots>
<id>central</id>
<name>libs-release</name>
<url>http://artifactory-url/libs-release</url>
</repository>
<repository>
<snapshots>
<enabled>true</enabled>
</snapshots>
<id>snapshot</id>
<name>libs-snapshot</name>
<url>http://artifactory-url/libs-snapshot</url>
</repository>
</repositories>
</profile>
</profiles>
<activeProfiles>
<activeProfile>artifactory</activeProfile>
</activeProfiles>
All I did was copy paste this settings.xml across different machines. As long as the network is reachable (I use vpn), then I can connect to the artifactory just fine.
Please comment if this is not what you want.
I've run into a strange Maven configuration issue that I have never encountered before, and am confused as to my solution.
I have a local Nexus server that I use as a mirror for everything. Until now, I've only had the following mirror in my settings.xml file:
<mirrors>
<mirror>
<id>nexus</id>
<mirrorOf>*</mirrorOf>
<name>WADA Nexus</name>
<url>https://nexus.domain.org/repository/Public/</url>
</mirror>
</mirrors>
However, I recently wanted to create my own custom parent pom that I have deployed to my Nexus repo. In my project, I have pointed to my parent pom:
<parent>
<groupId>org.domain</groupId>
<artifactId>root-pom</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
However when I now try to run my build, it fails with the following:
ERROR: Failed to parse POMs
org.apache.maven.project.ProjectBuildingException: Some problems were encountered while processing the POMs:
[FATAL] Non-resolvable parent POM: Could not find artifact org.domain:root-pom:pom:1.0.0-SNAPSHOT and 'parent.relativePath' points at wrong local POM # line 9, column 10
For some reason, maven is not trying to look up the parent pom in my Nexus repo.
My only workaround was to define a random repository value in my settings.xml file:
<repositories>
<repository>
<id>nexus</id>
<releases>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
<checksumPolicy>warn</checksumPolicy>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
<checksumPolicy>fail</checksumPolicy>
</snapshots>
<url>https://www.google.com/anythingCanGoHere</url>
<layout>default</layout>
</repository>
</repositories>
Since I've mirrored all Repos/URLs, I can set that url to any value and maven will now pick up my parent pom.
So, why do I even need to specify the repository at all? Shouldn't maven automatically try to resolve the parent pom against maven central or some other default repository?
It is not a strange configuration issue, but simply a misunderstanding from your side. What you have done is to populate <distributionManagement/> in your parent POM and added a catch-all mirror in your settings.xml with your local Nexus instance and expect it to work.
Do you actually know what you are mirroring? No! The default, hardcoded repo in Maven is Maven Central. It is a release repo which does not contain any snapshots. Therefore you see the ERROR. The bogus repo is necessary to enable Maven to request snapshots from your Nexus instance otherwise it will only request releases. Nexus in turn has a repo group with Central and your hosted release and snapshots repos.
As long as you don't define any snapshot repos in your POMs (which you shouldn't) Maven will never be able to download any snapshots.
I'm an Apache Archiva veteran who has recently switched over to Artifactory Pro. I've been attempting to replicate, in Artifactory, a setup where I implemented virtual, private repositories within Archiva. The end result should be that different teams have access to their own team's artifacts, remote repos, the default local repos, and a company-wide repository.
However, I'm having trouble downloading only some dependencies, that are available on and pulled from Maven Central, whenever I configure my Maven settings.xml to use my private virtual repository. If I use Artifactory's default settings.xml (libs-release, libs-snapshot, plugins-release, plugins-snapshot and no virtual repository), then I can download all dependencies that are available on Maven Central and that my projects require.
I'm running Artifactory v4.4.2 on their provided Tomcat within a Windows server 2012 virtual server. I am not running behind a proxy. I have no such issues with Archiva.
In regard to my private virtual repository setup, I have a virtual repository named "test" that is a "generic" Package Type. That repository includes the following repos:
remote-repos
libs-release
libs-snapshot
plugins-release
plugins-snapshot
test-release-local
test-snapshot-local
company-release-local
company-snapshot-local
The first 5 repos listed are the default virtual repository repos provided by Artifactory. The last 4 repos listed are the local repos, and they are of a Generic Package Type.
I think I should use a mirror.
Here is an example settings.xml that I am using (my username and password are getting populated within the generated settings.xml that I save to my Maven conf folder):
<?xml version="1.0" encoding="UTF-8"?>
<settings xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.1.0 http://maven.apache.org/xsd/settings-1.1.0.xsd" xmlns="http://maven.apache.org/SETTINGS/1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<servers>
<server>
<username>${security.getCurrentUsername()}</username>
<password>${security.getEscapedEncryptedPassword()!"*** Insert encrypted password here ***"}</password>
<id>central</id>
</server>
<server>
<username>${security.getCurrentUsername()}</username>
<password>${security.getEscapedEncryptedPassword()!"*** Insert encrypted password here ***"}</password>
<id>snapshots</id>
</server>
</servers>
<mirrors>
<mirror>
<mirrorOf>*</mirrorOf>
<name>test</name>
<url>http://localhost:8082/artifactory/test</url>
<id>test</id>
</mirror>
</mirrors>
<profiles>
<profile>
<repositories>
<repository>
<snapshots>
<enabled>false</enabled>
</snapshots>
<id>central</id>
<name>libs-release</name>
<url>http://localhost:8082/artifactory/libs-release</url>
</repository>
<repository>
<snapshots />
<id>snapshots</id>
<name>libs-snapshot</name>
<url>http://localhost:8082/artifactory/libs-snapshot</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<snapshots>
<enabled>false</enabled>
</snapshots>
<id>central</id>
<name>plugins-release</name>
<url>http://localhost:8082/artifactory/plugins-release</url>
</pluginRepository>
<pluginRepository>
<snapshots />
<id>snapshots</id>
<name>plugins-snapshot</name>
<url>http://localhost:8082/artifactory/plugins-snapshot</url>
</pluginRepository>
</pluginRepositories>
<id>artifactory</id>
</profile>
</profiles>
<activeProfiles>
<activeProfile>artifactory</activeProfile>
</activeProfiles>
</settings>
An example of an artifact that I cannot pull from Maven Central through my virtual repository is poi-ooxml-schemas-3.10-FINAL.jar or many Apache Maven plugins. As soon as I remove the mirror section, I can download all dependencies from Maven Central. This makes no sense to me. My virtual repository is configured to include the remote-repos virtual repository and therefore should be able to pull everything from Maven Central.
What am I doing wrong?
Well, it seems that the actual thing here is that this is a bug which is related to the predefined layout of the generic virtual repository.
The suggested workaround, until this will be fixed, is to create a new repository layout based on the simple-default layout.
So, instead of the simple-default layout:
[orgPath]/[module]/[module]-[baseRev](-[fileItegRev]).[ext]
One should create a new layout which looks like this:
[orgPath]/[module]/[module]-[baseRev].[ext]
Once you create this new repository layout you can change the defined layout of the repository to the newly created one.
This will fix the behaviour you mentioned.
O.K. I figured out part of the answer myself and another part of the answer via JFrog support's help.
Here was the first set of issues that I discovered:
I noticed that if I use a virtual repository that's of a Generic type with a local repository of a Generic type, then artifact retrieval would download most of my pom's dependencies but not all of the dependencies.
I noticed that if I use a virtual repository that's of a Generic type with a local repository of a Maven type, then artifact retrieval would download most of my pom's dependencies but not all of the dependencies.
Those issues seem like bugs to me.
So, I ended up defining a virtual repository (named test-maven in the config below) and two local repositories, all of which were a Maven type. The two local repositories are included within the virtual repository.
I came up with a settings.xml that worked, but it was using a Mirror, which JFrog support advised me that is not a best practice. Bearing that advice in mind, here is the final settings.xml that works for me:
<?xml version="1.0" encoding="UTF-8"?>
<settings xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.1.0 http://maven.apache.org/xsd/settings-1.1.0.xsd" xmlns="http://maven.apache.org/SETTINGS/1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<servers>
<server>
<username>USERNAME</username>
<password>PASSWORD</password>
<id>test-maven</id>
</server>
</servers>
<profiles>
<profile>
<repositories>
<repository>
<snapshots />
<id>test-maven</id>
<name>test-maven</name>
<url>http://localhost:8082/artifactory/test-maven</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<snapshots />
<id>test-maven</id>
<name>test-maven</name>
<url>http://localhost:8082/artifactory/test-maven</url>
</pluginRepository>
</pluginRepositories>
<id>artifactory</id>
</profile>
</profiles>
<activeProfiles>
<activeProfile>artifactory</activeProfile>
</activeProfiles>
</settings>
Using this config, I verified that I can download all artifacts published to Maven Central, further remote repositories, snapshots from the local snapshot Maven repository, and releases from the local snapshot Maven repository. This setup allows me to utilize private repositories per development team.
As soon as I remove the mirror section, I can download all dependencies from Maven Central.
You cannot access the mirror because you have not specified the credentials to use. (Also you don't have anonymous access enabled)
From: https://www.jfrog.com/confluence/display/RTF/Maven+Repository#MavenRepository-ConfiguringAuthentication
Each <repository> and <mirror> element specified in the file must have a corresponding <server> element with a matching <id> that specifies the username and password.
Your mirror's id is test. So you need to add another server entry for it:
<servers>
<server>
<username>USERNAME</username>
<password>PASSWORD</password>
<id>test-maven</id>
</server>
<server>
<!-- credentials for mirror -->
<username>USERNAME</username>
<password>PASSWORD</password>
<id>test</id>
</server>
</servers>
It's a tad annoying that Artifactory's "Set me up" feature for creating settings.xml files doesn't add a <server> entry for mirrors automatically.
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.
We have numerous Java projects, which are CI built with Jenkins. These are deployed to our own Nexus server just fine.
The problem is, we need to provide these libraries to a third party, but without the source code.
So for each project, in Nexus we have:
Releases repository for our devs (includes deployed source code)
Snapshots repositories for our devs (includes deployed source code)
Third party release repository (only JAR + POM)
(and would be good to have): Third party snapshot repository (only JAR + POM) for third party nightly builds
The question is: how is this usually handled in Jenkins/Nexus world? I'd prefer to have one single Job in Jenkins which handles the CI build and the release (artefact deployment) process "automatically".
Currently I'm using multiple <distributionManagement> profiles in our "main root pom.xml" (included by all projects):
[...]
<profiles>
<profile>
<id>default</id>
<distributionManagement>
<repository>
<id>releases</id>
<name>Release</name>
<url>http://path/to/nexus/content/repositories/releases/</url>
</repository>
<snapshotRepository>
<id>snapshots</id>
<name>Snapshot</name>
<url>http://path/to/nexus/content/repositories/snapshots/</url>
<uniqueVersion>false</uniqueVersion>
</snapshotRepository>
</distributionManagement>
</profile>
<profile>
<id>third-party</id>
<distributionManagement>
<repository>
<id>releases</id>
<name>Release</name>
<url>http://path/to/nexus/content/repositories/third-party/</url>
</repository>
<snapshotRepository>
<id>snapshots</id>
<name>Snapshot</name>
<url>http://path/to/nexus/content/repositories/third-party-snapshots/</url>
<uniqueVersion>false</uniqueVersion>
</snapshotRepository>
</distributionManagement>
</profile>
</profiles>
From the Maven docs, it seems to be no way of using multiple repositories during the same build lifecycle, not to mention the fact that we need/don't need the source based on the target repo.
I can do a trick with creating a Job in Jenkins, with the Maven "Goals and options": clean deploy -P third-party and then adding the Post-build action - "Deploy artifacts to Maven repository" with the "default" data - but in this case, only SNAPSHOTs are going to both repo and artefacts released via Jenkins Maven Release Plug-in are going into one repository only.
Any practical ideas how can I do this without overcomplicating our CI job hierarchy?
Thanks in advance!
You can just handle this all in Nexus. Create a repository target that contains a pattern like the one used in the preconfigured example "All but sources (Maven 2)" and narrow that target down even further with another pattern that restricts the groupid, artifactid and maybe even version.
Then create a privilege that uses that repository target and assign it to the user or role you want to have the respective access.
No need to do multiple deployments or some such..
See http://books.sonatype.com/nexus-book/reference/repository-targets.html
You can use Maven Wagon Plugin and upload a single jar to a remote location on deploy phase.