Is it possible to define an "abstract" build in parent pom? - maven

I want to define a build in the parent pom to enforce that build to the children.
Ideally a child pom just does mvn install and applies the build defined at the parent level.
I have 2 problems:
The build makes use of properties that are defined only in children
When I do mvn install on the parent I just want to create the pom and save it on my maven repo, not actually do a build (that should be done in children)
Is it possible to store helper files inside of the parent pom to use them in the child?
Is this possible?

You can define pretty much in the parent POM.
You can define all the plugins in the pluginManagement. You can use the <plugins> section of the parent POM to activate the plugins without using them in the build of the POM itself (with <phase>none</phase> and <inherited>false</inherited> on the execution)
You can build the parent POM and put it in a repository.
You can predefine properties and let child POMs override them.
But you cannot add additional files.

4all who stumbled upon this question only now (like me):
in addition to the possibilities described in the previous answer, you could define profiles in parent project, but activate them only in concrete project, e.g. by overriding profile activation property. This way you can avoid execution of the stuff during the build of the parent.
you could even go further and workaround limitation of additional files (beware, this is evil*):
define helper module(s) in the repository of your parent project
add dependency to the helper module in the profile defined in parent project
unpack helper files using the maven-resources-plugin (copy-resources)
*) why this is evil? - well, if you need a hack like this, it is an indicator that something is wrong with your architecture. Otherwise, if this would be a common requirement, the Maven team would provide a proper way to handle it.

Related

Is it possible to see the actual pom.xml executed, including parent dependencies/plugins?

I need to extract a project from a repository which uses several layers of parent projects. Every parent project adds some dependency or plugins or properties. This is becoming a nightmare as I'm not able to build any more the project, once I've manually added pieces from parent projects.
Is there a way to create a list of all dependencies/plugins/properties which are linked by a single pom.xml so that I can build a portable, single Maven project?
Thanks
You can create the effective pom (https://maven.apache.org/plugins/maven-help-plugin/effective-pom-mojo.html) that is a kind of merge with all parent POMs.
This is useful to understand the complete list and configuration of plugins.
Whether this helps you to build a "portable" Maven project, I don't know. Without the appropriate Maven repositories with all the plugins, dependencies and so on, Maven will not build.
Base concept of Maven is CoC (Convention over Configuration). Maven has a SuperPOM and all model is inherited from that. SuperPOM is located in maven-model-builder jar. Here is the source https://maven.apache.org/ref/3.6.2/maven-model-builder/super-pom.html
Each Maven goal is using a merged model called effective pom. The help plugin has effective-pom goal which displays the full model including parent model(s) and SuperPOM.
So the answer is just run: mvn help:effective-pom command to see actual model.

maven multi-module project execute parent after child

In maven multi-module project can we have parent project to build/execute after child?
We have custom plugin in parent that needs to be executed after child modules are build. Is there any maven life cycle that says to execute plugin after child projects are build ?
Simple answer is: No, cause the parent is always executed first before any child. If your custom plugin needed to have all childs modules have been built you plugin should check this. Furthermore it has to be configured into a separate module which contains all other childs as dependencies to make sure the ordering is correct (Maven is doing this automatically).
And there is no such lifecycle cause the lifecycle is something about step by step but does not defined something about child/parent relationship...
Create a "deploy" module, define your plugin in that module's pom.xml and put this module at the end of modules list.

Maven inheritance and evaluation of properties

Since system scope is said to be deprecated and dangerous, we use a local repository. The repository is in the parent folder and used by most of the submodules. Now including the repo gets messy. Providing the URL is sort of a hack.
We tried ${project.parent.basedir}/repo in the submodules, but this evaluates to nothing. We also tried to set it in the parent pom, ...
<repository>
<id>project_repo</id>
<url>file://${project.basedir}/project_repo</url>
</repository>
but maven decides to ship the url as given to the submodules which in turn evaluate the property. This lead us to the mess of just taking the relative parent dir, forcing the submodules to be subfolders of the parent pom:
<url>file://${project.basedir}/../project_repo</url>
This is problem Y. The question concerning X is, why does maven inherit before evaluation and how can I avoid this?
forcing the submodules to be subfolders of the parent pom
Regardless of other faced issue, this is actually the recommended approach in general, to have a multi-module/aggregation project (the parent) and submodules as subfolders, in order to have one central/entry-point folder (the parent) providing common configuration and governance (its pom.xml file) and modules (subfolders).
but maven decides to ship the url as given to the submodules which in turn evaluate the property.
Indeed project.basedir is evaluated as the folder containing the pom.xml against we are currently building (or sub-building, in case of a module), since the building project is the module at a given time.
From official documentation concerning project.basedir
The directory that the current project resides in.
If you want to always point to the folder from which you launched your build (that is, the aggregator/parent project in this case), you could use session.executionRootDirectory instead.
However, be careful especially if wishing to build a module directly from its directory, you may then run into troubles (path issues): you should always run it from the parent using reactor options like -pl (projects to build).
This is also a trigger for further thoughts: maintenance and readability of the project may suffer this approach. An enterprise Maven repository would then be a better solution.
Further reading on SO:
Maven variable for reactor root
Finding the root directory of a multi module maven reactor project
Update
The question concerning X is, why does maven inherit before evaluation and how can I avoid this?
Concerning your X question, here is the explanation I could find:
The answer relies in the core of a Maven build, the Maven Model Builder:
The effective model builder, with profile activation, inheritance, interpolation, ...
In particular, it performs the following steps in the following order:
phase 1
profile activation
raw model validation
model normalization
profile injection
parent resolution until super-pom
inheritance assembly
model interpolation
url normalization
Bold is mine. That is, it does so because it's made to do so by its model.

How to deploy a parent pom file without executing plugins

I am doing some re-factoring to use parent poms and put common configuration in a common place.
I have a separate git repo to house the parent poms. Some of the common configuration specifies directories/files that will exist relative to the child projects, but not relative to the parent pom (they are in different git repos).
When I try to deploy the pom, one of the plugins is failing because the path does not exist.
How is this supposed to work?
I'd expect that if the artifact has "pom" packaging then it wouldn't actually try to run the plugins (at least that is what I want). Or do the plugins I use need to be responsible for knowing that it is a "pom" artifact?
The parent should, probably, only have pluginManagement, not plugin.
The pluginManagement section of the parent pom is used to share plugin versioning and base configuration across modules. This is in line with the dependency management section of the parent, which allows you to configure versions and exclusions across modules. For example, you could configure the site plugin in the parent to provide a standard look and feel across all modules, while the modules override the site plugin with module specific details.

Maven2: Multiple inheritence or profile selection

I have a Master/Child pom project with many child modules. For some of the child modules I have a series of tasks that only they need to undertake, basically read a properties file to configure a jboss deploy location.
At present I have copied the build section into a few POMs and this is now starting to ring alarm bells. I really should write this once and use it many.
This has set me on a philosphical path.
a) I believe I could create a profile in the master POM and when running the child POMs enable this profile thus using the defined functionality from the Parent POM. This keeps the current structure in place of 1 parent : many children. It also raises the question, could I actually activate that profile in the child POM so that the person doing the build on the child did not have to use a -P command line option?
b) I could change the exisiting parent/master POM in to a grandparent and inherit the master POM into a new parent pom, adding the property reading/jboss deploying facilities to this new parent. The child POMs requiring this functionality would then inherit from the new Parent, giving me a grandfather-father-son inheritence. This would mean that the person doing the build would not need to rememeber the commandline at the cost of another level of inheiritence.
Question is, which method is the "maven way"?
Unfortunately option a) is not supported by Maven. I had a similar situation to solve and tried the child-enables-profile-defined-in-parent bit, only to find it doesn't work; details elsewhere in StackOverflow.
I don't know if there is an official best practice, as I didn't find one when I did my hunt before. I used a combination of grandparent/parent/child POMs and the <pluginManagement> configuration.
I would try <pluginManagement> in your parent POM first. If that doesn't quite meet the need the extra POM level might work. Good luck!

Resources