Modern Maven Pom Templates - maven

Every time I make a new proper project using Maven hosted on Github I have to go look at either one of my own old projects and copy the pom file or I go find a project that I think does a good job and copy there POM file. Then I have to go search and replace things like project name... etc.
Now Maven has a solution to this through archetypes but I have yet to see one that is modern enough such that it:
Uses the release plugin and deploys to SonaType Central Maven reop.
Connects to Github (meaning the scm connections and release plugin work do the right thing)
Makes all three jar artifacts (sources, javadoc, and regular jar)
I have contemplated make some giter8 templates but was hoping somebody already did something like this (most of the g8 templates are for sbt).

You can use com.jcabi:parent:pom which does exactly what you need and many more. It deploys to Sonatype, defines common dependencies with versions, pre-configures most popular plugins, and defines a few useful profiles.
This article explains more: Don't Repeat Yourself in Maven POMs; Use Jcabi-Parent

You could have a look at the parent pom released by Sonatype. It's intended to be used as a parent pom for projects that deploy to oss.sonatype.org (which may or may not be promoted to Maven Central).
When the sonatype-oss-release profile is enabled, it will ensure that sources and javadocs are built. It also includes an example of the <scm> pom element.

It turns out its incredible easy to create your own maven archetype.
Just make a generic project with stuff you like to use
In the project directory run mvn archetype:create-from-project
Generally Maven guesses the right things to make variable but if not you just edit the Velocity templates.
Install your archetype locally with mvn install
To use your new archetype: mvn archetype:generate -DarchetypeGroupId=com.mygroup -DarchetypeArtifactId=my-archetype
Now the only caveat is that there is not very good doc on the web that I could find on the archetype system. Like its unclear what variables you have available to you for Velocity (although most of them are obvious).
http://maven.apache.org/archetype/maven-archetype-plugin/create-from-project-mojo.html

Related

Does "build with local dependencies" exist in Maven without multi-module?

I have a set of applications, all use Maven and the local repository. The applications form a dependency tree using <dependency> in their pom.xml. All of these projects have -SNAPSHOT in their version.
Is it possible for Maven (or some compatible dependency manager) to build an application together with all of its local dependencies whose source changed?
I do not want to create a multi-module project, because:
the projects are exactly libraries, not modules;
I do not want an additional complexity just to have a form of build which is already precisely defined;
I want the process to be dynamic: if a library is mature enough to be put into a remote repository, it would be no more rebuilt with the main project and that's ok.
For now, there is a lot of refactoring, moving code from one library to another etc. and it happens often that substantial parts of the dependency tree need to be rebuilt. I thus need to manually write mvn install in several projects in order to assure that there is no stale code.
No, it doesn't work. Even with a multi-module project, maven does not detect which modules have changed sources in it and which do not.
There was a (flaky) implementation in Maven 2, but it was not continued in 3.x, see How to get maven 3.0 to only build modules with local scm changes
I hoped they would include it again in maven 4, but I didn't see it yet: https://maarten.mulders.it/2020/11/whats-new-in-maven-4/
I once did a similar setup, but had to use shell scripts with some git magic to get it working.
You can also decide to put your libraries in separate repo's from the start, and use the repo tool that google uses for android development: https://github.com/GerritCodeReview/git-repo/blob/main/README.md
Once you run mvn install on the particular Maven project, it will be accessible for all other Maven projects, which are on the same workstation, during dependency collection (before the compile phase).
Official Maven Build Lifecycle description:
install - install the package into the local repository, for use as a dependency in other projects locally
It's not necessary to keep libraries as part of the same project(or have it as a multi-module project). But once you want to share those libraries with your teammates, you would need either to force them installing libraries locally (as you did), or store those libraries at some external repo, like Artifactory or Nexus

Confused with maven assembly plugin vs build-helper-maven:attach-artifact

I'm a bit confused between maven assembly plugin and build-helper-maven plugin.
I've also read in the maven documentation that The assemblies/archive created by the Assembly Plugin gets deployed during the deployed phase.Hence, they can be deployed to the remote nexus repositories.
The purpose of maven assembly plugin is to archive many things into one(say in tar.gz format).
However, the attach-artifact goal present within build-helper-maven plugin has the same role i.e.archiving,installing and deploying the artifact.
With that being said,why would anyone use both of them together? I've seen people using both of them together. Isn't one of the plugins an alternative choice of the other?
Kindly advise.
If you use maven-assembly-plugin you can create as you already mentioned any kind of archives (range from very simple to very complex structures) they will be by default be attached to your project which means they will be deployed into remote repositories in one go if you do mvn deploy with no supplemental configuration.
The build-helper-maven-plugin is intended to add an artifact (one goal of this plugin) which is usually not generated by Maven itself which most of the cases is a smell. If people using them together (in the use case to create an archive and attach it) this makes no sense.
Apart from that the build-helper-maven-plugin can also be used to add other source directories for example for scala, kotlin projects (other goals for example add-source etc.)
So those plugins are not alternatives they have different intentions/use cases.

Creating Hermetic Maven Builds

I am attempting to create a way in which hermetic builds can be achieved while still relying on SNAPSHOT dependencies in your project.
For the purposes of example, say I have a project which has a dependency structure like this:
┌ other-1.2-SNAPSHOT
mine-1.2.3 ──┤
└ thing-3.1-SNAPSHOT ── gizmo-6.1.3-SNAPSHOT
What I would like to do is resolve all the SNAPSHOT dependencies locally to something which is related to my current version and then deploy those as releases to my Nexus' release repository. Not all of these dependencies are internal so I cannot simply just make a release on each.
So, in this example, other-1.2-SNAPSHOT would become something like other-1.2-mine-1.2.3 and thing-3.1-SNAPSHOT would become thing-3.1-mine-1.2.3. This is relatively trivial in about 60 lines of python.
The problem, however, is in resolving transitive SNAPSHOTs to concrete versions. So I also need to convert gizmo-6.1.3-SNAPSHOT to gizmo-6.1.3-mine.1.2.3 and have thing-3.1-mine-1.2.3 depend on it.
This is only an example of one way in which to achieve what I want. The goal is that in a year or two down the road I can checkout my release branch for version 1.2.3 and be able to run mvn clean package or the like without having to worry about resolving long-since-gone SNAPSHOT dependencies.
It's important that this branch be compilable and not just retain all dependencies using something like the jar-and-dependencies functionality of the assembly plugin. I'd like to potentially be able to modify the source files and make another release build (e.g., applying a hotfix).
So,
Is there anything like this available that will be able to convert SNAPSHOT dependencies in a recursive fashion to be concrete?
Are there any plugins which manage this kind of thing for you? The release plugin had promise with some configuration options on its branch goal but it doesn't resolve external deps to the degree that I want.
Are other techniques available for creating hermetic Maven builds?
This is not a widely used technique, but you can always check your specific SNAPSHOT dependencies into your project as a "project" repository, as described in this blog post: Maven is to Ant as a Nail Gun is to a Hammer
In short, use the Dependencies Plugin to create repository located in your project directory. The below is copied from the linked blog post (which you should read):
1) Run mvn -Dmdep.useRepositoryLayout=true -Dmdep.copyPom=true dependency:copy-dependencies
"This creates /target/dependencies with a repo-like layout of all your projects dependencies"
2) Copy target/dependencies/ to something like libs/
3) Add a repository declaration like the following to your POM:
<repositories>
<repository>
<releases />
<id>snapshots-I-need-forever</id>
<name>snapshots-I-need-forever</name>
<url>file:///${basedir}/libs</url>
</repository>
</repositories>
You make this an automated part of your build/release process: step 1 by configuring the Dependencies plugin to a lifecycle phasephase, and step 2 using AntRun Plugin to move the downloaded dependencies to the right place..
Hope this works for you. I have to go take a shower now...
The maven versions plugin will do most of what you want.
http://mojo.codehaus.org/versions-maven-plugin/
However you will almost certianly need to run it in a pre-build step in which you resolve all the dependencies and update the pom file accordingly. Then re-run maven (which re-reads the pom) to run the real build. You might be able to configure everything within the pom itself triggered with a separate goal thus avoiding a separate script.
This works better if you use particular versions instead of SNAPSHOT dependencies and let the pre-build step upgrade them if necessary. The only real difference for dependency resolution is that maven will always re-download -SNAPSHOT dependencies whereas it will only download normal dependencies if there is a new version available. However many plugins (including the versions plugin) treat -SNAPSHOT dependencies differently causing problems. Since every CI build has a new version number I never use -SNAPSHOT, prefering a different tag like -DEV with more predictable behaviour for things like developer local builds etc.
I've spent a lot of time getting maven to do things similar to this. Most maven projects I know have some kind of pre-build step in order to set version numbers or get around other limitations such as this. Trying to do all this in one step usually fails because maven only reads the pom once, string substitution doesn't work in a few places and the deployed/installed pom doesn't generally doesn't contain the results of string substituion or changes made during the build.

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/

How to make my maven project depend on non maven projects?

I want to create a maven project, which has to depend on a non maven project which in turn depends on 2 other non maven projects. I do not have ownership of any of the other projects and it would not be possible for me to change anything in those projects let alone the structure to conform to the maven structure.
I asked if I could just get jars -- but was told that because of multiple levels of dependency, it would be "difficult" -- although I haven't understood why.
Is this possible or should I just abandon the use of maven to create my project and go with a regular project with jars in the lib folder?
Inxsible
If you can go with a regular project build that means you must have access to the other project's jar files?
It doesn't really matter how the other project builds them, you can still gain more control over your own build process by loading the jars you depend on into a Maven repository.
I'd suggest using one of the following repository managers:
Nexus
Artifactory
Archiva
They'll give you management screens to uploading 3rd party jars, they'll also a more efficient way to use other Maven repositories like Maven Central.
Once you've got your Maven build process working, you could encourage the other projects to automatically publish their versions into your Maven repo.
They could use the ANT tasks provided by the Maven or Apache ivy projects. Worst case you just continue to load their libraries until they see the light :-)

Resources