Maven: how to find parent pom? - maven

I am in the process of learning maven and setting up a build environment. One thing I can't figure out, how to set up a project such that it finds a company-wide parent pom. I would like this to work:
$ git clone some_project
$ cd some_project
$ mvn install some_project
The some_project/pom.xml should reference a company-wide pom which it could get from a company maven repository. But where do I specify the company repository?
Putting it in some_project/pom.xml would probably do but then the location is hardcoded in many projects, which could lead to quite some trouble down the road should the server location change.
Having it in settings.xml could work I guess but would break the above requirement.
Edit
Thanks for the answers. I am going with the settings.xml solution although it won't allow the above sequence of commands. Seems like there is no solution that does not require some sort of initial manual setup and of the proposed solutions settings.xml is the simplest to me. Therefore I can't decide which of the two answers to accept. Both are equally good.
Here's the part from settings.xml I came up with:
...
<profiles>
<profile>
<activation>
<property>
<name>!skip</name>
</property>
</activation>
<repositories>
<repository>
<id>internalrepo</id>
<name>Central Internal Maven Repository</name>
<url>http://server.company.example.com/mvnrepo</url>
</repository>
</repositories>
</profile>
</profiles>
...

I'd recommend putting it in settings.xml.
If your company runs its own maven repo, it makes sense to have this configured in settings.xml - especially as you may need to add things like access credentials, which of course should never appear in a (shared) project pom. The only downside is that each user will have to jump through one additional (one-time) hoop when first installing their maven client.
An alternative is to not actually get the root pom from the company maven repo initially, but instead install it directly into your local repo from git. If your root pom is itself a maven project (which is not uncommon) and is available in git, simply clone it and run mvn install.

Putting the company repository URL in settings.xml is considered a good practice. You can also have associated username/password needed for repository upload.
If you care about repository relocation, you must rely on a good DNS choice (repository.mycompany.com is generaly fine) and a good usage of web servers rewrite rules.

Related

Adding environment dependent parameters to the build

In my company's parent POM I specify corporate repositories, that we all use. The URLs contain server name and the path of course. Each time I change the POM I publish a new version.
Now imagine, that the server hosting our repos gets renamed. I can change all URLs in the parent POM (not a problem) and publish a new version with fixed URLs. But I can't change URLs in the existing versions of the parent POM.
This means, that I can't rebuild any artifact from the past.
Is there some standard way to get around this problem? Like:
Central property file
A configuration POM with a fixed 1.0.0-SNAPSHOT version, that get republished on any change?
You never put repositories except for distMngt in your POM. Again -- never. You have burned your POMs forever. This exists in Maven because repo managers did not exist back then. It is bad practice for years now and shall be removed.
Always use a Nexus instance with a repo group. This shall be added to your settings.xml which will mirror everything.
For those who don't believe, I am a long year Maven committer.
Another approach that we employ at work is to replace the URLs in the <distributionManagement> with parameters, like so:
<distributionManagement>
<repository>
<id>my-repo</id>
<name>My Release Repo</name>
<url>${url.deploy.releases}</url>
</repository>
<snapshotRepository>
<id>my-repo</id>
<name>My Release Repo</name>
<url>${url.deploy.snapshots}</url>
</snapshotRepository>
</distributionManagement>
This way, we use settings.xml to control where the artifacts should be deployed. This has the advantage that if you ever migrate a repository (which we did) you only need to update settings.xml for new builds/releases.
If you need to go back to an earlier release and republish (for whatever reason) you just checkout the release tag, set up settings.xml to point to the new repo and do a mvn clean deploy.
If you can't modify settings.xml you can always just copy it, change the copy and point out the new settings file with the -s flag.
This approach also works for <scm> tags.
If you use repositories in your parent pom and may change over time, the best strategy is in the URL or it use ALIAS (DNS, Apache redirect, Rewriting) and especially not the IP address directly , and you do not have to change the address of the repository every time.
Example:
<repositories>
<repository>
<id>myrepo</id>
<url>http://myrepo.me/content/repositories/public/</url>
</repository>
</repositories>
and:
http://myrepo.me/content/repositories/public/ => ip address 1.2.3.4/*/*/

Maven does not reference the settings.xml for a repository when deploying

I am trying to configure the deploy step in a Maven 3.0.4 POM using the <distributionManagement> tag. From XSD for POMs (line 1389), it suggests that merely providing the id should allow Maven too look up the corresponding values from the settings.xml file. I have the desired server listed (which is configured correctly since I can pull dependencies from it and see it mentioned when running in -X debug mode: [DEBUG] Repositories (dependencies): [archiva.snapshots (http://snap-mvnrepo.initech.com/archiva/repository/snapshots, releases+snapshots)]) in the settings.xml. However, when I just provide the <id> in my POM and try to deploy, I get an error that Maven is missing the URL for the repository, but when I explicitly provide the <url> the deploy works.
Does anyone know what I should do to get it working by id only? I don't want to hard code the URL.
DISCLAIMERS: Typos are likely the result of anonymization, but it is possible that they are "real" so feel free to point away at any.
About the <id> child tag of <repository> from the XSD for POMs (line 1389):
A unique identifier for a repository. This is used to match the repository to configuration in the settings.xml file, for example.
From my settings.xml:
<profile>
<id>archiva_dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<repositories>
<repository>
<id>archiva.snapshots</id>
<name>Initech Internal Snapshot Repository</name>
<url>http://snap-mvnrepo.initech.com/archiva/repository/snapshots</url>
</repository>
</repositories>
</profile>
From my (failing) pom.xml:
<distributionManagement>
<repository>
<id>archiva.snapshots</id>
<!--
<name>Initech Internal Snapshot Repository</name>
<url>http://snap-mvnrepo.initech.com/archiva/repository/snapshots</url>
-->
</repository>
</distributionManagement>
The error:
Caused by: java.lang.IllegalStateException: Failed to create release distribution repository for com.initech.ws:initechws:pom:1.0-SNAPSHOT
at org.apache.maven.project.MavenProject.getReleaseArtifactRepository(MavenProject.java:1853)
at org.apache.maven.project.MavenProject.getDistributionManagementArtifactRepository(MavenProject.java:1377)
at org.apache.maven.plugin.deploy.DeployMojo.getDeploymentRepository(DeployMojo.java:227)
at org.apache.maven.plugin.deploy.DeployMojo.execute(DeployMojo.java:118)
at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:101)
... 20 more
Caused by: org.apache.maven.artifact.InvalidRepositoryException: URL missing for repository archiva.snapshots
at org.apache.maven.repository.legacy.LegacyRepositorySystem.buildArtifactRepository(LegacyRepositorySystem.java:775)
at org.apache.maven.project.MavenProject.getReleaseArtifactRepository(MavenProject.java:1843)
... 24 more
The /project/distributionManagement/id value defines the /settings/servers/server/id to match against in order to identify the credentials to use when connecting to the url specified by /project/distributionManagement/url
Because the URL for deployment is very often different from the URL for read access, and the same credentials may apply to multiple URLs, there is no looking up of /project/repositories/repository or /project/pluginRepositories/pluginRepository.
The short answer is thus that you must specify /project/distributionManagement/url in order to be able to deploy, and if you need credentials in order to deploy to that URL you need to specify /project/distributionManagement/id and ensure that the matching credentials exist in your settings.xml
How could we update the documentation to make the above clearer and prevent future users from becoming confused in the manner you have been?
Update
The modello toolchain is generating the XSL with only some of the sentences, so
A unique identifier for a repository. This is used to match the repository to configuration in the settings.xml file, for example.
Is actually
A unique identifier for a repository. This is used to match the repository
to configuration in the settings.xml file, for example.
Furthermore, the identifier is used during POM inheritance and profile
injection to detect repositories that should be merged.
Source
Finally in order to fully make sense of the sentence, you need to be aware that the settings.xml file is just the source of settings when Maven is invoked from the command line. Maven Embedder may actually mean that the settings provided to Maven come from some other source entirely (think, e.g. from the configuration database of Eclipse or another IDE) which is the reason for some of the fun in MRELEASE-577.
A better way to read the first sentence might be
A unique identifier for a repository. This is used to match the repository to configuration, for example in the settings.xml file.
But if you can suggest something even better I will update the docs accordingly

Maven Internal Repository, Is it Really This Hard?

I have several projects which use Maven and I would like to run an internal repository on my work network. I have several libraries which are from third parties and cannot be released into the wild, as well as a few libraries of our own which need to be available within the network (including to our TeamCity CI Server) but cannot be deployed outside the network. After a bit of research, I found three main recommendations on how to accomplish this: Archiva, Artifactory, and Nexus. I have tried each, and have failed to achieve a successful build of any of my projects using the internal repositories created by any of them.
This leads me to believe that I am misunderstanding something or doing something wrong. Does anyone know of a tutorial that will walk me through setting up and internal Maven repository and integrate it with my project?
I have only worked with Nexus, but I found it very easy to install:
Go to http://www.sonatype.org/nexus/go to download the OSS version
Get the 'WAR' distribution
Install the servlet in my installation of Tomcat, via the Web Application Manager
At that point, I can visit http://myserver:8080/nexus to see everything working.
For a superficial setup, I add the default password to my settings.xml:
<servers>
<server>
<id>my-snapshots</id>
<username>admin</username>
<password>admin123</password>
</server>
<server>
<id>my-releases</id>
<username>admin</username>
<password>admin123</password>
</server>
</servers>
and in my POM file:
<distributionManagement>
<snapshotRepository>
<id>my-snapshots</id>
<name>My internal repository</name>
<url>http://myserver:8080/nexus/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>my-releases</id>
<name>My internal repository</name>
<url>http://myserver:8080/nexus/content/repositories/releases</url>
</repository>
</distributionManagement>
To go beyond this, the learning curve jumps up quite a bit, but I found Sonatype's online books to be pretty good. Repository Management with Nexus is the one for understanding what you can do with the repository server. The only thing I found tricky is that some of the info applies only to their commercial software and they don't work too hard to advertise the difference.
Repository managers like Archiva and Nexus are more than just an internal repository. They serve as proxies that obviate reaching out to Maven central or other external repository.
For just an internal repository all you need is a network or HTTP accessible location that has the structure of a Maven repository. Then you refer to it as another repository in your settings file.
<repository>
<id>my-internal-repo</id>
<url>http://myrepo.mycompany.com/</url>
</repository>
See more in Maven's documentation at http://maven.apache.org/guides/introduction/introduction-to-repositories.html.
I would suggest to use the Nexus evaluation guide (latest available version is 2.13 now) that comes with the Nexus Pro Installer, but also works with Nexus Open Source for the simple use cases of proxying and deploying components.
The examples are also available on github and include setups for Maven, Ant/Ivy and Gradle. Once you have a look at the examples and read the guide you will be able to set up your projects in the same way easily.
And of course if there is any problems you can always ask on the mailing list or chat with the developers on hipchat

Accessing local repository in offline mode

I need to make Maven access local repository (file://) when it is ran in offline mode (basically, I am trying to setup repository hierarchy so it does not put artifacts where I don't need them).
This does not work out-of-the-box, though I always assumed this scenario is supported. Is there some flag to enable particular repository in offline mode?
For the dev environment only, if you use IntelliJ IDEA, you can configure Maven to work offline as follow:
Preferences... > Search for Maven > Work offline (checked)
It is possible to set up profiles for repositories utilizing the local file system rather than a network address.
<repository>
<id>mymaven</id>
<url>file://D:\mylocalrepo</url>
</repository>
According to documentation, it is also possible to reference offline mode in a property value.
${settings.offline}
You would then leverage these together to activate a given settings profile according to the examples here. (If Maven doesn't detect the property, try evaluating it directly using the above syntax.)
<profiles>
<profile>
<id>myNeededProfile</id>
<activation>
<activeByDefault>false</activeByDefault>
...
<property>
<name>offline</name>
<value>true</value>
</property>
...
</activation>
...
</profile>
</profiles>
I believe that the Maven Help Plugin can guide this development by computing which profile will be active under certain conditions.
I also think that this could be accomplished more simply by explicitly invoking a profile from the command line each time offline mode is requested.
mvn groupId:artifactId:goal -o -P profile-1,profile-2
Or, even more straightforwardly, by having two separate settings files and subbing them out specifically for the offline/online operations. You could write a command-line wrapper in whatever OS environment you're using to detect the offline request, then move and rename the files before executing the Maven commands, then move them back upon completion.
Maven always tried to connect to central repository. You can define own central (it is only property, which you can redefine)
<repository>
<id>central</id>
<name>My Central</name>
<layout>default</layout>
<url>${my_url}</url>
</repository>
Make the same for snapshot, plugin repository etc. Configuration you can use as profile - it will be optional. See ingyhere answer.

Maven - pointing to a *single* repository

I've got a Nexus Maven repository that I want to be the one and only repository used by my projects.
Per the Nexus documentation, To solve this problem I should change my local .m2/settings.xml.
Changing my settings.xml to solve this problem isn't a good practice, as it's not portable across different developer machines / CI servers.
What I want to do is change my global parent pom to say "use this and only this repository for all projects that use me as a parent." How can I do that? I see that I can add my repository as one of the repositories that are checked, but not the only repository. I tried cutting and pasting the 'mirror' section of the settings file to my pom, but 'mirror' is not allowed there.
Any ideas?
Thanks,
Roy
Tweak Nexus' instructions of modifying your $HOME/.m2/settings.xml. Have a networked settings file that refers to Nexus. This settings file should be used by all developers (and your CI server).
How do all developers refer to this one settings file?
There are a couple of ways of skinning that cat.
Option 1: Alias your Maven command.
On UNIX: alias mvn=mvn -s /networked/path/to/settings.xml
ON Windows: Open mvn.bat. Find mvn invocation and alter it similarly
Option 2: Home/settings linked to networked location
ON UNIX: cd $HOME; rm settings.xml;ln -s /networked/path/to/settings.xml settings.xml
ON Windows: I don't know the equivalent foo for symbolic linking
Assuming that you have a "standard" Maven install for all developers, you can change $M2_HOME/conf/settings.xml
Otherwise, you're out of luck with anything short of an intelligent network proxy.
Have you tried to configure the <repositories> element in your pom?
<project>
...
<repositories>
<repository>
<id>my-internal-site</id>
<url>http://myserver/repo</url>
</repository>
</repositories>
...
</project>
More information and details can be found at the Maven Internal Repositories page.

Resources