common POM based plugins across multiple microservice projects - maven

I am trying to figure out a way to import a set of common Maven plugins, across multiple microservice projects?
Idea is to maintain a single place to manage all the common plugins - like jacoco, javadocs etc.
We totally want to avoid the parent POM way of handling it.

The Maven way to do this is to have a parent POM. You can either construct a multi-module project or have an external parent POM.
Maven has no way of "importing xml" into a given POM, except for the <scope>import</scope> for dependencyManagement. So you cannot define a set of plugins, properties etc. and just import them.

Related

Maven: how to not depend on Parent POM

I have a Maven multi-module project. Something like this:
- ParentProject
- ChildA
- ChildB
- ChildC
The child projects inherit from a Parent POM (ParentProject) solely for the reason of sharing stuff like <build>, <scm> and <properties>, so as to not repeat it in all the child modules. Thus, the objective of the parent-child relationship is not related to dependencies in any way. It plays a role at build-time, not at runtime, so to speak.
The child projects's artifacts are for consumption for a wider audience, hence they'll be published into a centralized repo.
How do I "break" the relationship between from the child up to the parent seen from a perspective of a consumer of a child?
Let's say another project, ProjectX, adds a dependency on ChildA. When doing this the Maven client will attempt to not only download the POM and artifact of ChildA itself but will even try to download the POM for ParentProject. However, there's absolutely no need for that POM seen from a consumer point of view. It doesn't contain information that the consumer needs to know.
How can I break this relationship from consumer's perspective? Forcing the POM for ParentProject to be published into a repo seems pointless as nobody has any need for it there.
Perhaps there's another way that Maven will let me share things like build instructions and properties between projects without mandating that a Parent POM exists in a centralized repo ?
Or perhaps there's some way I can manipulate the POM for the Child projects which gets put into the centralized repo (removing the <parent> element as it is irrelevant).
Perhaps only me but I feel that Maven is conflating two unrelated concepts here (build-time vs consume-time) and forcing unnecessary roundtrips and unnecessary artifacts in repo. I haven't dabbled with Gradle yet but I wonder if it does it any better?
Usually, the Maven POM is both build POM and consumer POM. This is not ideal, and will probably change in future versions of Maven.
At the moment, your best option seems to be the flatten Maven plugin, which allows you to remove "unnecessary" parts of the POM before uploading it.

How to deploy child module without also deploying parent module?

I have a project with a parent aggregator module and 3 children modules.
I don't know if this is a bug for me or just how Maven works, but I am currently unable to deploy one of my children modules without also deploying the respective parent. When I try to import the child module on another project of mine, Maven throws an error saying it can't resolve the parent. If I deploy both to my Nexus, it works perfectly. Do I always have to deploy both?
Yes.
You always need the parent POM as well.
When Maven need to "use" a module, it needs to resolve it.
If this module has ancestors it needs to access to every ones to resolve it.
OR you will face somethings like :
Could not resolve dependencies for project org.projectB:childA-Consumer:jar:0.1.0:
Failed to collect dependencies at org.projectA:childA:jar:0.1.0:
Failed to read artifact descriptor for org.projectA:childA:jar:0.1.0:
Could not find artifact org.projectA:parent:pom:0.1.0
Solution 1 : Deploy the parent
The common way is to deploy the parent, so this way when you consume your module maven will be able to find ancestors and so resolve your module's pom.
But lot of users seems to consider this as not so satisfying. (There are many question about that on stackoverflow ...)
Solution 2 : Parent != Aggregator
Most of the time in multi-module project, the aggregator pom is also the parent pom but this is 2 different concepts.
parent : is about sharing configuration with inheritance.
aggregator : is about building several modules at same time.
(more details about aggregator vs parent differences)
So, you can have an aggregator with several children and each child has no parent.
This way you don't have to deploy your aggregator.
Drawback you can not use inheritance to share config between modules.
Note that this is not a drawback for everyones, some consider that using inheritance and so parent is not good idea. 😅
Solution 3 : Use Maven Flatten Plugin
Currently poms contains 2 kind of information :
how to build the artifact,
how to consume it (e.g. dependencies).
Maven 5 will maybe clarify this and so you could have a different pom in your released artifacts and in your source code.
Using Maven 3, there is a plugin which aims to do that : flatten-maven-plugin
It aims to generate a pom.xml consumers oriented.
Among others, parent relationship is resolved, flattened and removed.
This way, you can use parents to share configuration between modules (with inheritance) and not deploy your aggregator and/or parents .
Drawback, you could maybe face issues with some other maven plug-in interaction ? 🤷
Some tips you need to know if you wan to use flatten-maven-plugin :
flatten cleangoal is no more useful.
how to fix url, scm url, scm connection and scm developerConnection resolution.

Spring boot parent pom with custom parent

I read a lot of posts regarding the ways to use spring-boot-starter-parent in a spring boot project.
Essentially, I read posts (Spring documentation also talks about this) describing two ways to do this
To use spring-boot-starter-parent as the project parent directly. It gives us the benefits of having the dependency management as well as the plugin management.
The other way is to import the spring-boot-starter parent in the project pom (we may need this in case we already have a parent pom for the project).
It allows us to get the benefits of dependency management but not the plugin management)
I am creating a new Maven multi module project. Ideally I would like to have my own custom parent and also get all the benefits of using the Spring-boot-starter-parent.
I was wondering if it made sense to create a custom parent for my maven projects. This parent would in turn be a child of the spring-boot-starter-parent.
If I am not missing anything, this way I could get the benefits of having the dependency management and plugin management from spring-boot-starter-parent and at the
same time have a custom parent for all my projects where I could define some other common dependencies or if needed override the dependencies defined in the
spring-boot-starter-parent which would then be inherited by all my projects.
Does this design make sense or am I missing something.
What are the drawbacks of this approach?
There are no drawbacks -- this is exactly what you're meant to do if you want a multimodule spring-boot project. However, consider this: typically multi-module projects have all modules versioned together, released together, and dependant on each other. This rarely makes sense in a group of spring-boot modules, which are typically of the micro-service style and which require independent evolution. So, you should question your need for a multi-module project at all.

Combine two maven project

I Implemented two maven project each using spring MVC, Hibernate, Jax-RS service. they have separate configuration, database, controllers, models, services.
I need to combine both the project in such a way that one is work as parent and other should be its child and can access parent services.
If you want to share configuration among projects, you can use a parent pom.
If you want to combine two projects as subprojects of one larger one, you can use modules. Both concepts are described in
https://maven.apache.org/guides/introduction/introduction-to-the-pom.html#Project_Inheritance_vs_Project_Aggregation
If you want to access classes from project in another project, add a dependency in the dependencies section of your pom.

Maven include another pom for plugin configuration

is there a way to include another pom or information in a maven pom ?
I have several poms which are basically not related or have different parent poms. Nevertheless for packaging it is required to have a Manifest identical to all projects.
So currently I have in a pom:
<plugin>
<artifactId>maven-assembly-plugin>
<!--- .... -->
<archive>
<manifestEntries>
<build-date>....</build-date>
<build-nr>.....</build-nr>
etc etc
I would like to avoid to paste this configuration to all severall poms.
So how can I share the configuration of a plugin without inheritance ?
Thanks
One way to do this is using pluginManagement section. plugin configurations can be defined in this section in a parent pom and will be available to inherited poms to be used as is or overridden.
Here is the relevant maven documentation. In your specific case, you would need to organize your projects/poms suitably.
The only correct answer is to use inheritance. Have an inherited ancestor with this configuration in it. Since you have existing parent POMs, these must inherit from this new parent. If this isn't possible then rethink the hierarchy of your Maven projects, or else you'll have to copy and paste the same configuration into each file and add a comment indicating the section must not be modified / must be maintained consistently with [insert list of projects here].
TLDR; Inheritance is designed specifically to resolve situations such as yours. If you can't use it then don't try to hack around it - either restructure your POMs or copy and paste!

Resources