Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Releasing a multi-module Maven project hosted in single Git repository

I'm trying to release individual modules of a multi-module project, contained within a single git repository.

The folder structure looks something like this:

  |- api/pom.xml
  |- database/pom.xml
  |- core/pom.xml
  pom.xml

The parent pom is simply used as a way of building all subcomponents in a way that makes sense by the use of the <modules> tag. In essence, building api, then database, then core.

The project started out hosted in SVN and by simply pointing to different paths in the repository in the maven scm tag it was easy to get the maven release commands to play nice. This doesn't seem to be the case with Git.

When running mvn release:prepare it performs changes on the api pom as desired, but when performing mvn release:perform it attempts to build the parent pom, and fails to build the database package due to it's inability to resolve the api-snapshot dependency that is listed in database/pom.xml.

How should I configure my scm tags to be able to release a specific module within the Git repository? Is this even possible?

Edit: adding pom samples

Here's an example setup of how the pom files look:

parent pom.xml

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

  <modelVersion>4.0.0</modelVersion>
  <groupId>com.findwise.hydra</groupId>
  <artifactId>hydra-parent</artifactId>
  <version>0.2.0</version>
  <packaging>pom</packaging>

  <modules>
    <module>api</module>
    <module>database</module>
    <module>core</module>
  </modules>
</project>

api/pom.xml

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

  <modelVersion>4.0.0</modelVersion>
  <groupId>com.findwise.hydra</groupId>
  <artifactId>hydra-api</artifactId>
  <packaging>jar</packaging>
  <version>0.2.0</version>
  <name>${project.artifactId}</name>
  <description>Hydra API</description>

  <licenses>
    ...
  </licenses>

  <scm>
    ...
  </scm>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    ...
  </dependencies>

  <build>
    <finalName>${project.name}</finalName>
    <plugins>
      ...
    </plugins>
  </build>
</project>

The database pom looks very much like api, but has a dependency to api. The same goes for core, which depends on database (and through it, on api).

The api and database artifacts themselves are important on their own though, as api defines the client API and database the backend API, both of which are used for integrating with the application. From this stems the original thought of releasing them separately -- the parent pom is merely an afterthought to allow simpler building of the entire stack.

like image 921
Joel Westberg Avatar asked Jul 17 '12 18:07

Joel Westberg


People also ask

What is multi module project in Maven?

Maven's Multi-Module Project A multi-module project is built from an aggregator POM that manages a group of submodules. In most cases, the aggregator is located in the project's root directory and must have packaging of type pom.

How do I specify multiple repositories in Maven?

NOTE: You will also get the standard set of repositories as defined in the Super POM. The other way you can specify multiple repositories is by creating a profile in the $ {user.home}/.m2/settings.xml or $ {maven.home}/conf/settings.xml file like the following:

How to build submodules in Maven?

Now, the submodules are regular Maven projects, and they can be built separately or through the aggregator POM. By building the project through the aggregator POM, each project that has packaging type different than pom will result in a built archive file.

How to manage multiple Git repositories?

Multiple Git Repositories With Repo Repo is another useful utility that you can use to manage multiple repositories. It is used for one of the most popular codebase repo: Android. The repo helps you to work on modules or functionalities that you can think are worth your time.


1 Answers

The usual way to release a multi-module build is to do it from the root position which means also to release all it's sub modules with it. Not releasing a single module separately. If you try to do so you will loose the relationship of the versions to each other.

If you really want to release the modules separately just make separate maven projects out of it and give them each a git repository.

The tree you mentioned looks really like a multi module build which should be released in a single step from the root.

Based on what you have updated i can recommend that you should go with a real multi-module build with a structure like the following:

root
 +-- pom.xml (1.0-SNAPSHOT)
 !
 +-- api 
 !     +-- pom.xml (1.0-SNAPSHOT)
 +-- database
 !     +-- pom.xml (1.0-SNAPSHOT)
 +-- core
       +-- pom.xml (1.0-SNAPSHOT)

The best is to use inheritance in Maven which means to use in every module api, core, database a parent like this:

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

  <parent>
    <groupId>com.findwise.hydra</groupId>
    <artifactId>hydra-parent</artifactId>
    <version>0.2.0-SNAPSHOT</version>
  </parent>

  <artifactId>hydra-api</artifactId>

  <description>Hydra API</description>

This give you the option to put everything which is common in api, core and database into the parent. For example you should put the license information only into the parent, the properties like them:

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

and furthermore you can put information about plugins you are using into the parent as well like:

  <build>
    <pluginManagement>
      <plugins>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>2.3.2</version>
          <configuration>
            <source>1.6</source>
            <target>1.6</target>
          </configuration>
        </plugin>
        ...

and of course you have to define the scm area only a single time in the parent and many other things as well.

Also it's possible and recommended to define dependencyManagement into the parent which gives you the chance to define the dependencies only at one point with their appropriate versions and no need to define the version in the modules.

This will result in dramatically reducing the size of the pom's in the modules.

The result will be to release from the parent via a single mvn release:prepare etc. but will produce different artifacts like hydra-api, hydra-core and hydra-database having the same version number which will make sure to have the api, core etc. in accordance with each other.

like image 195
khmarbaise Avatar answered Sep 22 '22 22:09

khmarbaise