Maven release and recomposed POM family - maven

I'm having some issues running the Maven release plugin in my company's specific maven structure. Let me explain the concept of recomposed family I'm referring to. My projects are multimodule projects, where each module may have a different parent than its natural father.
project/
pom.xml (the natural multimodule reactor father) (I list as modules all that follows)
module1/pom.xml (my parent is NOT ../pom.xml, I'm a half sibling)
module2/pom.xml (my parent is ../pom.xml, I'm a natural child) (I have a dependency on module1)
project-war/pom.xml (my parent is NOT ../pom.xml, I'm a half sibling)
The reason we adopt this "foster parent" strategy, is that we want to activate some plugins by default for some specific "adopted siblings". For example, every WAR projects needs to define a specific maven-resource-plugin execution ID. Since we have about 80 WARs to generate, imagine the maintenance if we are to add an extra execution step to ALL WARs. This works well for development purposes, we do have valid and running SNAPSHOTs building and deploying.
Now that we want to release, the maven-release-plugin seems not to like this specific structure. In short, since module2 needs module1, but module1 has a different father, release plugin keeps module1 as a SNAPSHOT.
My question here is, has anyone manage to release a projects with recomposed family members? Is there any configuration that I need in the release plugin to enable a full release of such projects?

Violating the inheritance between modules are parent is going to give you more problems than anything else.
Your only options here are either:
fix the parent-children model so the release plugin can do its job (and then move those module activations to the children where you want it)
do the tagging, changing of versions, build+release (mvn deploy , and optionally also site-deploy) manually

After some further tests, here are my conclusions about this issue.
The recomposed family CAN be tackled by Maven on a simple condition: ALL members of the family are present in the reactor.
That would mean having a "super-reactor" that has a reference to both the project you want to release, and the parent poms that may be declared by some modules. Of course, the release plugin will then release everything in this super reactor. If you have many projects that all refer the same parent projects, you should release them in one shot.
Moreover, for the build model to be generated correctly, all relative paths must be right. In my specific case, we wanted to avoid such a thing, I guess we are back to setting a fixed folder structure.
It could be handy to exclude some projects from the release plugin, but of course that creates a potential instability.

Related

Multi Project Maven using single POM

I have various projects (lets say Project 1, project 2, project 3 etc....). They are in different repositories in the BitBucket.
Some of these Projects share the same Versions. I wanted to check if I can use a Super Parent POM ? I want the Projects to listen to the Parent POM for Version changes, is this possible ? Did google around however dint find any useful information on this.
Any pointers will be helpful
Thanks,
You can use one parent POM for all you projects no matter where you store them. The only requirement is that that POM is deployed in a Maven repository and is available in any of that projects. It can be Maven Central or JCenter or your corporate Maven repository like Artifactory or Nexus. Actually, a lot of open-source projects depend on so-called oss-parent POMs. Take a look at Guava, for example, it depends on sonatype/oss-parents. Some companies make their own parents, like FasterXML.
The answer to second question is generally "no". You cannot simply "watch" for the version changes in such parent POMs, unless you:
Own them. The easiest way. You can trigger downstream builds, or fire alarms, or automatically create issues / tickets in children POMs whenever you update parent POM.
Configure you CI/CD to do that. Basically, it's the same as 1, but you just have to watch for the updates and trigger things.
Use third-party service that will do that. Once, there was one called VersionEye, but they are gone. I've heard that Snyk is doing something similar.

Maven: can a child module of a multi-module parent project be used in another completely separate project?

EDIT: I have changed this question so that it is not simply a duplicate of Can maven projects have multiple parents? (the answers for which seems to assert that a module can't have 2 parents)
Q: Maven: can a child module of a multi-module parent project be used in another completely separate project ?
Consider a ChildCommon project that is an API module or common implementation library to be shared by many projects.
There are at least 2 possibilities:
Case1: If 2 parents are allowed (with Maven 3.3.3):
ParentA
|--ChildCommon
ParentB
|--ChildCommon
Case2: Instead of 2 parents, a completely separate project depends directly on the child module:
ParentA
|--ChildCommon
ProjectB dependsOn ChildCommon [EDIT: ANSWER IS, YES, THIS WAY WORKS]
And if so, if part of the Maven build spec for the ChildCommon module has been siphoned off (up) into ParentA, how does one ensure the correct Maven spec is used when it is used by ParentB or ProjectB (without having to repeat things from ParentA brute force) ?
[EDIT: Answer is that Maven handles that perfectly via the "externally" referenced child's parent POM.]
EDIT: Expanding: My aim is to have my POM Optimizing and Refactoring cake using a parent POM and eat it. I have a set of 6 core modules that work together to nicely achieve the modularisation I need to develop a core web app system:
CoreLib, CoreAll, CoreImp, CoreAPI, CoreEJB, CoreWeb
CoreWeb runs as a standalone web app, and can also be reused by other web apps using overlays.
I won't go into here why I need 6, but it's in fact elegant for my case. It is however wearisome having to sometimes clean and build each one. It is also error-prone repeating certain artifact versions in each pom.xml (my main concern).
A specific web app combo leverages (at least some of) the above core modules (including CoreWeb):
SpecAPI, SpecEJB, SpecWeb
But another applications (a non-web one) might leverage only a subset of the core ones such as CoreAll, CoreImp, and would not under any circumstances want coupling to, for example, CoreWeb.
If you have a child project/module ChildCommon with a parent POM project:
ParentA
|--ChildCommon
You MAY reference ChildCommon to reuse it in another project ProjectB without adverse side-effects such as cascading to all other children of ParentA.

MAVEN: Multi-module project, How to add different environments for build

There is a complex multi module project I am working on to move from ant.
Things we want to achieve are:
Ease of development, and packaging for developer.
Example: Parent Project
SON A
Parent Project
SON
GRANDSON A
GRANDSON B
DAUGTER (DEPENDS ON SON)
GRANDSON C
GRANDSON D
What I want is that when a developer is working on Daughter Project he just downloads the parent project and the SON dependency should be resolved from svn repository. I know it can be done by defining dependecy in pom.xml but that will conflict with my second requirement.
2) To download all daughters and sons of the parent project and compile them so that build consistently can be checked by automated build manager like Jenkins. And in addition I would also like to release the revisions on a flag to the maven repository if the build is successful. Please note that revision needs to be head of each module.
3) In both the procedure I want to create a tar file or my own style directories which will contain different jars in different directory as per my need. (I can achieve this by adding ant copy command; any better Idea on same)
What are the standard approaches in maven to achieve it.
In your Maven hierarchy, only the leaf projects (the grandchildren in your example) will be actual modules that contain code and produce an artifact (e.g. a jar). The internal nodes (Parent, Son, Daughter) will only be used to hold common configuration and dependencies that are shared by modules down the hierarchy. Therefore, Daughter cannot depend on Son, but Grandson C can depend on Grandson A, for instance.
If the parent project hierarchy have their own life cycle, i.e. the poms can be released independently, they should be on their on SVN module. Developers working on submodules do not even need to download these poms, as they would be automatically retrieved from your Archiva, if they are deployed there by Jenkins. See this answer for a similar situation.
However, you see to indicate you wish to build and release all modules are the same time. In this case, you can have the same pom hierarchy by keep all projects in the same SVN repository.

Maven dependency vs multimodule?

Very new to Maven, can someone please explain to me the difference between using maven modules vs just adding a dependency to your maven project to another maven project in your workspace? When would you use one over the other?
A dependency is a pre-built entity. You get the artifact for that dependency from Maven Central (or Nexus or the like.) It is common to use dependencies for code that belongs to other teams or projects. For example, suppose you need a CSV library in Android. You'd pull it as a dependency.
A Maven module gets built just like your project does. It is common to use Maven modules for components that the project owns. For example, maybe your project creates three jar files.
A dependency can be thought of as a lib/jar (aka Artifact in Maven parlance) that you need to use for building and/or running your code.
This artifact can either be built by your one of the modules of your multi module project or a third party pre-build library (for example log4j).
One of the concepts of maven is that each module is going to output a single artifact (say a jar). So in case of a complex project it is good idea to split your project to multiple modules. And these modules can be dependent on each other via declared dependencies.
See http://books.sonatype.com/mvnex-book/reference/multimodule-sect-intro.html for example of how a web app is split to parent and child modules and how they are linked.
One of the most confusing aspects of Maven is the fact that the parent pom can act as both a parent and as an aggregator.
99% of the functionality you think about in Maven is the parent pom aspect, where you inherit things like repositories, plugins, and most importantly, dependencies.
Dependencies are hard, tangible relationships between your libs that are evaluated during each build. If you think of your software as a meal, it's basically saying A requires ingredient B.
So let's say you're preparing lasagne. Then your dependency chain would look something like this:
lasagne
<- meatSauce
<- groundBeef
<- tomatoPaste
<- cheese
<- noodles
The key thing is, each of the above items (meatSause, groundBeef, cheese, etc) are individual builds that have their individual set of dependencies.
By contrast, the only section of your pom that pertains to aggregation is the modules section:
<modules>
<module>meatSauce</module>
<module>groundBeef</module>
<module>tomatoPaste</module>
<module>cheese</module>
<module>noodles</module>
</modules>
Aggregation simply tells your build engine that it should run these 5 builds in rapid succession:
groundBeef -> tomatoPaste -> cheese -> noodles -> meatSauce
The main benefit of aggregation is the convenience (just click build once) and ensuring the builds are in the correct order (e.g. you wouldn't want to build meatSauce before tomatoPaste).
Here's the thing though: even if you organize the libs as standalone projects without module aggregation, your build will still come out the same provided you build in the correct order.
Moreover, both Jenkins and Eclipse have mechanisms for triggering builds if a dependent project has changed (e.g. changing groundBeef will automatically trigger meatSauce).
Therefore if you're building out of Jenkins or Eclipse, there is no need for aggregation

Maven : Multimodule projects and versioning

What are the best practices for software versioning and multimodules projects with Maven?
I mean, when I create a multimodules project with Maven, what is the best approach for the versioning? To use a single version for all the modules (defined in the top project)? To use a version for each module (defined in the POM of each module)? Is there another approach that I'm missing? What are the pros and cons of each approach?
In general, are the different modules released together (possibly sharing the same version number)?
Thanks
Honestly it depends on what you would like to do. Multimodule projects are created for multiple reasons, one of them being you only need to deploy what has changed instead of all modules.
Think about it this way: if you had a non-multi-module project and you only had to change one line in the services layer, you have to rebuild the entire project and deploy all of the code again...even though only your services layer will change.
With multi-module projects, you can regenerate your project and deploy only what changed...your services. This reduces risk and you're assured that only your services module changed.
You also have a multitude of benefits to using multi-module projects that I'm not listing here but there is certainly a huge benefit to NOT keeping your version numbers of your modules in sync.
When you build your project, consider deploying it to a repository that will hold all compatible jars together for builds (each build creates a new folder with the parent-most pom version number). That way, you don't need to keep documentation about which jars are compatible...they're all just deployed together with a build number.
I was looking for a solution for this exact problem myself and versions-maven-plugin was exactly what I needed. I don't like the release plugin communicating with the SCM system. The versions plugin does just what we need: it sets a new version number in all poms of the project:
mvn versions:set -DnewVersion=2.0.0
Then I can proceed with commits, tags and an official build server build...
EDIT:
The versions plugin depends on how a maven multi-module project has been organised: as a result, it often does not update all POM files in a complex multi-module project.
I've found that sed and find do the job much more reliably:
sed -i 's/1.0.0-SNAPSHOT/1.0.0-RC1/g' `find . -name 'pom.xml'`
Typically you create a multi-module project because you have deemed that the various modules are parts of a single whole. Maybe the client-piece, the controller-piece and the services-piece. Or maybe the UI with services.
In any case, it makes sense to have the version numbers for the various modules to move in lock-step. However Maven does not enforce that as a rule.
As to your question
are the different modules released together (possibly sharing the same
version number)
I would think so. That is one of the reasons for having it a multi-module project. Otherwise you could have the modules as independent projects.
Of course this is the kind of stuff that is rife with edge cases and exceptions ;-)
I had the same problem with a project I`m working on. I also decided to use separate versions and even the dependency to the parent pom only has to be updated if some of the managed dependencies change. (so mostly as #vinnybad describes it)
Two additions
exists-maven-plugin
With the usage of the "org.honton.chas.exists-maven-plugin" only the modules will be deployed to the repository that have actually changed, which is really great, because also the according docker-images will only be published if something has changed on one of the service. This avoids "polluting" the image repository with different but unchanged versions.
versioning
One main downside of the "separated versions" approach are the questions regarding versioning:
What's the current version of my project?
Which module versions work with each other? (even thought they don't directly depend on each other, one does rely on what another does, e.g. they share the database schema)
To solve that I put all module versions into the dependency management part of the parent pom, even if no other module depends on them. A "integration-test" module could solve that by depending on all of the modules - and of course testing them together.
This way I would be "forced" to update the parent pom with every change, since it's referring the released module versions. This way the parent pom would have the "leading" version and at the dependency-management block state the versions of all modules that are compatible with each other (which will be ensured by the integration test).

Resources