133

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 ?

Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
mglauche
  • 3,344
  • 4
  • 28
  • 31
  • 1
    http://maven.apache.org/pom.html#Distribution_Management – OhadR Jul 23 '14 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 Jul 23 '14 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 Jul 24 '14 at 10:42

3 Answers3

160

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.

Neeraj Singh
  • 457
  • 7
  • 14
Jesse Webb
  • 43,135
  • 27
  • 106
  • 143
  • Here is another answer where I describe project inheritance in more detail and how to manage it's inherit complexity, pardon the pun. ;) http://stackoverflow.com/questions/6347913/ – Jesse Webb Jun 14 '11 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 Nov 05 '13 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](http://maven.apache.org/examples/injecting-properties-via-settings.html). 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 Nov 06 '13 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 Nov 06 '13 at 20:34
  • 1
    See https://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 Feb 12 '22 at 17:19
86

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>
hjoeren
  • 549
  • 1
  • 5
  • 12
Michael Wyraz
  • 3,638
  • 1
  • 27
  • 25
  • 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 Sep 26 '19 at 18:56
  • @Shabirmean The reason is a too old version of the deploy plug-in. I have extended my answer with a solution. – Michael Wyraz Sep 27 '19 at 19:55
  • Yeah, I figured it. Thank you very much :) – Shabirmean Sep 28 '19 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 Oct 02 '20 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 Sep 15 '22 at 13:40
7

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
Robert Newton
  • 1,344
  • 12
  • 19
  • I always received a message like '401 unauthorized' and removing the default solve my problem. Thx – Fábio Almeida Jul 14 '22 at 14:21
  • 1
    This doesn't seem to a bug. According to [the docs](https://maven.apache.org/plugins/maven-deploy-plugin/deploy-mojo.html): _since 3.0.0 the layout part has been removed because Maven 3 only supports Maven 2 repository layout._ – not2savvy Sep 15 '22 at 13:37
  • @not2savvy Good point, I have updated my answer, thanks – Robert Newton Sep 16 '22 at 00:08
  • Would be great if you propose this as edit to my answer. otherwise users needs to combine both answerts for a complete solution ^^ – Michael Wyraz Sep 23 '22 at 10:12