I have a question regarding how best to re-structure a number of individual Maven projects using a combination of inheritance and aggregation.
Setting the scene:
All three projects have a couple of basic dependencies like log4j and junit in common. Aside from that, web-app1 and web-app2 depend on project-api and also share a number of additional common dependencies between them.
I have been reading https://books.sonatype.com/mvnref-book/reference/pom-relationships-sect-pom-best-practice.html , I'm just wanting to confirm that I understand best practice.
Inheritance:
Would it make sense for me to create an organisational level parent POM that includes the dependencies (dependency management) that are common to all three projects and some environment settings and overarching project information. The intent being all Maven projects (not necessarily directly) inherit from this POM.
Would it make sense for me to create another parent POM that includes the dependencies (dependency management) that are common to web-app1 and web-app2 and have only web-app1 and web-app2 inherit from this POM. I think this POM (lets call it web-app parent POM) should be a child POM of the organisational level parent POM.
Aggregation:
In terms of aggregation, I do not want to create a single artifact at the end of the day. Rather, I want to run one Maven build command (likely at the organisational POM level) to build the three projects in this order:
Does this mean the organisational parent POM would declare modules:
And the web-app parent POM would declare modules:
Note the web-app parent POM and organisational parent POM do not have any related code. I believe this is OK noting "In fact, in the Maven world, a project need not contain any code at all, merely a pom.xml." taken from http://maven.apache.org/pom.html.
Finally, how do I ensure the build order I need is respected? E.g. Building the organisational parent POM would result in project-api being built and this latest build being used in the building of web-app1 and web-app2?
I hope this isn't too confusing, happy to clarify if more info is required. Feel free to tell me if I have this completely wrong! Thanks.
In Maven, project aggregation is similar to project inheritance, except that the change is made in the parent pom instead of the child pom. Maven uses the term module to define a child or subproject, which is part of a larger project. An aggregate project can build all the modules together.
All Maven POMs inherit values from a parent POM. If a POM does not specify a direct parent using the parent element, that POM will inherit values from the Super POM. Project Inheritance shows the parent element of project-a which inherits the POM defined by the a-parent project.
model version is the version of project descriptor your POM conforms to. It needs to be included and is set. The value 4.0. 0 just indicated that it is compatible Maven 3.
The groupId is an XML element in the POM. XML file of a Maven project that specifies the id of the project group. In contrast, artifactId is an XML element in the POM. XML of a Maven project that specifies the id of the project (artifact).
Your approach is sensible. A couple of points:
Yes to environment settings and overarching project information, no to dependencies.
Projects should explicitly list all their dependencies and not rely on inheriting them (IMHO). It means you have to declare your logger a few times but it will save you pain later. (You can of course use a separate POM project to group together dependencies that are related and hence usually specified together, like the hibernate example in your link). If you want to centralize versions of dependencies, you can put a dependencyManagement
section in the parent POM, which means you still declare the dependency in the child project, but the version comes from the parent, thus ensuring consistency. Children that don't declare the dependency don't end up with it at all.
Having a webapp-parent is a good idea if they have duplicated plugins, configuration etc. If they share code, you could add another project webapp-common that's a built as a jar which the other two can depend on. Its dependencies will be transitively included, so that's a natural place for common dependencies to go.
webapp-parent doesn't need to be both parent and aggregator, unless you need to frequently build webapp1 and webapp2 but not project-api at the same time. You can just put all the projects as modules of the overall parent. Your directory structure could look like
overall
project-api
webapp-parent
webapp1
webapp2
or if you prefer your original suggestion, which is also fine
overall
project-api
webapp-parent
webapp1
webapp2
It's more important to keep an eye out on the project layout over time, and refactor when appropriate.
Maven is clever enough to build the modules in the correct order, as long as you declare the dependencies.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With