Maven parent pom vs modules pom
There seem to be several ways to structure parent poms in a multiproject build and I wondering if anyone had any thoughts on what the advantages / drawbacks are in each way.
The simplest method of having a parent pom would be putting it in the root of a project ie
myproject/
myproject-core/
myproject-api/
myproject-app/
pom.xml
where the pom.xml is both the parent project as well as describes the -core -api and -app modules
The next method is to separate out the parent into its own subdirectory as in
myproject/
mypoject-parent/
pom.xml
myproject-core/
myproject-api/
myproject-app/
Where the parent pom still contains the modules but they're relative, eg ../myproject-core
Finally, there's the option where the module definition and the parent are separated as in
myproject/
mypoject-parent/
pom.xml
myproject-core/
myproject-api/
myproject-app/
pom.xml
Where the parent pom contains any "shared" configuration (dependencyManagement, properties etc.) and the myproject/pom.xml contains the list of modules.
The intention is to be scalable to a large scale build so should be scalable to a large number of projects and artifacts.
A few bonus questions:
Edit: Each of the sub projects have their own pom.xml, I've left it out to keep it terse.
In my opinion, to answer this question, you need to think in terms of project life cycle and version control. In other words, does the parent pom have its own life cycle ie can it be released separately of the other modules or not?
If the answer is yes (and this is the case of most projects that have been mentioned in the question or in comments), then the parent pom needs his own module from a VCS and from a Maven point of view and you'll end up with something like this at the VCS level:
root
|-- parent-pom
| |-- branches
| |-- tags
| `-- trunk
| `-- pom.xml
`-- projectA
|-- branches
|-- tags
`-- trunk
|-- module1
| `-- pom.xml
|-- moduleN
| `-- pom.xml
`-- pom.xml
This makes the checkout a bit painful and a common way to deal with that is to use svn:externals
. For example, add a trunks
directory:
root
|-- parent-pom
| |-- branches
| |-- tags
| `-- trunk
| `-- pom.xml
|-- projectA
| |-- branches
| |-- tags
| `-- trunk
| |-- module1
| | `-- pom.xml
| |-- moduleN
| | `-- pom.xml
| `-- pom.xml
`-- trunks
With the following externals definition:
parent-pom http://host/svn/parent-pom/trunk
projectA http://host/svn/projectA/trunk
A checkout of trunks
would then result in the following local structure (pattern #2):
root/
parent-pom/
pom.xml
projectA/
Optionally, you can even add a pom.xml
in the trunks
directory:
root
|-- parent-pom
| |-- branches
| |-- tags
| `-- trunk
| `-- pom.xml
|-- projectA
| |-- branches
| |-- tags
| `-- trunk
| |-- module1
| | `-- pom.xml
| |-- moduleN
| | `-- pom.xml
| `-- pom.xml
`-- trunks
`-- pom.xml
This pom.xml
is a kind of "fake" pom: it is never released, it doesn't contain a real version since this file is never released, it only contains a list of modules. With this file, a checkout would result in this structure (pattern #3):
root/
parent-pom/
pom.xml
projectA/
pom.xml
This "hack" allows to launch of a reactor build from the root after a checkout and make things even more handy. Actually, this is how I like to setup maven projects and a VCS repository for large builds : it just works, it scales well, it gives all the flexibility you may need.
If the answer is no (back to the initial question), then I think you can live with pattern #1 (do the simplest thing that could possibly work).
Now, about the bonus questions:
Honestly, I don't know how to not give a general answer here (like "use the level at which you think it makes sense to mutualize things"). And anyway, child poms can always override inherited settings.
The setup I use works well, nothing particular to mention.
Actually, I wonder how the maven-release-plugin deals with pattern #1 (especially with the <parent>
section since you can't have SNAPSHOT dependencies at release time). This sounds like a chicken or egg problem but I just can't remember if it works and was too lazy to test it.
From my experience and Maven best practices there are two kinds of "parent poms"
"company" parent pom - this pom contains your company specific information and configuration that inherit every pom and doesn't need to be copied. These informations are:
Preparing this parent pom need to be done with caution, because all your company poms will inherit from it, so this pom have to be mature and stable (releasing a version of parent pom should not affect to release all your company projects!)
The intention is to be scalable to a large scale build so should be scalable to a large number of projects and artifacts.
Mutliprojects have structure of trees - so you aren't arrown down to one level of parent pom. Try to find a suitable project struture for your needs - a classic exmample is how to disrtibute mutimodule projects
distibution/
documentation/
myproject/
myproject-core/
myproject-api/
myproject-app/
pom.xml
pom.xml
A few bonus questions:
This configuration has to be wisely splitted into a "company" parent pom and project parent pom(s). Things related to all you project go to "company" parent and this related to current project go to project one's.
Company parent pom have to be released first. For multiprojects standard rules applies. CI server need to know all to build the project correctly.
An independent parent is the best practice for sharing configuration and options across otherwise uncoupled components. Apache has a parent pom project to share legal notices and some common packaging options.
If your top-level project has real work in it, such as aggregating javadoc or packaging a release, then you will have conflicts between the settings needed to do that work and the settings you want to share out via parent. A parent-only project avoids that.
A common pattern (ignoring #1 for the moment) is have the projects-with-code use a parent project as their parent, and have it use the top-level as a parent. This allows core things to be shared by all, but avoids the problem described in #2.
The site plugin will get very confused if the parent structure is not the same as the directory structure. If you want to build an aggregate site, you'll need to do some fiddling to get around this.
Apache CXF is an example the pattern in #2.
上一篇: 无论如何排除从父POM继承的工件?
下一篇: Maven家长pom vs模块pom