Maven parent-child relationship - java

I have encountered the below "pattern" for maven parent-child relationships:
http://yuml.me/3f8dd366
In this example we have a module with 2 sub modules. The module has a parent pom "Parent for building the Module" which knows the two sub-modules as it's children.
The sub-modules how ever have no idea that this parent knows them, and they think their parent is the one named "Parent for dependency management". Which has common configurations like dependency management, plugin configuration, common properties etc.
My question:
Is this a "good" pattern? Meaning does it have advantages/disadvantages as the seemingly more intuitive patter of child<->parent relationship

One interesting thing to look at is the aggregator pom.
It's a pom that groups project by module, without having a "parent-child" relationship. The aggregator pom doesn't have dependencies management. It only manages the build.
Having both parent(s) pom and aggregator pom is quite a powerful feature of maven.
You can find more information here.
This maven page also has valuable insight on how to set up pom for complex projects.

Hum... I think I disagree with the terms on your picture. Here is how I see this:
This way of organizing modules can be confusing for lot of developpers, but it is a legal way of doing things.
Anyway, I don't recommend this approach because it's confusing. But sometimes, their is no alternatives.
When using this configuration ?
One (or more) of the sub module already have a parent (i.e. was developed in another project but you need to rebuild it). Note that the <module> entry in multi-module project is a relative path so you can have something like:
<modules>
<module>../../somedir/othermodule</module>
...
</modules>
When possible, I recommend to use the multi-module also as the parent because:
less confusing
clean and readable <modules> and <parent> sections (no need to use ugly relative paths to specify the parent or the submodules)
you can organize your modules in a clean hierarchical structure under SCM (so that maven-release-plugin will be happy) (I know that eclipse don't like hierarchical projects, but that's another problem)

This is actually good to have a company wide configuration pom which doesn't care about it's children and contains stuff like properties, dependecyManagement, repositories, pluginManagement etc. which all of them will inherit
Maybe this can help you: Company wide parent pom

Related

Using dependency management in a child pom

Is there any reason to use the dependency management section in a child pom? I'm looking at a maven project in my organization that uses inheritance and aggregation, where the parent and child poms both have a dependency management section. Is the child one doing anything?
I found this question really helpful but didn't find the answer to my specific question - Differences between dependencyManagement and dependencies in Maven
It can be used to control the version of transitive dependencies (libraries that your direct dependencies depend on) without adding a direct dependency.
Child POM will add or override dependency management entries of the parent POM.
Keep in mind that you really, really don't want to have different versions of the same dependency in your codebase. So use this feature judiciously. Preferably you should have organization-wide parent POM file with all dependency versions defined and child POMs don't change them.
In a child pom it does not make sense.
In a multi module setup you should control everything for all children in the parent. For example solve version conflicts / excluding transitive dependencies or import BOM files from other frameworks/libraries (for example spring boot/junit 5/etc.) makes handling of those libs including the centralised maintenance location...

How to define common configurations in maven projects

I hope this is the right place and right discussion to start.
What I want
I am looking for a good/the right way to handle multiple maven projects, that share a common configuration, which is in my case
Set the maven-compiler-plugin version with source/target compilation version
Set the maven-source-plugin to attach sources to artifacts
Define local repository server
Define common dependencies (via dependencyManagement and dependencies).
What I did
My first approach was to create a multi module project. But as the modules are actually independant, when it comes to release (so not the same release cycle), it seemed to be more a burden as a gain. I also failed to make it that I can independently work with a submodule in IntelliJ and have for each submodule it's own Jenkins job. For me it was always all or nothgin
The second approach was/is to have seperate projects. This makes coding in IntelliJ simple and Jenkins can have jobs for each project.
But now changes to parent pom, which affects the children, are tedious to delegate as all other projects must adopt to the change to the new parent.
It is doable and might be the way to work with this, but as I am afraid I misuse the parent concept here, I was wondering, whether there is a better way to use common settings in multiple maven projects ?
Thanks for reading and I hope this was understandable
You can re-use dependencies management section from different pom using <scope>import</scope>, described here, but that would work only for dependencies and you cannot do that for properties, repos and etc.
I'm afraid there is no better way to solve you problem then the parent-pom. Actually this is widely adopted approach. Spring boot, for example, uses that for a long time already.
One thing you want to do to is a good release management for that parent pom. Be sure that you are not dependent on SNAPSHOT version to not brake existing projects.
Just create a parent POM with the common settings and keep the rest separate.
Publish that POM to the (local) repository separately as a standalone entity with pom packaging (no submodules at this level).
Have a look at the Spring Boot parent POM as an example.
The only change in your projects would then be to use your new POM as the parent POM.
<project ... >
<parent>
<groupId>my-group</groupId>
<artifactId>my-parent</artifactId>
<version>1</version>
</parent>
...
Note however that it is generally not a good idea to hardcode dependencies in the parent POM (defining versions via dependencyManagement is OK, but let each project specify explicitly which dependency it actually needs).

Integration testing of Maven Plugin submodule

I have Maven project with multiple submodules. One of these submodules, let's say submodule X depends on all other submodules, as it is Maven Plugin that integrates everything else.
Now I want to use this Maven Plugin during verify stage in my parent POM to do real run of it over entire project (kind of eating own dogfood).
Unfortunatelly I'm getting error:
The projects in the reactor contain a cyclic reference
So how can I make such dogfood integration test for a Maven Plugin submodule?
I would review aggregation and inheritance: they are indeed two different concepts in Maven often used in combination but which can however be used in a complete separated manner as well.
In this case, your plugin submodule is certainly defined as a module in the aggregator pom (that is, it is a submodule). But I also presume the plugin submodule also has as parent pom the aggregator pom as well (that is, the aggregator pom is also the parent pom, which is a normal approach, but not always required).
Is the latter required? You could keep on having the multi-module/aggregator approach without necessarely having the aggregator as parent of the plugin submodule. As such, the plugin subModule would still be a module of the aggregator pom but it would not have as a parent the aggregator pom, decoupling it from it and as such breaking the cyclic dependencies.
Possible drawback: in the aggregator pom you were also defining common things (dependencies management, properties) required also in the plugin submodule. If the case, you would then need to duplicate/review these common settings only for the concerned submodule.
Small suggestion from my side. Cyclic means you have some transitive dependency in your modules. Can please check the dependency tree of your modules and resolve the circular dependency first.

Maven inheritance and aggregation

I'm just curious, what happens if there are used both inheritance and aggregation in the same maven application?
This is the application structure:
my-project-app
my-project-jar
my-project-war
Now, in app's pom.xml, I declare jar and war projects as modules, and in the same time the the poms from both modules declare the app pom as their parent. It is create some kind of redundancy here, isn't it?
What is the best solution for this case?
It's not redundant. They both do different things.
If you use aggregation (define <modules>), you just say which projects have to be built, and its package type is pom.
If you inherit (define <parent>), you'll inherit the parent pom's preferences.
See:
Inheritance and aggregation create a nice dynamic to control builds through a single, high-level POM. You will often see projects that are both parents and aggregators. For example, the entire maven core runs through a single base POM org.apache.maven:maven, so building the Maven project can be executed by a single command: mvn compile. However, although both POM projects, an aggregator project and a parent project are not one in the same and should not be confused. A POM project may be inherited from - but does not necessarily have - any modules that it aggregates. Conversely, a POM project may aggregate projects that do not inherit from it.
More infos here.

Managing Maven multimodule build while inheriting from parent pom

In a nutshell, what I am trying to do is build a bunch of libraries and applications, all Maven projects, all at once. From what I understand a way to accomplish this just in one command line run of mvn package would be to create a multimodule project that will list each module that I would like to build, throw them in the Maven reactor, and build.
Following examples in the Maven book it seems that normally a multimodule pom sits in a directory above the individual modules. However it is also normally the case that a parent pom sits in a directory above the modules, which raises the question, is it normally the case that a multimodule build should also be a parent? I think not; however I wonder why I am running into this funny design quirk.
So, I'm wondering the right way to set this up. I see the following conventions / requirements:
The multimodule pom must have knowledge of where the other modules live on disc. Since it is actually doing the build from source it can't simply rely on already installed versions (since it's installing them!)
The parent doesn't actually have to be a physical directory up although that would be preferable. I see this as the convention best to break.
Really the individual libraries/application shouldn't even need to know they are being built as part of a multimodule build.
How is this usually set up in a multimodule build? Is there a simpler way to manage building multiple Maven projects all at once?
I put all the individual modules within the root module. Some software has trouble with multiple layers of hierarchy.
To make a child module refer to it's parent on the same level:
<parent>
<groupId>com.domain</groupId>
<artifactId>xyz</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../xyz/pom.xml</relativePath>
</parent>
I suggest you do not put anything in the multimodule (e.g. properties) that individual modules need to inherit. If you do, you won't be able to build the other modules independently.
I would go so far as to say that this is the fuzzy part of the "conventions". The documentation, and common sense, both suggest that project aggregation ( aka multi-module builds ) and inheritance are two different mechanisms provided to handle different use cases.
At the same time, it seems that there is a de facto convention ( yeah, I know ) of combining both the project aggregation and inheritance parent roles into a single pom. In fact, both the element of the parent declaration and the module element of the project aggegration mechanism seem to steer the use toward this combination.
Personally, I find it very usefull to separate the parent pom out on a regular basis. And I also find it useful ot locate parent pom in a totally separation location in my source control, and thus my folder structure. However, it rarely seems useful to locate builds that are a part of the same multi-module build structure in source control / folder structure. Perhaps this is even a good measure of whether something should be included in the same aggregate build; if it seems to deserve collocation in the source folder structure, then perhaps its a strong candidate for aggregation.
The only thin I am sure of is that these things are worth sorting out a head of time. And it's probably better to error on the side of not creating monolithic build structures . . . it's very hard to deal with a huge lump of aggregated, parent child build modules that isn't really necessary. On the other hand, aggregating individual builds to run together is a functionality provide at higher levels, such as the CI build server. So, I guess I might suggest erroring on the side of more independence.

Categories