Multi Project Maven using single POM - maven

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.

Related

Skipping a Maven module that's already been published to Maven Central

Let's say I have an aggregate Maven project. com.example:foo:1.0.0 is the aggregate parent POM, and it contains the child project com.example:bar:2.0.0. I publish them both to Maven Central using the nexus-staging-maven-plugin. Note that I do not use dependency management in the parent POM for the version of com.example:bar:2.0.0, even though it is a child project. That is, the two versions are not tied together.
I also use com.example:foo:1.0.0 as the parent POM in other projects, so I would prefer that its coordinates don't change unnecessarily (e.g. be published multiple times with different coordinates, even if the contents have not changed).
It turns out that com.example:bar:2.0.0 changes quite frequently, so I want to release com.example:bar:2.1.0. But I will be building from the aggregate parent POM in that repository, com.example:foo:1.0.0. Must I increment the version of the parent POM as well, even though the parent POM has not changed, and even though the versions are not tied to each other in any way? I would prefer to have the nexus-staging-maven-plugin simply realize that com.example:foo:1.0.0 has already been published, skip it, and continue and publish com.example:bar:2.1.0.
This question also extends to a sibling module that has already been published. Is there some way to configure nexus-staging-maven-plugin to skip a module that has already been published, yet continue building and publishing the other sibling projects that have not been published yet?
From this simplified example I'm sure someone will be tempted to answer, "but you shouldn't do it like that". In my more complex example, there are reasons it might be advantageous to do it like I'm explaining; and besides, that response would still leave the actual question unanswered.
I also realize that I could do some tests to see what happens, and perhaps I will, but I'm posting the question here to 1) get an authoritative answer, 2) promote discussion of the options, and 3) leave some definitive answer here for other who might have the same question. Thank you.
AFAIK, the nexus-staging-maven-plugin does not have a user property to detach or ignore certain artifacts.
You may be able to write your own plugin that takes the Maven project and eliminates a certain artifact from it.

List users of an artifact in a repository

I need a tool that will help to find all artifacts that reference another artifact.
When I rebuild an artifact, I need to update/rebuild all artifacts that were using the old version. But I work in a big organisation, and nobody knows really where the artifact is spread in the organisation, so nobody is ever completely sure that everybody use the latest versions.
What I need would be a tool - maybe an artifactory plugin or feature, or a maven plugin doing a lookup in the repository - that indexes all the known poms, and is able to make a listing of all artifacts that have the updated artifact in their dependencies, either directly and transitively. Thus a list of artifacts I would need to rebuild. Quite the opposite of dependency:tree.
Filtering that list by repository, groupId, packaging, etc. is a nice to have. But I can live without.
Any idea?
You can use the Artifactory Query Language with the REST API to do that. For example, if you want to find all builds that use "MySuperAwesomeDependency-1.0.2" your AQL statement would be something like:
//Find builds that use a dependency that is a snapshot
builds.find({"module.dependency.item.name":{"$match":"MySuperAwesomeDependency-1.0.2*"}})
The key in the above statement would be the module.dependency.item.name, which allows you to search for dependencies by name, assuming you store the dependencies in Artifactory.

Maven release and recomposed POM family

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.

Moving a project to Maven Central

I manage many maven projects. Most of them deploy to our internal maven repository. Now I would like to start releasing one project to Maven Central. Up until now, I have had a parent POM that specified the distributionManagement of our internal repository. It doesn't make sense to deploy this information to Maven Central.
How should I specify the distribution management for my internal projects? Should I have a seperate parent pom group-internal for internal projects?
Sonatype mentions a way to deploy directly to their repositories, but they recommend using their own parent pom (oss-parent). Looking at projects using mvnrepository.org, I couldn't find any projects with oss-parent as the parent. Do most project manually deploy their artifacts to Sonatype? Where and how do they deploy them first?
So many questions! I'm amazed at how complicates this is...
Update: it turns out some of the projects I identified do use oss-parent. It's just hidden as it's the parent of a parent.
Once you are all set up, you can deploy staged releases and SNAPSHOTs directly to Sonatype's OSS repository. Stages releases can then be released through Sonatype's Nexus UI.
To create a repository folder for your application to which you can deploy, you open a ticket with Sonatype on their JIRA along with a reference to the open-source project you will deploy. The process is very smooth and Sonatype will help you if you don't supply all the necessary information.
While on first glace it doesn't look like many projects have oss-parent as a parent, they often do when you navigate up the POM tree. For example, Google Guava has the parent guava-parent, which has the parent oss-parent. Once your project has oss-parent and the repository is configured, you can easily deploy SNAPSHOTs and releases with mvn deploy or mvn release:prepare release:perform.
It seems overwhelming, but it's easily understood if you just plow through the steps for the first time.
The first I recommend to read is the following:
https://docs.sonatype.org/display/Repository/Sonatype+OSS+Maven+Repository+Usage+Guide
The OSS parent makes under special circumstance sense under other not. That depends what kind of project you like to distribute.
UPDATE: That link is dead now. Look here for help deploying to Sonatype.
UPDATE: For Maven Central check this: http://central.sonatype.org/

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