135

I'm trying to figure out how to organize many (around 50+) maven2 projects, so that they can deploy into a central nexus repository. When using the mvn deploy goal, one does need to specify the target in the distributionManagement tag like this:

<distributionManagement>
   <repository>
      <id>nexus-site</id>
        <url>http://central_nexus/server</url>
   </repository>
</distributionManagement>

Now, i don't want every single pom.xml (of those 50+) to contain this block over and over again. My first though would be the settings.xml file, but it seems it is not possible (by design) to define it there. So, the first question would be, why is that the case ? If it would be possible i could specify it in the settings.xml in the maven2 distribution, which could be distributed to all developers.

The only possible solution i've found was to create an organisation-wide master-pom project, that does contain these settings, and make all other pom.xml depend on this master-pom via <parent> tag. But this looks kind of strange in multi-module builds:

- master configuration POM (pm)
- Project 1 parent pom (p1 with module 1 and module 2 as modules)
    - Project 1 module pom (with pm as parent)
    - Project 2 module pom (with pm as parent)

Usually i read in all documentation that the module poms should use the parent pom, not some different one. But after reading the maven website about Inheritance v. Aggregation it is written that it is indeed possible.

One problem i found was with the maven site generation, which does seem to have problems with this setup (modules does not get linked correctly if they have no direct back-reference)

So, is this a valid approach ? Any other, more obvious, simpler solution to the problem ?

3
  • 1
    maven.apache.org/pom.html#Distribution_Management
    – OhadR
    Commented Jul 23, 2014 at 11:08
  • 5
    @OhadR: They only write how to write it in one project. Point is that I didn't want to duplicate it about 500 times ...
    – mglauche
    Commented Jul 23, 2014 at 13:45
  • 1
    i see. point taken. so as the one who answered said, you can have a main pom for the project, that will contains the 'distribMngmnt'...
    – OhadR
    Commented Jul 24, 2014 at 10:42

3 Answers 3

161

The best solution for this is to create a simple parent pom file project (with packaging 'pom') generically for all projects from your organization.

<?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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>your.company</groupId>
    <artifactId>company-parent</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>pom</packaging>

    <distributionManagement>
        <repository>
            <id>nexus-site</id>
            <url>http://central_nexus/server</url>
        </repository>
    </distributionManagement>

</project>

This can be built, released, and deployed to your local nexus so everyone has access to its artifact.

Now for all projects which you wish to use it, simply include this section:

<parent>
  <groupId>your.company</groupId>
  <artifactId>company-parent</artifactId>
  <version>1.0.0</version>
</parent>

This solution will allow you to easily add other common things to all your company's projects. For instance if you wanted to standardize your JUnit usage to a specific version, this would be the perfect place for that.

If you have projects that use multi-module structures that have their own parent, Maven also supports chaining inheritance so it is perfectly acceptable to make your project's parent pom file refer to your company's parent pom and have the project's child modules not even aware of your company's parent.

I see from your example project structure that you are attempting to put your parent project at the same level as your aggregator pom. If your project needs its own parent, the best approach I have found is to include the parent at the same level as the rest of the modules and have your aggregator pom.xml file at the root of where all your modules' directories exist.

- pom.xml (aggregator)
    - project-parent
    - project-module1
    - project-module2

What you do with this structure is include your parent module in the aggregator and build everything with a mvn install from the root directory.

We use this exact solution at my organization and it has stood the test of time and worked quite well for us.

5
  • Here is another answer where I describe project inheritance in more detail and how to manage it's inherit complexity, pardon the pun. ;) stackoverflow.com/questions/6347913
    – Jesse Webb
    Commented Jun 14, 2011 at 22:02
  • In the classic consulting model, wherein "client owns the code", my development team will need to work on the project off-site and then take the latest code to the client-site and build it again. In my situation, working with a multi-module project, if I reference the company POM in the project parent POM, I will have to update that reference to point to the client's company POM. I'd rather strive to maintain all environment specific settings in settings.xml if I can help it. What is the recommended approach for my situation?
    – Web User
    Commented Nov 5, 2013 at 21:29
  • 2
    @WebUser Your problem sounds more like a situation where you need different values in your POM file(s) as opposed to what this answer addresses: avoiding duplicated settings across multiple modules. I think you should try injecting properties via a settings.xml file. If that doesn't help you, ask a new question here on SO, link to it here, and I will try to further assist you.
    – Jesse Webb
    Commented Nov 6, 2013 at 17:12
  • Thanks @JesseWebb I did end up trying that out and it is useful to abstract those values away from the POM for the situation I described. For my needs, I added relevant properties under the active profile and those resolved in the POM.
    – Web User
    Commented Nov 6, 2013 at 20:34
  • 1
    See lists.apache.org/thread/ddmdzlf5yb8kk7jt0jw69bvvxsgc1m7k for a related discussion in the Maven user list. This replaces Premek's broken link to the same discussion.
    – Gili
    Commented Feb 12, 2022 at 17:19
94

There's no need for a parent POM.

You can omit the distributionManagement part entirely in your poms and set it either on your build server or in settings.xml.

To do it on the build server, just pass to the mvn command:

-DaltSnapshotDeploymentRepository=snapshots::default::https://YOUR_NEXUS_URL/snapshots
-DaltReleaseDeploymentRepository=releases::default::https://YOUR_NEXUS_URL/releases

See https://maven.apache.org/plugins/maven-deploy-plugin/deploy-mojo.html for details which options can be set.

It's also possible to set this in your settings.xml.

Just create a profile there which is enabled and contains the property.

Example settings.xml:

<settings>
[...]
  <profiles>
    <profile>
      <id>nexus</id>
      <properties>
        <altSnapshotDeploymentRepository>snapshots::default::https://YOUR_NEXUS_URL/snapshots</altSnapshotDeploymentRepository>
        <altReleaseDeploymentRepository>releases::default::https://YOUR_NEXUS_URL/releases</altReleaseDeploymentRepository>
      </properties>
    </profile>
  </profiles>

  <activeProfiles>
    <activeProfile>nexus</activeProfile>
  </activeProfiles>

</settings>

Make sure that credentials for "snapshots" and "releases" are in the <servers> section of your settings.xml

The properties altSnapshotDeploymentRepository and altReleaseDeploymentRepository are introduced with maven-deploy-plugin version 2.8. Older versions will fail with the error message

Deployment failed: repository element was not specified in the POM inside distributionManagement element or in -DaltDeploymentRepository=id::layout::url parameter

To fix this, you can enforce a newer version of the plug-in:

        <build>
          <pluginManagement>
            <plugins>
              <plugin>
                <artifactId>maven-deploy-plugin</artifactId>
                <version>2.8</version>
              </plugin>
            </plugins>
          </pluginManagement>
        </build>
5
  • I am continuously trying this solution but only the altDeploymentRepository property works. altReleaseDeploymentRepository and altSnapshotDeploymentRepository are not recognized and I get this error: Deployment failed: repository element was not specified in the POM inside distributionManagement element or in -DaltDeploymentRepository=id::layout::url paramete. Any suggestion would help. Thank you
    – Shabirmean
    Commented Sep 26, 2019 at 18:56
  • @Shabirmean The reason is a too old version of the deploy plug-in. I have extended my answer with a solution. Commented Sep 27, 2019 at 19:55
  • Yeah, I figured it. Thank you very much :)
    – Shabirmean
    Commented Sep 28, 2019 at 22:15
  • 1
    I have been unable to get the settings.xml part of this solution to work with any of the values. Is there a minimum version of maven-deploy-plugin that respects the properties?
    – tekHedd
    Commented Oct 2, 2020 at 21:52
  • Best approach. However, note that in version 3.0 of the maven-deploy-plugin, the layout part has been removed, so just leave out the ::default.
    – not2savvy
    Commented Sep 15, 2022 at 13:40
8

Regarding the answer from Michael Wyraz, where you use alt*DeploymentRepository parameters in your settings.xml or command line, the format has changed in version 3.0.0 of the maven-deploy-plugin

In the value:

releases::default::https://YOUR_NEXUS_URL/releases

you need to remove the default section, making it:

releases::https://YOUR_NEXUS_URL/releases
4
  • I always received a message like '401 unauthorized' and removing the default solve my problem. Thx Commented Jul 14, 2022 at 14:21
  • 1
    This doesn't seem to a bug. According to the docs: since 3.0.0 the layout part has been removed because Maven 3 only supports Maven 2 repository layout.
    – not2savvy
    Commented Sep 15, 2022 at 13:37
  • @not2savvy Good point, I have updated my answer, thanks Commented Sep 16, 2022 at 0:08
  • Would be great if you propose this as edit to my answer. otherwise users needs to combine both answerts for a complete solution ^^ Commented Sep 23, 2022 at 10:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.