Maven profiles - dev vs production - maven

I was curious about how to set up development vs production maven profiles. Should I only put the snapshots repo in the dev profile, and the other artifacts (local repo, for releases etc), in the production profile?
What are the major things which different profiles of these types?

The major difference is, obviously, settings among Prod, Test, and Dev profiles. Things like
Database connectivity
Properties like resource settings, thread-pool configuration, log file location and it's size
Storage settings like for local you might have a /mnt/media but for Prod, you may want S3
varies in these profiles.
Now come to release, usually Test profile/s has SNAPSHOT releases (like nightly builds) that is configured to go to SNAPSHOT repository of yours. And a Prod profile is released, usually, using Maven Release Plugin, that automatically knocks the SNAPSHOT off your release version/artifacts. And is configured to store the artifact in RELEASES repo. The configuration for these repos goes like
<profile>
<id>test</id>
<distributionManagement>
<snapshotRepository>
<id>snapshotrepo</id>
<name>Repository for snapshots only</name>
<layout>default</layout>
<uniqueVersion>false</uniqueVersion>
<url>http://repo.company.com/snapshots</url>
</snapshotRepository>
</distributionManagement>
.....
.....
.....
<profile>
<id>prod</id>
</distributionManagement>
<repository>
<id>releaserepo</id>
<name>Final release artifacts</name>
<layout>default</layout>
<uniqueVersion>false</uniqueVersion>
<url>http://repo.company.com/releases</url>
</repository>
</distributionManagement>
....
....
The credential to these repos goes into settings.xml.
Dev profile is usually not configured to release to company repo (as it will be too cluttered of useless artifacts), it just gets installed in your local repo, as SNAPSHOT and overwritten on each build.

Usually (in my experience) the different repos are configured in settings.xml, and not in separate profiles (except maybe in profiles enabled by default).
Example of a default profile:
<profile>
<id>default</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<repositories>
<repository>
<id>central</id>
<url>http://some_url/content/groups/public</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>snapshots</id>
<url>http://some_url/content/groups/public-snapshots</url>
<releases>
<enabled>false</enabled>
</releases>
</repository>
</repositories>
If you are concerned about having SNAPSHOT dependencies in your releases, you can use tools like maven-release-plugin to verify that there are no SNAPSHOT dependencies in your project.
What are the major things which different profiles of these types?
You often use profiles to separate between different build environments. For instance, using a CI you often put plugins for static code analysis, reporting, test coverage etc. in a profile that is only activated when building on the CI server (since it takes more time to run it with these tools enabled).
Another use is to separate out specific part of the application, for instance you don't want the acceptance-test submodule to run on every mvn test, but only sometimes when you enable the mvn test -p acceptanceTests profile
The problem with environment specific builds
Now, profiles are sometimes used to separate configurations like connections strings, enpoints etc. In my view that is not ideal, since you end up with environment specific builds. Sometimes that is hard to avoid, but most of the time this can be solved by externalizing configuration (make sure to have proper configuration management), and use the same binary artifact in dev/test/prod. That way you are sure that the build that passed system test is the same as that in prod etc.

Related

Maven: how to purge a custom local repository

Beside the local repository at the default location, I have another local repository with snapshots of a large number of jars of some projects which do not use Maven. It is defined in pom.xml as follows:
<repositories>
<repository>
<snapshots>
<updatePolicy>always</updatePolicy>
</snapshots>
<id>repo</id>
<url>file:///${project.basedir}/path/to/loca/repo</url>
</repository>
</repositories>
and has a distinct <groupId/> so that it is not confused with any other repository. Thanks to this, the main project can be compiled fast and with up-to-date jars on any system which sees its directory.
I would like to purge old snapshots from the custom repository, but
mvn dependency:purge-local-repository -DlocalRepositoryPath=./path/to/local/repo
purges the local repository at the default location, the custom one is left untouched.
How to purge only the repository in the custom directory?

Why is maven hitting repo.maven.apache.org for local jars?

I have a project built and installed in the local maven repository ~/.m2 named com.example.project. From time to time, not always, when I build another project that depends on com.example.project, maven says in debug messages:
Downloading: https://repo.maven.apache.org/maven2/com/example/project/maven-metadata.xml
Why is maven querying that URL and why does this happen occasionally? First, there is nothing on that URL, second, the jar already exists on local repository, third, I didn't change the version number of the local jar dependency. So let us say I have 1000 local projects, will it query URL1, URL2, ..., URL1000. What is the logic of this query to a non-existing URL?
Why is maven querying that URL and why does this happen occasionally?
occasionally: is specifically daily, because it is the default updatepolicy for the maven builtin Central Repository.
If you take a look at the maven super POM, which all pom files inherited from, you will find the repository is configured as follows
<repositories>
<repository>
<id>central</id>
<name>Central Repository</name>
<url>https://repo.maven.apache.org/maven2</url>
<layout>default</layout>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<release> element is not appearing here, so that means the repository will take the default values for it.
enabled (default is true)
updatePolicy (default is daily) --> possible values: "always", "daily" (default), "interval:XXX" (in minutes) or "never" (only if it doesn't exist locally).
hope this helps

Is it possible for maven to not search snapshots in release repositories?

I've discovered today, while investigating a bug regarding my project being no more deployable, that maven tries to load dependencies from all available repositories.
I don't find it wise, specifically regarding our internal artifacts, that are searched on amven central, Sonatype FlexMojos, and other external release repositories (specificall when the last one provides a custom 404 page that maven wrongly interprets as valid content, replacing my valid artifact with an invalid one).
So, is is possible to tell maven which repositories to lookup for SNAPSHOTs artifacts, and which to lookup for RELEASE ones ?
Would it help if you made it explicit to not look for snapshots in your repo?
<repositories>
<repository>
<id>central</id>
<name>Maven Repository Switchboard</name>
<layout>default</layout>
<url>http://repo1.maven.org/maven2</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
My solution is to set up a repository mirror in the intranet. That way, Maven needs to know a single URL to download everything.
I then use the internal mirror to bundle repositories (local and remote ones). If snapshot repos are first in the search path, the mirror server will almost never publish the names of my internal artifacts (only when I forgot to deploy them).
On top of that, it will reduce the download times for the rest of the team plus it will make sure that everyone can still work even when there are network problems outside of your control.

Installing a maven project with a dependency on a parent

I have a collection of related projects that inherit from a common maven project.
Since they are still in alpha release, they all (including the parent) are deployed in the Sonatype snapshots repository, instead of Maven central.
The configuration for accessing the maven central is in the parent project of my application.
So its POM specifies as its parent:
...
<parent>
<groupId>org.sonatype.oss</groupId>
<artifactId>oss-parent</artifactId>
<version>7</version>
</parent>
...
And set the corresponding repository at Sonatype:
...
<repositories>
<repository>
<id>snapshots-repo</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
...
So the children projects do not have to repeat this configuration.
The parent also provides many other things that are common to all my projects.
Currently I keep all these projects in unrelated directories.
Now, if a user of my application checkout one of my projects and attempt to install it with mvn install, he will receive the error: Non-resolvable parent POM: Could not find artifact ...
This makes sense to me, since the project cannot access the Sonatype repository (e.g., for downloading the parent) since it is precisely the parent the one that contains how to connect to such repository.
I do not want to request the user to install first the parent project, since he should be able to install what he needs in just one single step.
Then what is the recommended way to distribute my libraries so the user can install any of them with one single command ?
It occurs to me that I could include the parent POM in each of the projects (for example, using git submodules) so the parent can be resolved locally. But I am wondering if this is the best way to organize this (?). Any better alternative is appreciated.
UPDATE
I added this to my ~/.m2/settings.xml so the parent POM could be resolved in the Sonatype snapshots repository. Apparently it is working fine and the parent POM is resolved as any other dependency.
<profiles>
<profile>
<id>allow-snapshots</id>
<activation><activeByDefault>true</activeByDefault></activation>
<repositories>
<repository>
<id>snapshots-repo</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
<releases><enabled>false</enabled></releases>
<snapshots><enabled>true</enabled></snapshots>
</repository>
</repositories>
</profile>
</profiles>
If you want to keep it to one step install than you have to list enough information in the project pom, i.e. either:
no parent pom, put all the information into each project pom
tell maven where to find your other projects. List the sonatype shnapshot repo in each project file.
A repository manager only helps those with access to it. That is ok if the users are in one organisation. Using the sonatype repository reaches a wider circle.

Where should I define maven repositories given that I use mirrorOf * in settings.xml?

I have a nexus repo on my network. In settings.xml on the build server we have
<mirror>
<id>company.com</id>
<name>nexus</name>
<url>http://build.company.com/nexus/content/groups/public/</url>
<mirrorOf>*</mirrorOf>
</mirror>
On this build server we have a number of proxy repositories defined for public repos, and I have some commercially licensed artifacts in a hosted repo.
And a profile - Maven cannot resolve my parent pom (artifact in nexus) without this:
<profiles>
<profile>
<id>repos</id>
<repositories>
<repository>
<id>my-local-repo</id>
<name>bootstrapthingy</name>
<url>http://build.company.com/nexus/content/groups/public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
<checksumPolicy>fail</checksumPolicy>
<updatePolicy>always</updatePolicy>
</snapshots>
</repository>
</repositories>
</profile>
</profiles>
<activeProfiles>
<activeProfile>repos</activeProfile>
</activeProfiles>
My question today:
I also have removed all my
<repositories>
tags from the parent pom that all projects (should eventually!) inherit, and everything seems to work.
Is this well and good? I seem to end up a lot thinking about best practice when I work with maven - lately, around where should information be kept?
As my repositories are now defined at Nexus level, there is an element of my build that is no longer source code controlled, and this bothers me.
Yes I would argue you're on the right track!
Maven recommends to think about your infrastructure and plan it! By that it splits project concerns from infrastructure aspects. Project specific configuration goes into the pom.xml while I would vote to put infrastructure configuration into settings.xml
So the company mirror / proxy goes into settings.xml (as infrastructure may change) along with its authentication and environment settings (that are project independant!)
Usually projects do not rely on a per-project repository. If they do they could in almost any case use the nexus server for that (lets say explicit SNAPSHOT dependencies). So the practice to not have repositories in a pom.xml is ok. URL's change and builds should not request artifacts at different locations. It endangers your build reproduce-ability (as does adding all kinds of unstable remote repos into nexus).
I think within a company you need to consider (or simply acknowledge) that builds in projects are not self-maintained. Most open-source projects are since they do not have a common shared infrastructure they may benefit from (or suffer under?). You need to do the best of it but having infrastructure issues solved in settings.xml also means that the project does not need to do that anymore. Has pro's and con's - no doubt about that :)

Resources