In Maven2, to exclude a single transitive dependency, I have to do something like this:
<dependency>
<groupId>sample.group</groupId>
<artifactId>sample-artifactB</artifactId>
<version>1</version>
<exclusions>
<exclusion>
<groupId>sample.group</groupId>
<artifactId>sample-artifactAB</artifactId>
</exclusion>
</exclusions>
</dependency>
The problem with this approach is that I have to do this for every transitive dependency contributed by sample-artifactB.
Is there a way to use some sort of wildcard to exclude all transitive dependencies at once instead of one-by-one?
What has worked for me (may be a newer feature of Maven) is merely doing wildcards in the exclusion element.
I have a multi-module project that contains an "app" module that is referenced in two WAR-packaged modules. One of those WAR-packaged modules really only needs the domain classes (and I haven't separated them out of the app module yet). I found this to work:
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>app</artifactId>
<version>${project.version}</version>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
The wildcard on both groupId and artifactId exclude all dependencies that normally would propagate through to the module using this dependency.
For maven2 there isn't a way to do what you describe. For maven 3, there is. If you are using maven 3 please see another answer for this question
For maven 2 I'd recommend creating your own custom pom for the dependency that has your <exclusions>. For projects that need to use that dependency, set the dependency to your custom pom instead of the typical artifact. While that does not necessarily allow you exclude all transitive dependencies with a single <exclusion>, it does allow you only have to write your dependency once and all of your projects don't need to maintain unnecessary and long exclusion lists.
One thing I have found useful:
If you put the dependency with the exclusions in the dependencyManagement section of either the parent POM for your project, or in an importable dependency management POM, then you don't need to repeat the exclusion (or the version).
For example, if your parent POM has:
<dependencyManagement>
<dependencies>
...
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.2.1</version>
<exclusions>
<exclusion>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</exclusion>
</exclusions>
</dependency>
....
</dependencies>
</dependencyManagement>
Then the modules in your project can simply declare the dependency as:
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
</dependency>
The in the parent POM will specify both the version and the exclusions. I use this technique for nearly all of our projects and it eliminates a lot of repetition.
Three years ago I recommended using Version 99 Does Not Exist, but now I've figured out a better way, especially since Version 99 is offline:
In your project's parent POM, use maven-enforcer-plugin to fail the build if the unwanted dependency creeps into the build. This can be done using the plugin's banned dependencies rule:
<plugin>
<artifactId>maven-enforcer-plugin</artifactId>
<version>1.0.1</version>
<executions>
<execution>
<id>only-junit-dep-is-used</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<bannedDependencies>
<excludes>
<exclude>junit:junit</exclude>
</excludes>
</bannedDependencies>
</rules>
</configuration>
</execution>
</executions>
</plugin>
Then when that alerts you about an unwanted dependency, exclude it in the parent POM's <dependencyManagement> section:
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-test</artifactId>
<version>2.1.8.RELEASE</version>
<exclusions>
<exclusion>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</exclusion>
</exclusions>
</dependency>
This way the unwanted dependency won't show up accidentally (unlike just an <exclusion> which is easy to forget), it won't be available even during compile time (unlike provided scope), there are no bogus dependencies (unlike Version 99) and it'll work without a custom repository (unlike Version 99). This approach will even work based on the artifact's version, classifiers, scope or a whole groupId - see the documentation for details.
I use the following workaround : instead of trying to exclude the artifact in all appropriate dependencies, I draw the dependency as "provided" at top level.
For example, to avoid shipping xml-apis "whatever version" :
<dependency>
<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
<version>[1.0,]</version>
<scope>provided</scope>
</dependency>
Currently, there's no way to exclude more than one transitive dependency at a time, but there is a feature request for this on the Maven JIRA site:
https://issues.apache.org/jira/browse/MNG-2315
if you need to exclude all transitive dependencies from a dependency artifact that you are going to include in an assembly, you can specify this in the descriptor for the assembly-plugin:
<assembly>
<id>myApp</id>
<formats>
<format>zip</format>
</formats>
<dependencySets>
<dependencySet>
<useTransitiveDependencies>false</useTransitiveDependencies>
<includes><include>*:struts2-spring-plugin:jar:2.1.6</include></includes>
</dependencySet>
</dependencySets>
</assembly>
There is a workaround for this, if you set the scope of a dependency to runtime, transitive dependencies will be excluded. Though be aware this means you need to add in additional processing if you want to package the runtime dependency.
To include the runtime dependency in any packaging, you can use the maven-dependency-plugin's copy goal for a specific artifact.
If you develop under Eclipse, you can in the POM Editor (advanced tabs enabled) dependency graph look for the dependency you want to exclude of your project and then:
right click on it -> "Exclude Maven Artifact ..." and Eclipse will make the exclusion for you without the need to find out on which dependency the lib is linked.
What is your reason for excluding all transitive dependencies?
If there is a particular artifact (such as commons-logging) which you need to exclude from every dependency, the Version 99 Does Not Exist approach might help.
Update 2012: Don't use this approach. Use maven-enforcer-plugin and exclusions. Version 99 produces bogus dependencies and the Version 99 repository is offline (there are similar mirrors but you can't rely on them to stay online forever either; it's best to use only Maven Central).
In a simular issue I had the desired dependency declared with scope provided.
With this approach the transitive dependencies are fetched but are NOT included in the package phase, which is what you want.
I also like this solution in terms of maintenance, because there is no pom, or custom pom as in whaley's solution, needed to maintain; you only need to provide the specific dependency in the container and be done
Use the latest maven in your classpath.. It will remove the duplicate artifacts and keep the latest maven artifact..
Related
I'm using Lucene 4 in my application and don't want to change this. I'm trying to integrate Neo4J which bundles Lucene 3.5 as an IndexProvider implementation, neo4j-lucene-index.
Unfortunately, neo4j-lucene-index does not work, and with that dependency excluded, the app just hangs indefinitely on start up. I've tried neo4j-lucene4-index but that does not seem to be maintained very well and needs to be updated quite significantly to work with Neo4J 1.9.1. The changes go way beyond my understanding of the internals of Neo4J.
However, I can see that IndexProviders are pluggable, so I'm hoping that there is an existing alternative to Lucene - I can't find it at the moment though. Can anyone point me in the right direction for one?
It seems strange that Lucene 4 has been out for so long now and Neo4J doesn't support it. Am I missing something?
Currently, my POM looks like this for my Neo4J config:
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-neo4j</artifactId>
<version>2.2.1.RELEASE</version>
<exclusions>
<exclusion>
<artifactId>neo4j</artifactId>
<groupId>org.neo4j</groupId>
</exclusion>
<exclusion>
<artifactId>neo4j-cypher</artifactId>
<groupId>org.neo4j</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-kernel</artifactId>
<version>1.9.1</version>
<exclusion>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-lucene-index</artifactId>
</exclusion>
</dependency>
<dependency>
<groupId>org.neo4j.app</groupId>
<artifactId>neo4j-server</artifactId>
<version>1.9.1</version>
<exclusions>
<exclusion>
<artifactId>neo4j</artifactId>
<groupId>org.neo4j</groupId>
</exclusion>
<exclusion>
<artifactId>neo4j-cypher</artifactId>
<groupId>org.neo4j</groupId>
</exclusion>
<exclusion>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-lucene-index</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- A temporary dependency until Neo4J builds in support for Lucene 4.
Looks like they're planning to incorporate this project anyway This project
is available on GitHub, and needs to be built with: mvn license:format mvn
install to install into your local repo.
<dependency>
<groupId>com.keatext</groupId>
<artifactId>neo4j-lucene4-index</artifactId>
<version>1.9.M01-SNAPSHOT</version>
</dependency>-->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.0.1.Final</version>
</dependency>
There have been some changes internally from 1.8 -> 1.9. In short, a index provider must register a KernelExtensionFactory via META-INF/services, see https://github.com/neo4j/neo4j/blob/master/community/lucene-index/src/main/resources/META-INF/services/org.neo4j.kernel.extension.KernelExtensionFactory
This KernelExtensionFactory is the entry point, just checkout the Lucene 3 based implementation at https://github.com/neo4j/neo4j/tree/master/community/lucene-index.
Some time ago, I was also faced with this issue: I was working on prototyping, and I really liked embedded mode of Neo4j. But, once I decided to use Lucene 4 - I was stumbled with incompatibility issue.
OSGi
As been suggested here: How to use two versions of jar in my java project - one of the possible solution is to use OSGi, and wrap Neo4j and Lucene 4 into different bundles. Each bundle will have separate classloader - so Neo4j will use in runtime classes from Lucene 3, but you still be able to use Lucene 4 for your purposes.
But, as far as I was working on prototyping - I didn't want to spend time on adaptation of my project for OSGi platform by the single reason of incompatibility of two components.
Maven Shade Plugin
So, I have solved issue with help of Maven Shade Plugin.
Maven Shade Plugin provides an ability to merge all dependencies into single "fat" JAR (also, called "uber JAR").
So, you can generate "uber Neo4j dependency", and use it in your project - instead of "real" Neo4j dependency.
But there is an additional important moment: Lucene 3 and Lucene 4 has the same package structure, and many classes still have the same names. So, this might cause classloading conflicts.
To address this issue, Maven Shade Plugin provides an ability to relocate classes during generation of of "uber JAR": http://maven.apache.org/plugins/maven-shade-plugin/examples/class-relocation.html
You can specify package name, and during packaging - Shade Plugin will move classes from specified package and its subpackages to some other package, and will rewrite affected bytecode.
So, during composing of "uber JAR" for Neo4j - you can configure Shade Plugin to move classes of Lucene 3 to some other package, e.g.:
org.apache.lucene.* -> shaded_3_6_2.org.apache.lucene.*
(Luckily, it seems that Neo4j doesn't use reflection, in application to Lucene stuff).
So, you can create empty maven project with following pom.xml:
<project
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>my.hack</groupId>
<artifactId>uber-neo4j</artifactId>
<version>1.9.3</version>
<packaging>jar</packaging>
<name>uber-neo4j</name>
<properties>
<neo4j-version>1.9.3</neo4j-version>
</properties>
<dependencies>
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j</artifactId>
<version>${neo4j-version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<relocations>
<relocation>
<pattern>org.apache.lucene</pattern>
<shadedPattern>shaded_lucene_3_6_2.org.apache.lucene</shadedPattern>
</relocation>
</relocations>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>neo4j-repo</id>
<name>Neo4j Repository</name>
<url>http://m2.neo4j.org/content/repositories/releases</url>
</repository>
</repositories>
</project>
Described configuration - provides an ability to generate "uber JAR" for Neo4j with renamed packages of Lucene 3 (just do mvn install).
And, finally, you can attach this stuff as a module to your maven project.
So, after this workaround - you will be able to use both: Neo4j and Lucene 4 in your project.
Just in case, here is link to GitHub repository with maven configuration for generation of "uber JAR" for Neo4j: https://github.com/lagodiuk/neo4j-uber-jar
If you don't care what index Neo4j uses, and you're using Maven to manage dependencies, you can use the Maven Shade plugin's class relocation feature to rename Neo4j's Lucene dependency so it doesn't conflict with other dependencies on newer versions of Lucene.
In my case this required moving Neo4j-dependent code into a separate Maven project, as Shade acts on a whole project/jar at once. So if you can get your conflicting Lucene dependencies into different projects, this should work great.
I'm getting the following error. It seems there are multiple logging frameworks bound to slf4j. Not sure how to resolve this. Any help is greatly appreciated.
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/C:/Users/admin/.m2/repository/org/slf4j/slf4j-log4j12/1.6.4/slf4j-log4j12-1.6.4.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/C:/Users/admin/.m2/repository/org/slf4j/slf4j-log4j12/1.6.1/slf4j-log4j12-1.6.1.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
Resolved by adding the following exclusion in the dependencies (of pom.xml) that caused conflict.
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
Gradle version;
configurations.all {
exclude module: 'slf4j-log4j12'
}
The error probably gives more information like this (although your jar names could be different)
SLF4J: Found binding in
[jar:file:/D:/Java/repository/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in
[jar:file:/D:/Java/repository/org/apache/logging/log4j/log4j-slf4j-impl/2.8.2/log4j-slf4j-impl-2.8.2.jar!/org/slf4j/impl/StaticLoggerBinder.class]
Noticed that the conflict comes from two jars, named logback-classic-1.2.3 and log4j-slf4j-impl-2.8.2.jar.
Run mvn dependency:tree in this project pom.xml parent folder, giving:
Now choose the one you want to ignore (could consume a delicate endeavor I need more help on this)
I decided not to use the one imported from spring-boot-starter-data-jpa (the top dependency) through spring-boot-starter and through spring-boot-starter-logging, pom becomes:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
in above pom spring-boot-starter-data-jpa would use the spring-boot-starter configured in the same file, which excludes logging (it contains logback)
Sbt version:
Append exclude("org.slf4j", "slf4j-log4j12") to the dependency that transitively includes slf4j-log4j12. For example, when using Spark with Log4j 2.6:
libraryDependencies ++= Seq(
// One SLF4J implementation (log4j-slf4j-impl) is here:
"org.apache.logging.log4j" % "log4j-api" % "2.6.1",
"org.apache.logging.log4j" % "log4j-core" % "2.6.1",
"org.apache.logging.log4j" % "log4j-slf4j-impl" % "2.6.1",
// The other implementation (slf4j-log4j12) would be transitively
// included by Spark. Prevent that with exclude().
"org.apache.spark" %% "spark-core" % "1.5.1" exclude("org.slf4j", "slf4j-log4j12")
)
1.Finding the conflicting jar
If it's not possible to identify the dependency from the warning, then you can use the following command to identify the conflicting jar
mvn dependency: tree
This will display the dependency tree for the project and dependencies who have pulled in another binding with the slf4j-log4j12 JAR.
Resolution
Now that we know the offending dependency, all that we need to do is exclude the slf4j-log4j12 JAR from that dependency.
Ex - if spring-security dependency has also pulled in another binding with the slf4j-log4j12 JAR, Then we need to exclude the slf4j-log4j12 JAR from the spring-security dependency.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
Note - In some cases multiple dependencies have pulled in binding with the slf4j-log4j12 JAR and you don't need to add exclude for each and every dependency that has pulled in.
You just have to do that add exclude dependency with the dependency which has been placed at first.
Ex -
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
</dependencies>
If you work with gradle then add following code to your build.gradle file to exclude SLF4J binding from all the modules
configurations.all {
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
}
I just ignored/removed that jar file.
<!--<dependency>-->
<!--<groupId>org.springframework.boot</groupId>-->
<!--<artifactId>spring-boot-starter-log4j2</artifactId>-->
<!--</dependency>-->
I solved by delete this:spring-boot-starter-log4j2
Just use only required dependency, not all :))). For me, for normal work of logging process you need this dependency exclude others from pom.xml
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.5</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.1.8</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.1.8</version>
</dependency>
This is issue because of StaticLoggerBinder.class class belongs to two different jars. this class references from logback-classic-1.2.3.jar and same class also referenced from log4j-slf4j-impl-2.10.0.jar. both of jar in classpath. Hence there is conflict between them.
This is reason of log file is not generation even though log4j2.xml file in classpath [src/main/resource].
We have so select one of jar, I recommend use log4j-slf4j-impl-2.10.0.jar file and exclude logback-classic-1.2.3.jar file.
Solution: open pom file and view the dependency Hierarchy [eclipse] or run
mvn dependency:tree command to find out the dependency tree and source of dependency that download the dependency. find the conflicting dependency and exclude them. For Springboot application try this.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
This is working fine for me after struggling a lots.
...
org.codehaus.mojo
cobertura-maven-plugin
2.7
test
ch.qos.logback
logback-classic
tools
com.sun
...
## I fixed with this
...
org.codehaus.mojo
cobertura-maven-plugin
2.7
test
ch.qos.logback
logback-classic
tools
com.sun
...
For me, it turned out to be an Eclipse/Maven issue after switch from log4j to logback. Take a look into your .classpath file and search for the string "log4j".
In my case I had the following there:
<classpathentry kind="var" path="M2_REPO/org/slf4j/slf4j-log4j12/1.7.1/slf4j-log4j12-1.7.1.jar"/>
<classpathentry kind="var" path="M2_REPO/log4j/log4j/1.2.17/log4j-1.2.17.jar" />
Removing those entries from the file (or you could regenerate it) fixed the issue.
For me the answer was to force a Maven rebuild. In Eclipse:
Right click on project-> Maven -> Disable Maven nature
Right click on project-> Spring Tools > Update Maven Dependencies
Right click on project-> Configure > Convert Maven Project
I solved this by going to Project Structure from my Intellij project.
I deleted the file named: Maven: org.apache.logging.log4j:log4j-to-slf4j-impl:2.14.1
This file is not shown in this picture. You may see two libraries mentioned as log4j-to-slf4j. Delete one and you are good to go.
For all those looking for the solution for spring-boot-type dependencies, the magic incantation for Gradle is this:
configurations.all {
exclude group: 'ch.qos.logback', module: 'logback-classic'
}
in your build.gradle at the top level (not inside the dependencies block).
All other solutions found in the interwebs (including the one here suggesting to exclude the slf4j module) did not work for me.
This is what I have in my build.gradle (snippet):
// Removes the annoying warning about the multiple SLF4J implementations:
// SLF4J: Class path contains multiple SLF4J bindings.
configurations.all {
exclude group: 'ch.qos.logback', module: 'logback-classic'
}
dependencies {
annotationProcessor "org.springframework.boot:spring-boot-configuration-processor"
implementation ('org.springframework.boot:spring-boot-starter-actuator')
implementation ('org.springframework.boot:spring-boot-starter-data-mongodb-reactive')
implementation ('org.springframework.boot:spring-boot-starter-webflux')
annotationProcessor "org.projectlombok:lombok:${lombokVersion}"
compileOnly "org.projectlombok:lombok:${lombokVersion}"
// Removes the annoying warning:
// warning: unknown enum constant When.MAYBE
// reason: class file for javax.annotation.meta.When not found
// See: https://stackoverflow.com/questions/29805622/could-not-find-or-load-main-class-org-gradle-wrapper-gradlewrappermain/31622432
implementation group: 'com.google.code.findbugs', name: 'jsr305', version: '3.0.2'
// other stuff...
YMMV
I had the same problem. In my pom.xml i had both
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.28</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
When i deleted the spring-boot-starter-web dependency, problem was solved.
I got this issue in a non-maven project, two depended jar each contained a slf4j. I solved
by remove one depended jar, compile the project(which of course getting failure) then add the removed one back.
In case these logs are the result of this fix:
https://stackoverflow.com/a/9919375/2894819
When one of your libraries actually use it. And your application doesn't need SL4J just replace implementation to runtimeOnly.
// contains dependency to sl4j-api
implementation("com.github.doyaaaaaken:kotlin-csv-jvm:1.2.0")
// add this to remove both warnings
runtimeOnly("org.slf4j:slf4j-nop:1.7.36")
In that case when you run your app the actual dependency will be included once by the library and won't be included to the bundle of your application.jar itself.
In my case I had 2 sources of dependencies for log4 one in C:\Program Files\smcf.ear directory and the second from maven which caused the multiple binding for sl4j.
Deleting the smcf.ear directory solved the issue for me.
The combination of <scope>provided</scope> and <exclusions> didn't work for me.
I had to use this:
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<scope>system</scope>
<systemPath>${project.basedir}/empty.jar</systemPath>
</dependency>
Where empty.jar is a jar file with literally nothing in it.
Seems removing .m2 directory and :
mvn install -DskipTests -T 4 resolved this issue for me.
I have a EAR with a number of EJB dependencies. 2 of these have a provided scope dependency to the glassfish-embedded-all jar. However when I do a mvn install on my local machine or when the application is build through maven on hudson the ear always contains the glassfish-embedded-all jar.
e.g. DataAccess-ejb with provided dependency
<dependency>
<groupId>org.glassfish.extras</groupId>
<artifactId>glassfish-embedded-all</artifactId>
<version>3.0</version>
<scope>provided</scope>
</dependency>
Application-ear with ejb dependency
<dependency>
<groupId>com.xxx.yyy</groupId>
<artifactId>DataAccess-ejb</artifactId>
<version>1.0-SNAPSHOT</version>
<type>ejb</type>
</dependency>
Any ideas what I am doing wrong or possible suggestions?
Cheers,
James
Try using mvn dependency:tree in order to analyze what artifact is including the glassfish-embedded-all.jar, chances are that you're overlooking something. Maven won't include an artifact that is not declared as as direct dependency and/or inherited through transitive dependency.
You can also issue and mvn dependency:analyze-only command to further clean up those dependencies that you don't really need.
Dependencies with a provided scope are not transitive so you're not getting it transitively, there must be something else. Run mvn dependency:tree from the ear module.
But actually, I really wonder why you're using a provided scope, I think a test scope might be more appropriate. And by the way, I suggest using GF 3.0.1:
<dependency>
<groupId>org.glassfish.extras</groupId>
<artifactId>glassfish-embedded-all</artifactId>
<version>3.0.1</version>
<scope>test</scope>
</dependency>
Currently I am using Ivy for dependency management. And quite often I come across problem of getting identical jar files with different name due to transitive dependency.
Example:
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-javamail_1.4_spec</artifactId>
<version>1.4</version>
</dependency>
I am thinking of trying out Maven as well.
Any best practice to eliminate these identical artifact in either Ivy or Maven?
Global exclusion of artifacts would be a nice feature to deal with this kind of situation - same artifact with different names - until Maven provides a better way to deal with "Specs JARs" aka Virtual Dependencies.
Unfortunately, such a feature is currently not available (see MNG-3196 and MNG-1977) so you will have to declare dependency exclusions to exclude the unwanted artifact from the dependency pulling it transitively. In Maven, this is done by adding an <exclusions> tag under the <dependency> section of the pom.
<project>
...
<dependencies>
<dependency>
<groupId>sample.ProjectA</groupId>
<artifactId>Project-A</artifactId>
<version>1.0</version>
<scope>compile</scope>
<exclusions>
<exclusion> <!-- declare the exclusion here -->
<groupId>sample.ProjectB</groupId>
<artifactId>Project-B</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>
If Project-A-1.0.jar is used by all projects, one possible solution would be to declare this under the dependencyManagement section of a corporate POM to not repeat yourself.
In this particular example i would select the the javax one. And if you have artifacts which are coming under different names you can use excludes in Maven. I don't know if this is possible in Ivy.
I have a maven module which has some dependencies. In a certain profile, I want to exclude some of those dependencies (to be exact, all dependencies with a certain group id). They however need to be present in all other profiles. Is there a way to specify exclusions from the dependencies for a profile?
To my knowledge, no, you can't deactivate dependencies (you can exclude transitive dependencies but this is not what you are asking for) and yes, what you are currently doing with the POM (manually editing it) is wrong.
So, instead of removing dependencies, you should put them in a profile and either:
Option #1: use the profile when required or
Option #2: mark the profile as activated by default or put it in the list of active profiles and deactivate it when required.
A third option would be (not profile based):
Option #3: separate things in two separated modules (as you have separated concerns) and use inheritance.
Instead of excluding dependencies in a profile, you can set them as provided in it. This doesn't require any overly complex configuration and will exclude the dependencies you don't want from the final build.
In the desired profile, add a dependencies section, copy the declaration of the ones you want to exclude and scope them as provided.
For example, let say you want to exclude slf4j-log4j12:
<profiles>
<!-- Other profiles -->
<profile>
<id>no-slf4j-log4j12</id>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.2</version>
<scope>provided</scope>
</dependency>
</dependencies>
</profile>
<!-- Other profiles -->
</profiles>
One way that occurs to me is to have the dependencies in a separate pom. You can then add an <exclusions> section via the profile.
<dependencies>
<dependency>
<groupId>my.company.dependencies</groupId>
<artifactId>my-dependencies</artifactId>
<version>1.0.0-SNAPSHOT</version>
<type>pom</type>
</dependency>
</dependencies>
<profile>
<activation>
<activeByDefault>false</activeByDefault>
<property>
<name>exclude-deps</name>
</property>
</activation>
<dependencies>
<dependency>
<groupId>my.company.dependencies</groupId>
<artifactId>my-dependencies</artifactId>
<version>1.0.0-SNAPSHOT</version>
<type>pom</type>
<exclusions>
<exclusion>
<groupId>my.company</groupId>
<artifactId>bad-dep-1</artifactId>
</exclusion>
<exclusion>
<groupId>my.company</groupId>
<artifactId>bad-dep-2</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</profile>
I don't think it is possible to exclude direct dependencies either (at least, nothing is mentioned here).
The best thing you can do is to enclose the desired dependencies for each case into different profiles (as suggested already), but, you'll need to create two "mutually exclusive" profiles with the one of them "active by default". The most reliable way to achieve this is by using a parameter for your profile activation e.g.
<profiles>
<profile>
<id>default-profile</id>
<activation>
<property><name>!exclude</name></property>
</activation>
<dependencies>
dependency-A
dependency-B
...
</dependencies>
</profile>
<profile>
<id>exclude-profile</id>
<activation>
<property><name>exclude</name></property>
</activation>
<!-- exclude/replace dependencies here -->
</profile>
</profiles>
Then using "mvn [goal]" will use profile "default-profile", but "mvn [goal] -Dexclude" will use profile "exclude-profile".
Note that using 'activeByDefault' instead of a parameter for your "default" profile might work in some cases but it also might lead to unexpected behavior. The problem is that 'activeByDefault' makes a profile active as long as there is no other active profile in any other module of a multi-module build.
maven is a tool, we can hack it.
maven runs fine if you have the same artifact + version defined as dependency twice.
define a profile that eliminates an artifact + version by changing it to another package we already have.
For example, in the pom.xml:
... other pom stuff ...
<properties>
<artifact1>artifact1</artifact1>
<artifact2>artifact2</artifact2>
<artifact1.version>0.4</artifact1.version>
<artifact2.version>0.5</artifact2.version>
</properties>
<profile>
<id>remove-artifact2</id>
<properties>
<artifact1>artifact1</artifact1>
<artifact2>artifact1</artifact2>
<artifact1.version>0.4</artifact1.version>
<artifact2.version>0.4</artifact2.version>
</properties>
</profile>
Now if you install this pom.xml without the profile, artifact1:0.4 and artifact2:0.5 will be the dependency.
But if you install this pom.xml with the profile mvn -P remove-artifact2
The result pom.xml contains only artifact1:0.4
This comes quite handy during api migration where artifact are renamed and versions are not compatible.
Bit dirty but lightweight solution is to use <scope>import</scope>.
Unlike the other scopes you could use this:
will disable compile-time and runtime dependecies; unlike provided or runtime which disables only one at a time
won't mess up your test scope
you don't need to specify path to some dummy jar as would system scope require
Nothing gets imported as long as you use this hack outside dependencyManagement.