How to release Maven multi-module project with inter-project dependencies?

15,561

Solution 1

your project should define the version only in the parent (project) only once. And let all other modules have a parent relationship. This means you don't have a aggregation. You have a multimodule build instead.

Project  
|-pom.xml (version 0.1-SNAPSHOT)
|-DB  
| |-pom.xml (parent: ..)
|-Business  
| |-pom.xml (parent:..)

This will solve your problem (May be you can take a look here as an example).

Solution 2

I was able to succeed at doing this using Maven 3.3.9...but let me describe my case scenario:

I work with a Java framework called Liferay, where there is a tool called Service Builder that can build and deploy services using Maven with the exact structure as you described:

Service Layer
|-pom.xml (version 1.12.0-SNAPSHOT)
|-Service Portlet
| |-pom.xml (version 1.16.0-SNAPSHOT)<---   
|-Service                               | Artifact dependency
| |-pom.xml (version 1.5.0-SNAPSHOT)-----

As you can see, the portlet app module is built with the service being a dependency, which is a .jar file that packs interfaces among other things for the services to work.

By the way, I did this with my project using modules of different versions. I found an interesting article talking about this practice: Releasing modules of a multi-module project with independent version numbers. You can read the abstract to draw your own conclusions about if versioning modules is appropriate or not... but from my point of view, after reading the demands of the Client, it seems reasonable to me that versioning of modules should be a feature supported by Maven without being too painful to implement.

Running mvn release:prepare and mvn:perform inside the parent (Service Layer) was the way to go. Maven makes the release building and deployment in the following order: 1) parent pom 2) service dependency 3) service portlet.

Maven took care of the order, and that is nice...but the service dependency is built based on the portlet source code, with a goal being run in the parent project: mvn liferay:build-service...so the dependency is affected by the source code of the portlet app (sounds a little crazy). That was a tricky part in my case.

So how do we get the service dependency built and deployed for the service portlet to use it?

Well, the solution for this was using a configuration within the maven-release-plugin that allows Maven to run particular goals in the release:perform phase within any of the projects. What I did is adding this configuration in the maven-release-plugin declaration in the parent pom.xml (Service Layer):

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-release-plugin</artifactId>
  <version>2.5.2</version>
  <configuration>
   <goals>clean liferay:build-service deploy</goals>
  </configuration>
</plugin>

And Maven was able to deploy the parent and each of the children modules with our preferred version numbers (you will be asked to input them).

Summarized answer and recommendation: try using the <goals> configuration and run mvn release:prepare and mvn release:perform at the parent level

Parent and modules should be deployed following the order.

I hope this inspires someone in a similar situation at least, after 5 years.

Solution 3

For the multi module project, when it fails for child snapshot dependency try this release:clean release:prepare release:perform -DignoreSnapshots=true

Hope it helps.

Share:
15,561
Dima
Author by

Dima

Updated on July 02, 2022

Comments

  • Dima
    Dima almost 2 years

    Lets say we have 3 layers project. DB, Business, Web and aggregating pom.

    Project  
    |-DB  
    | |-pom.xml  
    |-Business  
    | |-pom.xml  
    |-pom.xml
    

    All modules are ment to be released and branched together, so Aggregator pom is configured to assign the same version to all submodules. We have the following versions:

    DB-0.1-SNAPSHOT  
    Business-0.1-SNAPSHOT which depends on DB-0.1-SNAPSHOT  
    Web-0.1-SNAPSHOT which depends on Business-0.1-SNAPSHOT  
    

    When doing release:prepare, all versions updated to 0.1, but prepare fails because there is no DB-0.1 in dependency yet.

    One solution is to create different projects for every module and release them one by one while using versions:use-releases plugin to update dependency to 0.1

    But I do not like this idea because it requires a lot of configuration and scripting. So, I prefer to use aggregation and release all modules with single command, but the problem is, as I wrote above, when release plugin tries to build Business-0.1 there is no DB-0.1 in repository yet.

    Is there any way to manage these inter-project dependencies?

    Thanks.

    UPD:

    even install goal fails.

    1. DB Build - OK (no snapshot nor release version is in any repository)
    2. Business - Failure (DB-0.1-SNAPSHOT not found in repository. But it's even not supposed to be there yet!)

    I'm using maven 3.0.2 and release plugin 2.1

  • Dima
    Dima over 13 years
    Every module has reference to the parent '<parent> <artifactId>parent-test</artifactId> <groupId>com.lookin2.test</groupId> <version>0.0.14-SNAPSHOT</version> </parent>' And I configured a release plugni to set each module with parent version. The problem is that Business has dependency on version of DB that is not in repository yet. If I set this dependency to some older version which is in repository already, then all works fine. I only have problem when trying to release new version of entire project.
  • khmarbaise
    khmarbaise over 13 years
    Which Maven version are you workign with? Can you give the pom snippets in particular with the referencing the DB dependency?
  • Aydin Gerek
    Aydin Gerek over 13 years
    This answer doesn't address how one module (eg Business) can depend on another (eg DB) and have that dependency updated automatically during the release process.
  • Programming Guy
    Programming Guy almost 13 years
    Agree, this answer doesn't address the question at all.
  • Duncan Jones
    Duncan Jones about 11 years
    @Dima Why did you accept this answer? Perhaps you can elaborate on how it solved your problem?
  • Johan Tidén
    Johan Tidén about 10 years
    I'd say it's the right answer but the explanation could be more clear. By leaving the version only in the parent, the the dependencies will be updated before the sub-modules start to build, which will make the reactor handle the dependencies so that DB is released and built before Business.