Preventing overriding dependency version in Maven child pom - maven

I have a dependencyManagement section in parent pom like
<dependencyManagement>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.2.1</version>
</dependency>
</dependencyManagement>
and a child pom, having it
<dependencies>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.0</version>
</dependency>
</dependencies>
I've tried to prevent this kind of overriding in child poms using enforcer plugin, allowing these only to be set in parent, but haven't been able to. I'd like this to fail the build. Is that possible, with that plugin or some other way?
There is DependencyCovergence, which forces all versions to be the same, but that's too restrictive as I don't want to control all transitive dependencies - just the ones defined explicitly.
I'd be happy if I could just prevent introducing any new dependencies at all in child poms - everything defined should really be defined in the parent pom, and then just mentioned, if needed, in the child.

You could add a dependency:analyze-dep-mgt execution in your parent pom and configure it to fail on version mismatches:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<id>analyze</id>
<phase>package</phase>
<goals>
<goal>analyze-dep-mgt</goal>
</goals>
<configuration>
<failBuild>true</failBuild>
<ignoreDirect>false</ignoreDirect>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

Related

Maven enforce no duplicate dependencies even of same version

We can use the maven-enforcer-plugin to prevent duplicate dependencies with difference versions.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>no-duplicate-dependencies</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<banDuplicatePomDependencyVersions/>
</rules>
</configuration>
</execution>
</executions>
</plugin>
What about for duplicate dependency declarations of the same version?
Consider that we are building a multi-module project.
Say we start with project Foo.
Foo pom.xml
<dependencies>
<dependency>
<groupId>someGroup</groupId>
<artifactId>someArtifact</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
Later, we introduce the module Bar, which also depends on the same version someArtifact.
Bar pom.xml:
<dependencies>
<dependency>
<groupId>someGroup</groupId>
<artifactId>someArtifact</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
And Foo depends on Bar, so we update the POM.
Foo pom.xml
<dependencies>
<dependency>
<groupId>myGroup</groupId>
<artifactId>bar</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>someGroup</groupId>
<artifactId>someArtifact</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
As in the above example, and as our projects grow, we may forget that the same version of dependencies are already transitive dependencies.
In my mind, for organization sake, I find it messy to leave these duplicate declarations, such as it is with someArtifact.
I could write a new maven-enforcer-plugin rule, but maybe there is already a solution.
Try with dependencyConvergence rule. Add this to your parent pom.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>3.0.0-M3</version>
<executions>
<execution>
<id>enforce</id>
<configuration>
<rules>
<dependencyConvergence/>
</rules>
</configuration>
<goals>
<goal>enforce</goal>
</goals>
</execution>
</executions>
</plugin>
Reference :: https://maven.apache.org/enforcer/enforcer-rules/dependencyConvergence.html

Maven plugin- exclude log4j1 transitive dependency

I have created sample application which has only one plugin 'aspectj-maven-plugin'.
When I build application, log4j1.2.12 is getting downloaded by this plugin.
Is there any way to avoid downloading log4j1 from maven plugin ?
I tried different options, like- exclude from dependency, increase plugin version, exclude from maven plugin, etc., but no luck.
My pom.xml -
<properties>
<aspectj.version>1.8.10</aspectj.version>
</properties>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.10</version>
<configuration>
<complianceLevel>1.8</complianceLevel>
<source>1.8</source>
<target>1.8</target>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
I have observed same with my another multi-module application. I have different maven plugin in different module- 'maven-war-plugin', 'maven bundle-plugin', etc.
One or another plugin is downloading log4j1.
If I increase version of one plugin then dependency is getting downloaded with another plugin.
I tried many options but no luck.
Log4j1 is not getting bundled in my war but what I need is log4j1 should not be downloaded.
Please let me know if there is any option to exclude lo4j1 from maven plugin.
Thanks.

Using Provided Artifact As Maven Plugin Dependency

This seems like it should be a simple question, but I can't seem to find any information about it. When a maven plugin has a required dependency, is it possible to tell it to use an artifact defined elsewhere in the section of the pom?
As an example, I'm trying to add the 'maven-processor-plugin' to my build. That plugin has a dependency on 'hibernate-jpamodelgen'. I'm working with wildfly, so I already have that jar as a dependency of the project. I want to ensure I am using the same version for both. Is what I'm trying to do even possible?
Some code snippets:
<dependencies>
<dependency>
<groupId>org.wildfly</groupId>
<artifactId>wildfly-ejb3</artifactId>
<version>${version.server.bom}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-jpamodelgen</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<compilerArguments>
<processor>-proc:none</processor>
</compilerArguments>
</configuration>
</plugin>
<plugin>
<groupId>org.bsc.maven</groupId>
<artifactId>maven-processor-plugin</artifactId>
<version>4.5</version>
<executions>
<execution>
<id>process</id>
<goals>
<goal>process</goal>
</goals>
<phase>generate-sources</phase>
<configuration>
<outputDirectory>${project.build.directory}/generated-sources/java/jpametamodel</outputDirectory>
<processors>
<processor>org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor</processor>
</processors>
<overwrite>true</overwrite>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-jpamodelgen</artifactId>
<!-- How do I handle this without hard coding the version? -->
<!-- <version>???</version> -->
</dependency>
</dependencies>
</plugin>
</build>
Define a property like <hibernate-jpamodelgen.version> in the <properties> section of the POM.
Then use that property for the version like ${hibernate-jpamodelgen.version}.

Maven unpack transitive dependencies' JAR to a folder

I have two maven artifacts in my private repository, com.test.Parent and com.test.Child. Child is dependent on Parent.
The only thing I want Maven to do is to download the Child jar and everything it depends on, and then unpack it to a directory.
I was able to put together a pom.xml that downloads the Child by calling mvn clean dependency:unpack, however in order to download the transitive dependency I had to manually include it in the pom.
What I want is to call, for instance maven initialize and my required dependencies would be downloaded. What I have now is this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack</id>
<phase>initialize</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>com.test</groupId>
<artifactId>Child</artifactId>
<version>1.2.3</version>
<type>jar</type>
<includes>**</includes>
<excludes>META-INF/**</excludes>
<outputDirectory>somepath/sources</outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
</execution>
<execution>
<id>unpack-dependencies</id>
<phase>initialize</phase>
<goals>
<goal>unpack-dependencies</goal>
</goals>
<configuration>
<excludeTransitive>false</excludeTransitive>
<includes>**</includes>
<outputDirectory>somepath/depend</outputDirectory>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>com.test</groupId>
<artifactId>Child</artifactId>
<version>1.2.3</version>
<type>jar</type>
</dependency>
</dependencies>
</plugin>
</plugins>
However, when I run mvn clean initialize, only the Child files are downloaded and unpacked.
POM file of com.test.Child contains this:
<groupId>com.test</groupId>
<artifactId>Child</artifactId>
<version>1.2.3</version>
<dependencies>
<dependency>
<groupId>com.test</groupId>
<artifactId>Parent</artifactId>
<version>7.8.9</version>
</dependency>
</dependencies>
Do you see any problem with the setup? The endgame is that developers can just download one pom.xml, run mvn <something> and all the dependencies will be automatically downloaded and unpacked to a certain structure.
Thanks
Edit:
When I delete my local Maven repository and run this pom, both Child and Parent are downloaded. So the dependency is there, but Parent is not picked up by the unpack-dependencies goal.
I solved the issue by moving the <dependencies> block outside <plugins>. So the final POM structure is:
<project>
<build>
<plugins>
<plugin>
...
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>com.test</groupId>
<artifactId>Child</artifactId>
<version>1.2.3</version>
</dependency>
</dependencies>
</project>
But if anyone can explain to me why this helps, that would be appreciated.

Maven - differences between dependencies inside plugin and outside?

I've come across some sample code which specifies dependencies inside the plugin tag like this :
<build>
<plugins>
<plugin>
<dependencies>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>2.2.8</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
It look strange to me because mostly I see people put the dependencies tag outside the build tag.
When you add <dependency> to project it is available to that project depending on its scope (compile, test, runtime, etc)
But when you add <dependency> inside plugin's execution you are making that artifact available to that plugin in classpath at runtime
For example:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>2.1</version>
<executions>
<execution>
<id>check my sources</id>
<goals>
<goal>check</goal>
</goals>
<phase>compile</phase>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>checkstyle</groupId>
<artifactId>checkstyle</artifactId>
<version>4.4</version>
</dependency>
</dependencies>
</plugin>
in this snippet checkstyle:checkstyle:4.4 is being available to maven-checkstyle-plugin at runtime
Read More
How to override a plugin's dependency in Maven

Resources