How can specific Maven artifacts in Nexus be blocked - maven

We use Maven through a local Nexus repository. Unfortunately, when querying for new versions, we get several false positives:
commons-collections:commons-collections ............ 3.2.1 -> 20040616
org.hibernate:hibernate-entitymanager ..... 4.1.9.Final -> 4.3.0.Beta1
The first is a version that is ancient but with an incorrect naming scheme. The second is actually only a beta version (we don’t usually get these, but some seem to slip through). Now the question is: How can these versions, which are not really on our repository but come from one of the repositories our Nexus refers to, be excluded?
I have tried routing, but either I got it wrong or it cannot block specific versions, only the complete artifacts with all its versions. I have seen procurement in the documentation, but it seems very complicated and I did not dare trying.

You may configure the versions-maven-plugin in your project's POM (or a corporate parent somewhere) to use a rules file telling the plugin which versions to ignore.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>versions-maven-plugin</artifactId>
<version>2.1</version>
<configuration>
<!-- some location that makes sense for your company/project -->
<rulesUri>http://host.company.com/maven-config/maven-version2-rules.xml</rulesUri>
</configuration>
</plugin>
An example rules file looks like the below. Mine ignores the "99.0-does-not-exist" version of the commons-logging plugin.
<ruleset xmlns="http://mojo.codehaus.org/versions-maven-plugin/rule/2.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://mojo.codehaus.org/versions-maven-plugin/rule/2.0.0
http://mojo.codehaus.org/versions-maven-plugin/xsd/rule-2.0.0.xsd">
<rules>
<rule groupId="commons-logging" artifactId="commons-logging">
<ignoreVersions>
<ignoreVersion>99.0-does-not-exist</ignoreVersion>
</ignoreVersions>
</rule>
</rules>
</ruleset>
You may add configuration to ignore other versions globally, not per-artifact as I did here, and regular expressions may be used as well. More information is available in the plugin documentation.

Related

Avoiding maven repository version collision when using feature branches

Question: How do you handle feature branches for maven multi project builds?
Jenkins builds and deploys these branches to keep build overhead on developers to a minimum but develop and feature branches cannot build the same maven version or we risk mismatch between artifacts and source.
We have a script to change parent version in child poms and version in root pom. While this segregates the branches in maven space, it results in extra work when merging.
I think nexus pro staging feature might help us avoid this requirement and make each feature branch use a specific repo which we easily drop after branch deletion/merge.
Again: how to handle the problem of multiple branches and maven?
How about the following approach:
Use the buildnumber-maven-plugin to fetch information from git and populate specific Maven properties (we are interested specifically in the scmBranch property (that is, the current git branch)
Use the build-helper-maven-plugin to check whether we are in a feature branch or not (via a regex, excluding well-known branches like master, develop, etc.) and populate (or not) a new Maven property, say branch.classifier
Use the maven-jar-plugin to set a classifier on the generated artifacts, based on what the previous step set, that is, using the new branch.classifier property: if empty, no classifier will be applied (default behavior, applied to the develop branch, for example); otherwise a classifier named after the current branch will be dynamically applied.
Here is a minimal example:
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>buildnumber-maven-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>create</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.10</version>
<executions>
<execution>
<id>regex-property</id>
<goals>
<goal>regex-property</goal>
</goals>
<configuration>
<name>branch.classifier</name>
<value>${scmBranch}</value>
<regex>(^develop)|(^master)|(^release.*)</regex>
<replacement></replacement>
<failIfNoMatch>false</failIfNoMatch>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
<configuration>
<classifier>${branch.classifier}</classifier>
</configuration>
</plugin>
</plugins>
</build>
The snippet below is basically populating the scmBranch property dynamically, then setting the branch.classifier to its value only if different than develop, master or release*, then setting it as a classifier.
Main advantages of this approach:
No pom changes will be applied, hence no merging issues at all
No clashes on Nexus working on the same version of the project but on different branches: the classified artifact will have different Maven coordinates, that is, the GAV (groupId, artifactId, version) becomes unique GAVC (+classifier)
That's actually a meaningful usage of the classifier attribute of an artifact:
The classifier allows to distinguish artifacts that were built from the same POM but differ in their content.
The generated artifact will be dynamically different in Nexus, according to its source branch, hence having implicit traceability: no intervention from developers (no error prone, implicit convention), no intervention from CI job (easier maintenance), completely transparent
Using classifiers, will be easier to use the artifacts generated by a branch as a maven dependency (e.g. in case of library project): I want to use the dependency currently under development on branch xxx
Examples
Hence, you would have the following artifacts generated:
When working on develop: e.g. project-1.0.0-SNAPSHOT.jar (empty classifier, hence not applied, as handled by the regex)
When working on featureA: e.g. project-1.0.0-SNAPSHOT-featureA.jar
When working on hotfix-JIRA123: e.g. project-1.0.0-hotfix-JIRA123.jar
When working on release-sprint42: that's up to you, I added this case to not apply the branch name, simply because in these cases I prefer to esplicitely set a special classifier, RC<number>, for release candidates, but that's a matter of conventions/taste/habits, you can apply the same approach on this branch as well, as long as no clashes will be created on Nexus. Also note: when using JIRA/Stash/Git integration, the release branch name is normally something like release/v0.1.0, where the / character may cause issues in some OS (still something fixeable via further regex replacing though, if really required).
When working on master: hey, no one should work on master :) the case is there just as a double check, but that's actually not required
Warnings on this approach:
As explained in the discussion below via comments, if the concerned Maven project is already using classifiers and even more via inter-modules dependencies (e.g. dependendies on test scope classes from another module), then this approach should be carefully tested, since it might have some drawbacks
The publication of the <artifactId>.pom files containing branch classifier can get into conflicts with the mainline build (i.e. overriding it)
This does not work Results in warnings throughout the build and GC error when run from top parent.
Ideally, we want to use version as to differentiate feature branch from mainline because it is the normal maven way and classifier manipulation can result in all kinds of issues.
Since maven can use environment variables for properties and we already initialize build environment with a script (we also have git hook scripts that can set environment variables from branch names) we can use env to control the version.
<groupID>my.project</groupId>
<artifactID>database</artifactId>
<version>1.2.0${env.BRANCHMODIFIER}-SNAPSHOT</version>
If on develop our scripts set BRANCHMODIFIER to ""
If on feature/JIRA-30495 our scripts set BRANCHMODIFIER to ".30495"
How does this work in eclipse or Intellij? No clue as of yet.
We use a similar technique as Peter Kahn, modifying the version of the branch before building. We have three steps in our "Pre Steps":
Execute shell: echo VERSION=$(echo ${GIT_BRANCH} | sed 's_^.*\/__') > env.properties
Inject environment variables: env.properties
Invoke top level Maven targets: versions:set -DgenerateBackupPoms=false -DnewVersion=${VERSION}-SNAPSHOT
I am quite sure that this can be done with two or even one and only step as well, bit the principe behind it will be the same.
The reason why we don't change the version in the pom.xml files in the branch directly is indeed merging. With SVN this was possible (merging with --accept-mine-conflict. With GIT this does not exist anymore, so we stopped changing versions and created this pre-build steps.
For Maven ge 3.5.0 try this https://maven.apache.org/maven-ci-friendly.html
This is the recommended Maven solution.
The only problem (but unusual) can be the numeric versions resolution of the maven dependencies. But this only apears, if you use different SNAPSHOT dependencies of the the module, which is a bad idea anyway.

How do I get maven to use the JNLP version naming convention?

I've been tasked with reducing the download size of one of our webstart apps. I've figured that a decent portion of the download is from all a largish library of jar files, and since we rarely update many of them, it seems the download will be reduced significantly using the JNLP Version Download Protocol. This should stop the continual re-download of the same jars when a new version of the app is released.
Now, the project is build with maven. Part of the process is automatically generating a JNLP file from a velocity template. The resources section of the JNLP file is populated by a $dependencies variable assumedly passed in by maven and looks something like this:
<jar href="lib/mainjar-0.1.40-SNAPSHOT.jar" main="true"/>
<jar href="lib/somejar-1.1.jar"/>
<jar href="lib/someotherjar-1.0.jar"/>
<jar href="lib/anotherjar-1.6.0.jar"/>
etc...
It seems to me that maven is using its standard naming convention and constructing the jar names from the artifactId and version tags out of the project pom files.
How can I get it to use the JNLP naming convention instead?
I can change the velocity template to cut the $dependencies variable up and re-combine it with the JNLP convention - but that's only halfway what I need since the actual jar names need to be changed too.
The version download protocol article is about speeding up the check that resources are up to date. Although it may be useful as well, it is not the part that prevents re-downloading of the same files.
Webstart-maven-plugin can take care of versioning of the jars for you and they declare they use the version protocol as well. See http://www.mojohaus.org/webstart/webstart-maven-plugin/jnlp-mojo.html#outputJarVersions
My personal experience differs from what the docs say. It adds the version attribute for jars in the resulting jnlp and does not set the jnlp.versionEnabled property, which seems to be required for the version download protocol. Either way JWS works as I would expect - files are not re-downloaded when their version does not change.
Plugin setup:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>webstart-maven-plugin</artifactId>
<version>1.0-beta-6</version>
<dependencies>
<!--This dependency definition resolves class loading issue on Java 8 -->
<dependency>
<groupId>org.codehaus.mojo</groupId>
<artifactId>keytool-api-1.7</artifactId>
<version>1.4</version>
</dependency>
</dependencies>
<executions>
<execution>
<phase>process-resources</phase>
<goals>
<goal>jnlp-download-servlet</goal>
</goals>
</execution>
</executions>
<configuration>
<outputDirectoryName>/</outputDirectoryName>
<libPath/>
<sign>
<keystore>${basedir}/foo-key-store.jks</keystore>
<storepass>password</storepass>
<alias>foo-self-signed</alias>
<verify>true</verify>
</sign>
<unsign>true</unsign>
<jnlpFiles>
<jnlpFile>
<inputTemplate>template.vm</inputTemplate>
<outputFilename>foo.jnlp</outputFilename>
<jarResources>
<jarResource>
<groupId>foo.bar</groupId>
<artifactId>foo</artifactId>
<version>${project.version}</version>
<mainClass>foo.bar.Foo</mainClass>
<outputJarVersion>false</outputJarVersion>
</jarResource>
</jarResources>
</jnlpFile>
</jnlpFiles>
<gzip>true</gzip>
</configuration>
</plugin>
Excerpt from the generated foo.jnlp showing the version attribute of a dependency:
<jar href="commons-collections.jar" version="3.2.1"/>
And the file it references is named:
commons-collections-3.2.1.jar

SoapUI Maven plugin has weird dependencies

I'm trying to use the SoapUI Maven plugin as shown here: http://www.soapui.org/Test-Automation/maven-2x.html
I can't add the eviware repository, since I'm behind a corporate firewall (only the browser can connect to the outside world) and have to use the local artifactory repo (which mirrors maven central).
So I tried downloading the appropriate jars and poms from the eviware repo and adding them to the local artifactory. Now it seems I've gone down the rabbit hole, the SoapUI plugin has more and more dependencies that I need to add. At first I didn't mind, but we're looking at tens of jars now, and most of them seem to be things that should be in maven central. But then I saw that most of these have altered group-IDs - for example there is a jetty dependency that uses "jetty" as group-ID instead of the canonical "org.mortbay.jetty". And this seems to be the case for many of these dependencies.
So my question has two sides: What are the SoapUI folks doing here? This seems fishy to me, or am I overlooking something?
And second, can I somehow make the plugin use the canonical jars instead of having to chase all the stuff that's in eviware's repository?
Have a look on this soapui forum, I explain why soapui uses weird maven coordinates and what could be done to use regular ones.
I have already complained about the problem on this post and I am sure that SoapUI dev are aware of the problem. Sadly, there is no current work to fix it.
I have tried relentlessly to use the maven-soapui-plugin, but It didn't work for me. However the maven-soapui-extension-plugin mentioned by pppeater and developed by redfish above has worked fine when I tried it. I have used artifactory as my repo manager.
First configure the plugin on your pom
<plugin>
<groupId>com.github.redfish4ktc.soapui</groupId>
<artifactId>maven-soapui-extension-plugin</artifactId>
<version>4.6.3.0</version>
<executions>
<execution>
<id>soapui-tests</id>
<phase>verify</phase>
<goals>
<goal>test</goal>
</goals>
</execution>
</executions>
<configuration>
<projectFile>${basedir}/src/test/soapui/airline-sample-soapui- project.xml</projectFile>
<outputFolder>${basedir}/target/soapui</outputFolder>
<junitReport>true</junitReport>
<exportwAll>false</exportwAll>
<printReport>false</printReport>
</configuration>
</plugin>
You still need to add the soapui plugin to your repo manager remote repositories and virtual repositories list using the url http://www.soapui.org/repository/maven2/
Just came across this plugin: https://github.com/redfish4ktc/maven-soapui-extension-plugin which notes: "starting from soapui 3.6.1, almost all SmartBear plugin versions have missing dependencies. This is fixed in maven-soapui-extension-plugin"
It also appears to address some Groovy dependencies which others have noted as an issue with the plugin.

Maven dependency:analyze thinks my JDBC JARs are "unused"

I'm using a MySQL connector JAR to make JDBC connections. My understanding is that I just have this JAR in the classpath, and it'll be dynamically loaded when I specify mysql: in the connection string.
I declare this dependency in my POM using <scope>runtime</scope>. When I run mvn dependency:analyze, it reports this artifact as "unused". I guess it can't determine that I'll need it through simple static analysis, fine, but surely that's going to be true of just about any runtime-scoped artifact, right? How can I convince Maven that this artifact really needs to be there?
dependency:tree will list all artifacts that are referenced by your pom files if that is what you are looking for. Otherwise you are likely out of luck. Maven openly declares that their dependency analyzer works at the bytecode level and will falsely report dependencies as unused in some scenarios.
A runtime-scoped dependency may or may not be used, it is impossible to tell with bytecode analysis (in fact, impossible to tell with most analysis I could think of). Maven has to decide to either assume they are used or assume they are unused and they went with the latter figuring the user could figure it out.
There is no option to tell Maven to treat runtime-scoped dependencies as used but you can manually add specific artifacts to the usedDependencies array in the configuration. Maven will simply assume those dependencies are used. You could also write your own dependency analyzer or find a 3rd party dependency analyzer that can handle this scenario.
==Update for comments==
You're right, it is quite new. The issue was fixed in version 2.6 which was released Nov, 25, 2012. It isn't yet in many of the public mirror repositories. You can find it here.
Since it is so new there are no examples of its usage however Maven follows some conventions. I would expect it to be declared as:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.6</version>
<configuration>
<usedDependencies>
<usedDependency>org.foo.bar:baz-tron</usedDependency>
<usedDependency>org.foo:whatsit</usedDependency>
</usedDependencies>
</configuration>
</plugin>
</plugins>
</build>

Maven "versions" plugin - how to exclude alpha/beta versions from response?

I have an issue concerning the plugin versions.
When it generates a report with the goal:
mvn versions:display-dependency-updates
It suggest is a lot of libraries that with beta or alpha versions.
org.hibernate:hibernate-validator ......... 4.2.0.Final -> 4.3.0.Beta1
The issue is that event if the goal of this plugin is to show the very latest versions of each dependency, I don't want to use beta/alpha versions for production code. But I don't want to search manually the last stable version neither.
I've tried the 'comparisonMethod' option: numeric, maven, etc. No success whatsoever.
Any ideas for the plugin 'versions' to show the latests available versions of dependencies, but without including beta/alpha?
You can configure the versions plugin like this:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>versions-maven-plugin</artifactId>
<version>2.1</version>
<configuration>
<rulesUri>someUrl</rulesUri>
</configuration>
</plugin>
someUrl can also be a file URL. The syntax of the rules file is given in http://www.mojohaus.org/versions-maven-plugin/version-rules.html, it may contain something like this:
<ruleset comparisonMethod="maven"
xmlns="http://mojo.codehaus.org/versions-maven-plugin/rule/2.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://mojo.codehaus.org/versions-maven-plugin/rule/2.0.0 http://mojo.codehaus.org/versions-maven-plugin/xsd/rule-2.0.0.xsd">
<ignoreVersions>
<ignoreVersion type="regex">.*-beta.</ignoreVersion>
<ignoreVersion type="regex">.*_ALPHA</ignoreVersion>
</ignoreVersions>
</ruleset>

Resources