Reputation: 2384
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.
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.
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.
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?
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
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
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