Factoring out common elements of Maven pom.xml - java

I have a number of Maven pom.xml files in various projects that contain a lot of similar configuration (license declarations, plugins, defintion of resource folders etc.)
What is the best approach to factor out these common elements into a parent pom and have them available for re-use?
I'm particularly interested in:
What should go in the parent pom vs. being project specific?
Where to store the parent pom, e.g. on GitHub?
Any gotchas to be aware of?

For enterprise projects, you can use Maven to deploy your parent pom on a artifact repository like Sonatype Nexus. But this can be cumbersome for just personal projects.
Everything that needs to be shared must be in parent pom.

Related

When to create maven submodules

At the moment I'm working in a project which contains out of 260 maven submodules under one parent pom. This seems to slow down the build. That's why I came up with the question when should I use submodules and when shouldn't I use it.
Introduction to the POM says:
If you have several Maven projects, and they all have similar configurations, you can refactor your projects by pulling out those similar configurations and making a parent project. Thus, all you have to do is to let your Maven projects inherit that parent project, and those configurations would then be applied to all of them.
And if you have a group of projects that are built or processed together, you can create a parent project and have that parent project declare those projects as its modules. By doing so, you'd only have to build the parent and the rest will follow.
Create submodules when:
projects share the same configuration, to avoid configuration duplication
projects are interconnected, to make building easier
This question is a bit broad because it is hard to set a general rule.
My rule of thumb:
"A multi-module project consists of those modules/artifacts that should always be built together".
If you just want to share configuration, you can use a parent POM without using multi-module.

Maven self-contained child artifact

I have a project which has 3 pom files: parent file (very basic one, just declares its children), main pom for building project itself and a pom file for generating swagger client library. The client artifact is getting downloaded into our Nexus.
The problem is that when I want to use a client library in another project as a dependency it also requires a parent artifact. I don't want to download it into Nexus since it's so basic and will only flood the repository. I've tried packing some kind of an uber-jar, but it doesn't work for me - jar is huge and contains all dependencies, yet it still needs parent artifact. Are there any workarounds?
While I generally would not care about having an additional Parent POM in the repository (our repository contains 2000 different self-created artifacts in various versions, it is not "flooded"), you can have a look at the
https://www.mojohaus.org/flatten-maven-plugin/
which allows you to make your pom smaller, and includes the possibility to get away without a Parent POM.

How to depend on multiple projects in a maven library?

My project depends on an external library, which consists of a number of maven projects.
Do I have to define each of the projects in the library to be a module in my project's parent pom.xml? Is there a way to define the library as a whole in my project without individually listing all the projects?
My project directly depends on only one project in the library, but that project depends on other projects in the library.
Do I need to define all the projects in the library in my project's dependencies?
Ideally, in parent pom you define modules i.e, external libraries which you want to build. When you build the parent pom, it will build all modules which are defined in parent pom. And further, modules will build other dependencies/modules.
You need a composite pom -- a pom which just declares a bunch of dependencies. You depend on it, and transitively, you get its dependencies.
See this discussion for more information.

Is Maven a good solution for my Application

I'm developing on an java application that consists on a main-application that is loading extensions (jars) at runtime. Each extension is a java project.
all jars have the main application in class path and other libraries. The manifest of the main application also has dependencies in the manifest classpath, e.g. sqldriver, poi,log4j etc.
Everytime I change on of the lib, i have to set all classpaths of the projects. Also if i want to build all the jars, i have to export each project once.
So I thought maybe is Maven a good solution for me. So I've installed m2eclipse and converted the projects to maven projects.
But for now i have for each projekt an own pom.xml and i also have to build all projects once.
I'm new to Maven and searching for best practises for my problem. So I'll thank you for your help and advice
Make all your projects modules of one parent pom project. This way you can build them all at the same time.
You can use a hierarchy for your pom files. Here's an older question (similar to yours) that has a great example in the answers:
Maven: POM modules and submodules hierarchy
Basically this structure:
<project>
<parent>...
</parent>
<artifactId>module</artifactId>
<packaging>pom</packaging>
<name>Module</name>
<modules>
<module>submodule</module>
</modules>
(...)
</project>
in a 'root' pom.xml file, besides the actual submodule pom.xml files.
Unless you really, really need OSGi , Maven is great. If you're doing OSGi maven is less great.
M2eclipse however is less helpful, and in my experience only leads to confusing headaches.
How you should build your projects depends on a few things. I agree that the submodule approach described in the other answers is best-practice, and if all your sub-module candidates are related (for instance, each represents a tier in a n-tiered application), in the same SCM repository, and the interfaces change often, and the versions are co-dependant then by all means, you should do that.
If however your submodules are stand-alone and don't have a lot of transitive dependencies, particularly if they are in separate SCM repositories, they are independently versioned, and you have a little spare hardware for a build server (like say Hudson) and a Maven2 artifactory (like Sonatype Nexus), you could just keep them as seperate projects, and let maven handle the rest. This way you avoid having to re-build everything because you made a small change in one of the submodules. You can just build that one.

Packaging jar is invalid Aggregator project need pom as packaging

My project has different modules.
Each module has a pom.xml which specifies jar packaging.
Each pom refers to common parent.
In the parent module there is also a pom.xml which includes all the modules.
When I tried to package using the pom.xml of the parent module, it shows the error - "Packaging jar is invalid Aggregator project need pom as packaging".
What can I do to make an executable jar of the application from maven?
To make things short: if your parent-aggregator project don't contains source code (and it's a good practice), just add this to your parent pom.xml:
<packaging>pom</packaging>
If the parent project contains source code, I strongly suggest you to:
move this code in a new module (let's call it commons)
make commons a child module of your parent project
add the commons module as a dependency of all other modules requiring it (maybe all of them)
add <packaging>pom</packaging> in the parent pom.xml
Maven requires the parent to be of packaging pom.
You can make a pom project behave as if it were a jar project, by including a bunch of plugin executions and attaching them to their subsequent lifecycle phase. It's not a happy road. On the contrary, the following is.
From an object oriented standpoint, what is it that you want? You have one object that is made up out of a bunch of other objects, right? In other words composition, as opposed to inheritance.
Your final delivery is made up out of the other (jar) projects, i.e. the other projects are dependencies of the final delivery project. You will define the other projects each as dependency so that whomever uses your final delivery knows what (transitive) dependencies to get. Alternatively the final delivery jar could be packaged up as "uber-jar" and thus contain all its dependencies. That all really depends on how the final delivery is to be used.
At the same time the following two aspects (may) still exist:
The parent project (which is different than the final delivery project, in fact it may be the parent of the final delivery project also) defines commonalities between its subsequent children, as is what you should expect from inheritance. A child is any project that refers to the parent through the parent configuration in its POM.
A project that defines modules that are to be easily built in one go. Modules are projects that are referred by use of modules.module. This is typically (I guess >99%) done in the parent project, but not necessarily. You could put it in the final delivery project also (without affecting inheritance, because that is thus a different beast), but it's atypical and I would not go there.

Categories

Resources