mdarwin
mdarwin

Reputation: 2384

how to move multi-module projects to maven

We are attempting to move several multi-module applications to maven, and having some problems.

Each module is stored independently in cvs. We have manifest files for each application, which list the modules required for that application (and optionally the version). Not all modules are in maven form.

So application 'customer_care' has the following manifest:

 <manifest>
 <module id="MY_api"/>
 <module id="custcare_webapp"/>
 </manifest>

Similarly, the application 'core batch' has a manifest like this:

 <manifest>
 <module id="MY_api"/>
 <module id="core"/>
 <module id="batch"/><!--NB this is a non-maven module -->
 </manifest>

I have started 'mavenising' our code, so the MY_api project has a pom.xml with dependencies defined, including one on another internal code module 'central_config'. I have specified version RELEASE.

The problem

This all works fine, until I need to create a frozen manifest. I can specify a version for each module:

 <manifest>
 <module id="MY_api" version="0.123.0"/>
 <module id="core" version="0.456.0"/>
 <module id="batch" version="0.789.0"/><!--NB this is a non-maven module -->
 </manifest>

BUT this build is not reproducible, because the version of the 'centralconfig' dependency in MY_api is 'RELEASE'. So if someone releases a new version of 'centralconfig', then next time we build this frozen manifest, it's different.

So why don't we use hard-coded versions of dependencies like central-config? Because then, we would have to update perhaps 10 or 20 pom files every time someone updates centralconfig to a new version. Everything which depends on central config, and everything which depends on that, would need its pom.xml updating and to be re-released. Not only is this lots of work, I don't know how I could programmatically and reliably identify every module which declares a dependency on central config.

A possible solution?

Could I define 'centralconfig.version' in one place, and then refer to it in all my modules? If so, where should I do this? I don't know much about parent poms but I feel they might provide a solution.

Update

It seems that using a parent pom is the way to go. But according to this question: Can maven projects have multiple parents? , it's not possible for a maven child project to have multiple parents.

So then how can the MY_api module be a child of both custcare_webapp and core_batch?

Update

I've concluded that maven doesn't meet my requirements, and we've gone back to using our 12-year old home-grown solution build using ant and CVS.

Upvotes: 11

Views: 1947

Answers (2)

K Erlandsson
K Erlandsson

Reputation: 13696

One other option that is often better than a parent-structure for managing versions is to import dependencies.

To illustrate how this works you create one project that only contain a pom specifying the versions to use for all your modules:

<project>
 <modelVersion>4.0.0</modelVersion>
 <groupId>test</groupId>
 <artifactId>module-versions</artifactId>
 <packaging>pom</packaging>
 <version>1.0</version>
 <dependencyManagement>
   <dependencies>
     <dependency>
       <groupId>test</groupId>
       <artifactId>a</artifactId>
       <version>1.1</version>
     </dependency>
     <dependency>
       <groupId>foo</groupId>
       <artifactId>bar</artifactId>
       <version>2</version>
     </dependency>
   </dependencies>
 </dependencyManagement>
</project>

Then, in all your projects that need to have dependencies to anyhing that you have hard coded versions for you import this project in the following manner:

  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>test</groupId>
        <artifactId>module-versions</artifactId>
        <version>1.0</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>

This way you only have to change the module-versions project anytime you release a new version of anything you have a dependency to.

This way you can have multiple "module-versions"-projects to split things up a bit.

Of course, you still have the problem that all project's that want to use the new version must also be released in turn, but that is the cost of using released dependencies in Maven.

Upvotes: 3

sparc_spread
sparc_spread

Reputation: 10833

I think you do need a parent POM. That is a top-level pom.xml that is solely a POM module and has no associated code. You build the entire project by running the mvn command on this pom.xml.

The POM should be in the directory above all the module directories. That is, each of your modules will be in a subdirectory of the directory that holds the master pom.xml

This POM's <packaging> type will be pom. That means it's a POM-only project with no code of its own. It will also have a <modules> tag containing one <module> element for each of your modules. That way, when you run the mvn command, Maven will know to build each of these modules as well. A decent sample parent POM is here.

Set all your dependencies in this POM, using the standard <dependencies> tag. The module POMs will inherit them. (Update: see comments below, is definitely worth exploring the <dependencyManagement> tag instead for the parent POM.)

Finally, each of your module POMs should refer back to the master POM. That way, if you run mvn in one of the module directories (i.e you are just building one module), it will look to the parent for dependencies. You do this with a <parent> tag, which will hold the <groupid> and <artifactid> of the master POM. A good example of a <parent> tag, as well as a good overall review of multi-module projects, is here.

Upvotes: 1

Related Questions