How to combine maven settings files - maven

I've been added to another team at work. Both teams use their own Nexus servers, and have provided me their own settings files, so currently I have to do a lot of hoop-jumping to make sure I'm using the correct settings.xml file to get the projects to build. Is there a good way to merge these files? I've been going through the maven documentation but getting really confused. Settings files are below (identifying info removed)
Team 1 settings file
<settings>
<mirrors>
<mirror>
<id>Nexus</id>
<name>Company Nexus Public Mirror</name>
<url>http://build.company.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
</mirrors>
<servers>
<server>
<id>snapshots</id>
<username>deployment</username>
<password>password1</password>
</server>
<server>
<id>releases</id>
<username>deployment</username>
<password>password2</password>
</server>
</servers>
<activeProfiles>
<activeProfile>jenkins</activeProfile>
</activeProfiles>
</settings>
Team 2 settings file
<settings>
<mirrors>
<mirror>
<!--This sends everything else to /public -->
<id>nexus</id>
<mirrorOf>*</mirrorOf>
<url>http://domain.company.com:8081/nexus/content/groups/public</url>
</mirror>
</mirrors>
<profiles>
<profile>
<id>nexus</id>
<!--Enable snapshots for the built in central repo to direct -->
<!--all requests to nexus via the mirror -->
<repositories>
<repository>
<id>central</id>
<url>http://central</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>true</enabled></snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>central</id>
<url>http://central</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>true</enabled></snapshots>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>
<activeProfiles>
<!--make the profile active all the time -->
<activeProfile>nexus</activeProfile>
</activeProfiles>
<servers>
<server>
<id>snapshots</id>
<username>deployment</username>
<password>password3</password>
</server>
<server>
<id>releases</id>
<username>deployment</username>
<password>password4</password>
</server>
</servers>
</settings>
I tried just merging the <mirrors> sections so both mirrors were listed, but only one team's code builds. I also don't understand how the server id's work. I'll have different username/password combinations for the different servers. I'd think the server id should match the id in the mirrors sections, but that clearly isn't the case. But if not that, how would maven know which snapshots or releases server to use?

You have to check what settings are maven taking during the deployment of the artifacts by using this command:
mvn help:effective-settings
Sometimes it can happen that you are using local settings and global settings (taking first the provided by the maven installation and then the provided by the repository), but maven is not recognizing both. With this command, you can verify the actual settings maven is taking during the deployment. In addition, you can locate the actual file maven is taking and, as a consequence, modify the file properly (with vim, for example) according to the configuration needed by the server.
Remember that there are two locations where a settings.xml file may live:
Maven installation directory
$M2_HOME/conf/settings.xml
User-specific settings file
~/.m2/settings.xml
If both files exists, their contents gets merged, with the user-specific settings.xml being dominant. https://maven.apache.org/settings.html

In my experience there are really only one feasible and easy solution and it does NOT include merging the settings files.
Switch settings files whenever necessary. Just have both files somewhere and have a command line script that switches them (copying over top of settings.xml from a template file). Or alternatively .. have different commands that pass in -s .. problem with that is that you this does not integrate nicely with the IDE usage.
If the id values for the different servers use different names you could also install a Nexus Repository Manager locally on your machine and proxy the two external ones. But in your scenario that wont work since overlapping id values for different servers are used. That must stem from a misunderstanding on both teams on what the id is used for.

If you want to merge several settings file into one, you can (should) use XInclude. It is a W3C recommendation and the best solution for your case.
There is a great tutorial about the usage of Xinclude. Here is the link
I hope this helps.

Related

How to use the internet for maven builds instead, if the corporate maven repository is offline or down?

I have a corporate repository defined in my POM:
<distributionManagement>
<repository>
<id>central</id>
<name>libs-release-local</name>
<url>http://bi-pub.wgresorts.com:8081/artifactory/libs-release-local</url>
</repository>
<snapshotRepository>
<id>snapshots</id>
<name>libs-snapshot-local</name>
<url>http://bi-pub.wgresorts.com:8081/artifactory/libs-snapshot-local</url>
<uniqueVersion>false</uniqueVersion>
</snapshotRepository>
</distributionManagement>
But they keep unplugging and moving or rebooting that box, so sometimes it's not available. Is there a way to tell my maven poms "try and use the corporate repository, but if it's down use the internet?" I tried specifying the repository and plugin repository outside of the distribution management section to no avail.
May anyone offer guidance please?
In settings.xml I have a mirror and a local repository defined:
<mirrors>
<mirror>
<mirrorOf>*</mirrorOf>
<name>repo</name>
<url>http://bi-pub.wgresorts.com:8081/artifactory/repo</url>
<id>repo</id>
</mirror>
</mirrors>
<localRepository>C:\apache-maven-3.1.1\.m2\repository</localRepository>
I don't want to have to keep changing the settings.xml depending on the whims of the IT department, can I set it up so it tries the corporate one goes to the internet if it's down?
EDIT
If you used the id central, you'll have to first create a pom with central that points to the real one on the internet before you can fix this. It can also point to your corporate repository but with a different ID. Then it will fall over to the internet if your corporate repository is down.
I think you may also have to delete the mirror section from the settings.xml
For better or worse, binary repository is a critical piece of the production pipeline.
You don't ask "what options do I have if my site is down", do you? You just keep your site up. Same story here, your IT department should realize that.
You can run Artifactory in DR mode (active/passive) or even in HA mode (active/active). Your repository has all the means to stay up 24/7, so you really don't need those workarounds.
First of all your settings.xml file is not correct.
<settings>
<mirrors>
<mirror>
<!--This sends everything else to /public -->
<id>nexus</id>
<mirrorOf>*</mirrorOf>
<url>http://localhost:8081/nexus/content/groups/public</url>
</mirror>
</mirrors>
<profiles>
<profile>
<id>nexus</id>
<!--Enable snapshots for the built in central repo to direct -->
<!--all requests to nexus via the mirror -->
<repositories>
<repository>
<id>central</id>
<url>http://central</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>true</enabled></snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>central</id>
<url>http://central</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>true</enabled></snapshots>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>
<activeProfiles>
<!--make the profile active all the time -->
<activeProfile>nexus</activeProfile>
</activeProfiles>
</settings>
You have to use the above definition to say maven to search for artifacts as well plugins into the mirror repository (doesn't matter if it's a nexus or artifactory).
As supplemental you have defined uniqueVersion which has no effect starting with Maven 3.
Apart from that the definition in setting.xml is for reading whereas the definition in pom.xml distributionManagement is used for writing which means deploying artifacts or the site.
So in both cases you need the repository up and working as already mentioned by JBaruch. If you IT department is not able to handle such cases (basic IT operations) i would hardly think about that.
Every build in your company depends on the availability of the Repository Manager either for downloading artifacts or for deploying results of the builds and for following steps of the pipeline as well.

Maven deployment user can deploy, but not read repository

The last few days I was trying to set a maven-development environment up. We're using TeamCity for the CI, SonarQube for analysis and SonaType Nexus for the repository management.
TeamCity and SonarQube are working like a charm - The nexus however gives us lots of trouble.
This kind of set up is nothing special, I've done it several times now. This time however, I got a very weird bug: TeamCity is able to deploy artifacts to the nexus, but gives an org.apache.maven.wagon.authorization.AuthorizationException: Not authorized , ReasonPhrase:Unauthorized. error when reading dependencies from the nexus.
I even tried changing the user that TeamCity uses from deployment to admin, same issue. chown returned the correct values as well (owned by the "buildagent" user).
I seriously have no clue what could cause this issue, I already tried reinstalling the nexus 3 times, even added the admin role to the "deployment" user - no change whatsoever.
The settings.xml the "buildagent" user uses has the following content (passwords marked with XXX):
<servers>
<!-- This is the username password used to access the nexus repository -->
<server>
<id>central</id>
<username>deployment</username>
<password>XXX</password>
</server>
<server>
<id>rn-releases</id>
<username>deployment</username>
<password>XXX</password>
</server>
<server>
<id>rn-snapshots</id>
<username>deployment</username>
<password>XXX</password>
</server>
</servers>
<mirrors>
<mirror>
<!--This sends everything else to /public -->
<id>nexus</id>
<mirrorOf>central</mirrorOf>
<url>http://build.example.com:8301/content/groups/public</url>
</mirror>
</mirrors>
<profiles>
<profile>
<id>nexus</id>
<!--Enable snapshots for the built in central repo to direct -->
<!--all requests to nexus via the mirror -->
<repositories>
<repository>
<id>central</id>
<url>http://central</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>true</enabled></snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>central</id>
<url>http://central</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>true</enabled></snapshots>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>
<activeProfiles>
<activeProfile>nexus</activeProfile>
</activeProfiles>
For your information: The build log from TeamCity states that the settings are getting read correctly as well, so that's not the cause either.
I really would like to fix this asap, since we have developers waiting to continue on their projects (and we don't want to give out the url if it's not secured, we have private projects running on the CI).
Thanks in advance!
Edit:
So I now even tried installing artifactory - and I still have the same issue. It seems to be something with either A: Maven or B:TeamCity.
The mirror to Nexus has the id nexus, but there's no <server>-entry with this id. If you add that to the settings.xml with the correct credentials, it should all work again.

Sonatype Nexus: How to set a single server credentials for multiple repositories in maven's settings.xml?

We have multiple repositories in Nexus (i.e., releases, snapshot and site). All 3 repos are under public group and users uses the same credentials to access all these repositories. Providing the same username and password in settings.xml for each repository makes it redundant and hard to maintain them.
Could you please suggest an elegant way to describe one server credential for all the 3 repositories?
Any help is greatly appreciated.
We are using maven 2.2.1 and Nexus OSS 2.7.1
Here is my settings.xml
<settings>
<servers>
<server>
<id>snapshot</id>
<username>deployment</username>
<password>deployment123</password>
</server>
<server>
<id>release</id>
<username>deployment</username>
<password>deployment123</password>
</server>
<server>
<id>site</id>
<username>deployment</username>
<password>deployment123</password>
</server>
</servers>
<mirrors>
<mirror>
<!--This sends everything else to /public -->
<id>nexus</id>
<mirrorOf>*</mirrorOf>
<url>http://localhost:8081/nexus/content/groups/public</url>
</mirror>
</mirrors>
<profiles>
<profile>
<id>nexus</id>
<!--Enable snapshots for the built in central repo to direct -->
<!--all requests to nexus via the mirror -->
<repositories>
<repository>
<id>central</id>
<url>http://central</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>true</enabled></snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>central</id>
<url>http://central</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>true</enabled></snapshots>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>
<activeProfiles>
<!--make the profile active all the time -->
<activeProfile>nexus</activeProfile>
</activeProfiles>
</settings>
Just use one entry in setttings.xml like that
<server>
<id>nexus</id>
<username>deployment</username>
<password>deployment123</password>
</server>
and then in distributionManagement in your pom.xml's you use something like that
<distributionManagement>
<repository>
<id>nexus</id>
<name>Nexus Releases</name>
<url>http://localhost:8081/nexus/content/repositories/releases</url>
</repository>
<snapshotRepository>
<id>nexus</id>
<name>Nexus Snapshot</name>
<url>http://localhost:8081/nexus/content/repositories/snapshots</url>
</snapshotRepository>
</distributionManagement>
For fully working setup with this look at the Nexus Book Examples project that are used in the trial guide. You can add a site with the same id as well, of course. Keep in mind that there is no problem if the id;s are the same as they just detail the identifier of the server element in settings to look for and are NOT an id element for the repository. Imho it should be called serverId or something to be clearer, but thats a different story.
Not a solution but a workaround:
settings.xml will handle system properties and environment variables. So if you're not fussed about putting your server authentication details in a script or in your environment, you can stick with three server credentials but eliminate the need to update all three of them in favour of updating your script or environments (I've put examples for both options in this snippet):
<servers>
<server>
<id>releases</id>
<username>${env.NEXUS_USERNAME}</username> <!-- Env var -->
<password>${nexus.password}</password> <!-- System (-D) var -->
</server>
<server>
<id>snapshots</id>
<username>${env.NEXUS_USERNAME}</username> <!-- Env var -->
<password>${nexus.password}</password> <!-- System (-D) var -->
</server>
<server>
<id>site</id>
<username>${env.NEXUS_USERNAME}</username> <!-- Env var -->
<password>${nexus.password}</password> <!-- System (-D) var -->
</server>
</servers>
Unfortunately there's no <properties> element supported in settings.xml!
Aside: maven already handles the snapshots and releases repositories within nexus, and that is the better way to do things. Your posted settings.xml even enables them already. Why do you need separate repository entries for snapshots and releases?
It looks like you mistaken things here. The given credentials and id's are for the distributionManagement and not for the access to the Nexus in this case. Apart from that you need three different username, password combinations cause you have three possible things releases, snapshots and site. So not a big deal.
Aprt from that i would suggest to upgrade Maven into Maven 3.X line cause Maven 2.2.1 is a little bit out of date.

What does "http://central" mean in my Maven settings.xml?

I've been copying "sample" settings.xml files for ages now, and almost all of them seem to include a repository with the URL http://central. This bugs me, because of course there could actually be a machine on the local domain called "central", so this is a valid URN, but it also must (might?) have some special meaning to Maven.
Is it just shorthand that's commonly used, but the actual URL is ignored? Could I replace it with something else, or remove it entirely? Is it documented anywhere?
If it matters, I develop on a corporate network that has an internal iBiblio mirror, that acts as "central" for us.
AFAIK, it is a bogus URL which mentions at Configure Maven to Download from Nexus as the following example: -
<settings>
<mirrors>
<mirror>
<!--This sends everything else to /public -->
<id>nexus</id>
<mirrorOf>*</mirrorOf>
<url>http://localhost:8081/nexus/content/groups/public</url>
</mirror>
</mirrors>
<profiles>
<profile>
<id>nexus</id>
<!--Enable snapshots for the built in central repo to direct -->
<!--all requests to nexus via the mirror -->
<repositories>
<repository>
<id>central</id>
<url>http://central</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>true</enabled></snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>central</id>
<url>http://central</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>true</enabled></snapshots>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>
<activeProfiles>
<!--make the profile active all the time -->
<activeProfile>nexus</activeProfile>
</activeProfiles>
</settings>
The nexus profile is configured to download from the central repository with a bogus URL of http://central.
This URL is overridden by the mirror setting in the same settings.xml file to point to the URL of your single Nexus group. The nexus group is then listed as an active profile in the activeProfiles element.
I hope this may help.
We also used exactly this sample config, even with the same comments for about 15(!) years without any problems. For maven builds it does not matter, as always nexus is requested for any dependencies.
But today I tried to built a project with a combined ant+maven build which failed to get dependencies via artifact:remoteRepository Task from central Repo.
The solution was to fix the "url" tag in the central repo: https://repo.maven.apache.org/maven2
So it looks like it doesn't matter in most cases, but to avoid any corner cases, always use the right url.

How to easily swap Maven settings profiles?

At my company we use a Nexus server to fetch the artifacts. Which is fine. But sometimes I want to use Maven at home too, where I cannot access the company Nexus. Is there an easy way to swap Maven settings profiles? And is it easily swappable with m2eclipse?
At the moment I'm using the following settings.xml:
<settings
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
<servers>
<server>
<id>central</id>
<username>company-user</username>
<password>company-user</password>
</server>
<server>
<id>mirror</id>
<username>company-user</username>
<password>company-user</password>
</server>
</servers>
<mirrors>
<mirror>
<id>mirror</id>
<url>https://url.to.company.nexus</url>
<mirrorOf>*</mirrorOf>
</mirror>
</mirrors>
<profiles>
<profile>
<id>defaultprofile</id>
<repositories>
<repository>
<id>central</id>
<name>Repository for Company artifacts</name>
<url>https://url.to.company.nexus</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>central</id>
<name>Repository for Company artifacts</name>
<url>https://url.to.company.nexus</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
</profiles>
<activeProfiles>
<activeProfile>defaultprofile</activeProfile>
</activeProfiles>
</settings>
I know i'll probably have to add a new profile to http://repo1.maven.org/, but how to make sure the existing mirrors will not complain with timeouts?
In my experience it is best to have multiple settings file around and swap them as needed. Either by copying the on top of the existing settings.xml from a differently named file or by using the -s option of the mvn command to specify the settings file. If this is too cumbersome to type all the time you can also make an alias for your mvn command with the different settings files. However that breaks bash completion for Maven, which is why I stick to just copying the settings file around with a script.
The same sort of thing actually applies for swapping context e.g. for Git changing the .gitconfig file around so you can pack all those file changes into a script or into different branches in git or whatever..
In addition it can help to run Nexus locally and just connect to it, and let it in turn proxy all the external repos..
The best i can suggest is to use Git/SVN/ and checkin the settings.xml file and use different branches to separate between company and home. Use either
svn switch URL/branches/company
svn switch URL/branches/home
or
git checkout company
git checkout home
A profile will not work cause the mirrorOf part can't be put into a profiles area. Changing in m2e can be done via the configuration dialog. But this might cause inconsistency with the command line.
Unfortunately, mirrors can't be configured in profiles. There's an open request in maven for that. As suggested in JIRA, you could use a script to easily switch between different settings.xml
As for answering to the question in the title : to easily switching between profiles in m2e, I suggest you install JBoss Tools Maven Profile Manager from this update site : http://download.jboss.org/jbosstools/updates/stable/juno/
To enable the same global profile(s) on all your projects :
in the project explorer view : select all maven projects (Ctrl+A)
hit Ctrl+Alt+P to open the Profile Mgmt wizard and select the profiles you want activated.
This is the equivalent to manually set the active maven profiles in each of your project properties page, which is way more tedious.
If you have the artifacts already downloaded in your local repository then you can use mvn -o clean compile .... This will avoid remote repository lookup.

Resources