I manage a Maven POM project, that (as usual with POM projects) consists of 1 file: pom.xml. There are multiple other projects that inherit settings from this POM. The parent pom does not function as an aggregator; there are no modules defined in it.
Since the POM project has a different release cylce and version history than the projects depending on it, it seems logical to me to put it in a separate SCM repository. The idea is that an automated build job will be triggered on a commit, which can then lead to a release of the new POM to the central artifact repository (Nexus). This leads to the situation where I have a Git repo with 1 file.
Question: Is this the normal/desired way to handle source code versioning of a POM project?
A common gloal (or enterprise) parent pom is to be considered like a separated product, it's an artifact on its own, with its own lifecyle and CI job (publishing it to a Maven repository, like Nexus in your case) and as such also with its own version control repository.
Moreover, it may also not be a repository with only one single file, the essensial pom.xml file, but also provide further resources. For example, a site folder, with its site.xml file specifying an additional report or section. In case of a git repository, it should also provide a well documented README.md file.
From experience, since a global Maven parent POM is used by many different projects, it is also good to take care of its versioning and release notes. For this reasons I would suggest to have the following:
A site folder with the following site.xml configuration (as an example):
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/DECORATION/1.4.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/DECORATION/1.4.0
http://maven.apache.org/xsd/decoration-1.4.0.xsd">
<body>
<menu ref="reports" />
<menu name="Release Notes">
<item name="0.0.1" href="release-notes-0.0.1.html" />
</menu>
</body>
</project>
An additional markdown folder under site providing release notes for each version. For example, form the href above, the following file will be picked up: release-notes-0.0.1.md.vm, providing information about its release, which will then end up in the Maven site of the POM.
As you can see, the repository may contain more than the single pom.xml file even for a super parent POM. Hence, it should always have its own version control (git in this case) repository.
Additional notes:
A global parent POM is normally applying the -parent suffix (e.g. maven-parent, spring-parent, hibernate-parent). Although not a standard, it's a de fact convention, recommended to follow
Preferably, follow the Maven official layout for the POM sections
From personal experience, avoid having SNAPSHOT versions: better to have multiple minor (but fixed) versions of a common parent POM rather than unstable or potentially impacting SNAPSHOT versions: it's the global parent pom, its goal is to provide governance and common minimal configuration, it should not introduce instability.
You will find a detailed solution here
Single click code-versioning (Complimenting cloud-native Architecture)
The idea is to use the maven plugin jgit-flow plugin and using Jenkins and this plugin we have created the whole pipeline to automate this process.
Related
This question is for getting feedback on a suggested versioning system for a multi-module java application built using Maven.
We have developed a multi-jar system (micro-services) with about 15 modules/jars. Some of them (5) are libraries used by the other modules in the system but not outside of the system. The modules are all stored in separate git repositories.
We have released first version and need to get serious with branching/versioning.
Goal: Minimize work needed to be done regarding versioning (updating version numbers, manual merge because of different version information per branch, etc).
How: Modules are identified by module name and git branch name, not by module name and version
We build our own "version-files" saved as resources in each module. These contain build time, git commit-id, branch name, build URL, etc, for the module itself plus included modules. So we have no need for any Maven version number after deployment.
Note: For library modules outside the system we use standard approach both for internally developed and externally developed modules. Ie. strict numbered versioning using Maven dependency system.
The system I'm contemplating is to
always use the version number <branch-name>-SNAPSHOTin the pom files, plus configuring Maven to always fetch latest SNAPSHOT version (not only daily as it does by default - ref. What exactly is a Maven Snapshot and why do we need it?).
Use a BOM (ref. Maven BOM [Bill Of Materials] Dependency) to define dependencies.
The pom file for a module in this system will be similar to:
<project>
...
<version>${revision}</version>
<dependencies>
<dependency>
<groupId>mygroup</groupId>
<artifactId>bom</artifactId>
<version>${revision}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
<properties>
<revision>default_version</revision>
<properties>
</project>
This version is specified during build by executing mvn using similar to: mvn deploy -Drevision=<branch-name>-SNAPSHOT (ref: https://maven.apache.org/maven-ci-friendly.html).
As the pom shows, we will (mostly) have one BOM version per branch name used in the system, with version name <branch-name>-SNAPSHOT - same as the module itself. The BOM file should include dependencies using explicit versions, also for system internal modules.
Example flows:
A simple feature branch. In branch modify pom so the BOM reference refer to same as parent branch - replace ${revision} for the BOM reference. Ie. you don't need a separate BOM (yet...)
A simple feature branch for internal library. Same as previous, but you should probably create same branch for a module using this library and a same branch for BOM ensuring the two modules are linked.
A system release. Create a release branch on all modules (git repositories). Including the BOM module. E.g: release201810. In BOM file in branch release201810 ensure that all referenced system-internal modules are referred to using version release201810-SNAPSHOT.
Parallell development. Create custom branch on modules as needed. Update the custom BOM as modules are branched for this development.
Is this a good idea?
I have some concerns:
You usually put the whole multi-module project into one git repository. Then you branch on the whole project, not on single modules.
The whole project usually has a version number in x.y.z-SNAPSHOT form which is increased over the time. Releases should be built with release versions, while during development you can have SNAPSHOT versions.
It is possible to build branches as x.y.z-branchname-SNAPSHOT, but dropping the version number all together is very non-standard.
I must say that every time I deviated from the standard (for good reasons, like legacy structures in the company), it caused problems later.
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.
I want to publish my Java project on GitHub. I'm not sure if I should upload my pom.xml from Maven in my repository.
I'm using Eclipse without eGit.
On the one hand:
the pom.xml is necessary to know which libraries I used.
On the other hand:
it's a configuration file which maybe shouldn't made public.
it destroys the look of a clean repo, because it's outside of the normal source files.
What should I do best?
it's a configuration file which maybe shouldn't made public.
This is wrong. The POM is indeed a configuration file but it is intended for this file to be public. Actually, quoting Maven guide to uploading artifacts to the Central Repository:
Some folks have asked why do we require all this information in the POM for deployed artifacts so here's a small explanation. The POM being deployed with the artifact is part of the process to make transitive dependencies a reality in Maven. The logic for getting transitive dependencies working is really not that hard, the problem is getting the data. The other applications that are made possible by having all the POMs available for artifacts are vast, so by placing them into the repository as part of the process we open up the doors to new ideas that involve unified access to project POMs.
As you see, this file is actually required so that the artifact can be uploaded to Maven Central.
What should not be public is your settings, i.e. the settings.xml file. It is in this file that you should store any sensitive information, like passwords. Again, quoting the Settings Reference (emphasis mine):
The settings element in the settings.xml file contains elements used to define values which configure Maven execution in various ways, like the pom.xml, but should not be bundled to any specific project, or distributed to an audience. These include values such as the local repository location, alternate remote repository servers, and authentication information.
If you currently store any sensitive information in your POM, you should consider refactoring it to extract this info and put it inside your settings instead.
it destroys the look of a clean repo, because it's outside of the normal source files.
It is a source file in the sense that Maven only requirement is exactly the presence of this file. It describes how to build your application and declares all of its dependencies. To say it differently: this file is a Maven source file, and as such, should be commited along with the project main source files. Without it, no-one can build your application and no-one can also package it.
There are a lot of questions about this, but the answers seem to contradict each other. So I wanted to ask it for my version of Maven (3.0.4).
I have a JAR file that's not part of any maven repository. It's a local dependency. I understand there are two ways to add it to my Maven project.
Add it as a dependency and specify the file path in the <systemPath> property. (No other work needed.)
Create a local repository <my-project>/repo and install the JAR in this repository. Then, add the new repository in my pom.xml file and add the new dependency.
I'm curious which way is better practice? I've heard some negative things about the <systemPath> property, although that way looks faster.
The answer is, it depends...
If you add it as a system dependency it is likely to become path dependent which makes it more difficult to share among other developers. Sure you can also distribute the 3rd party jar relative to your POM via your SCM but the intention of systemPath is more for dependencies that are provided by the JDK or the VM. From the docs about systemPath:
They are usually used to tell Maven about dependencies which are provided by the JDK or the VM. Thus, system dependencies are especially useful for resolving dependencies on artifacts which are now provided by the JDK, but where available as separate downloads earlier.
To install the jar in the local repo is also not friendly for sharing. It requires all developers to "upload" the jar to their local repo before building. You can of course add a script that handles this for you but it is always easy to forget to upload and IMO a better solution is point 3 below. The local install process is described here.
If you are working in an organization where the developers share the POM you should upload the 3rd party jar to a local repository manager. That way you can easily work with the 3rd party jar as if using any other maven enabled jar. Check this link for a comprehensive list on repository managers.
To summarize, if you are sharing the POM with others I would suggest that you upload it to a local repository manager. Otherwise the second option can work for you. As a last option, I would fall back to option number 1.
Also note that this has nothing to do with which version of Maven you are running.
You can add jar to your local maven repository. Usually it located at:
$home_directory/.m2/repository
For example you have expample.jar and you want to add it to your pom as:
<dependency>
<groupId>com.example</groupId>
<artifactId>example</artifactId>
<version>1.0</version>
</dependency>
Then you must add example.jar to:
$home_directory/.m2/repository/com/example/1.0/example.jar
In my case NetBeans do it for me.
The best way I see so far is to use install:install-file goal with maven. You can use the mvn command line to execute it directly with appropriate parameters, or if you are using eclipse EE, you can do so by leveraging the embedded maven and creating a Run Configuration as follows:
Then, you include the jar as follows:
<dependency>
<groupId>mylocal.weka</groupId>
<artifactId>weka</artifactId>
<version>1.0</version>
</dependency>
Of course adjust the parameters as per your needs.
Best,
Haytham
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.