Maven Inheritance and Aggregation Example Architecture

noosy picture noosy · Jan 13, 2012 · Viewed 8.5k times · Source

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:

  • There are 3 code based existing Maven projects all developed by the same team.
  • 1 project is an API, lets call is project-api.
  • The other 2 projects are web apps which utilise the project-api. Lets call them web-app1 and web-app2.

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:

  1. project-api
  2. web-app1
  3. web-app2

Does this mean the organisational parent POM would declare modules:

  1. project-api
  2. web-app parent POM

And the web-app parent POM would declare modules:

  1. web-app1
  2. web-app2

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.

Answer

artbristol picture artbristol · Jan 13, 2012

Your approach is sensible. A couple of points:

Organisational level POM

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.

Aggregation

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.

Build order

Maven is clever enough to build the modules in the correct order, as long as you declare the dependencies.