Maven exclusions specific version into fat jar - maven

I am working in project where Springboot jar and Hive jar creating conflict becuase of duplicate versions
<dependency>
<groupId>org.apache.hive</groupId>
<artifactId>hive-jdbc</artifactId>
<version>3.1.0.3.1.0.0-78</version>
</dependency>
Above hive jar is fat jar and coming with many duplicate dependancy ,in following example you can see two versions 2.6.0 and 3.1.1.3.1.0.0-78
Now if we want to add exclude
<exclusions>
<exclusion>
<artifactId>XX</artifactId>
<groupId>YYY</groupId>
</exclusion>
</exclusions>
Now i want to exclude only 2.6.0 version and keep 3 3.1.1.3.1.0.0-78
, is there any option where we can defined excluded jar version ?
[WARNING]
Dependency convergence error for org.apache.hadoop:hadoop-auth:2.6.0 paths to dependency are:
+-com.syf.gemfire:jdbc-gemfire-dataloader-pcf:2.0.0
+-org.apache.hive:hive-jdbc:3.1.0.3.1.0.0-78
+-org.apache.hive:hive-common:3.1.0.3.1.0.0-78
+-com.github.joshelser:dropwizard-metrics-hadoop-metrics2-reporter:0.1.2
+-org.apache.hadoop:hadoop-common:2.6.0
+-org.apache.hadoop:hadoop-auth:2.6.0
and
+-com.syf.gemfire:jdbc-gemfire-dataloader-pcf:2.0.0
+-org.apache.hive:hive-jdbc:3.1.0.3.1.0.0-78
+-org.apache.hive:hive-service:3.1.0.3.1.0.0-78
+-org.apache.hive:hive-llap-server:3.1.0.3.1.0.0-78
+-org.apache.hbase:hbase-hadoop2-compat:2.0.2.3.1.0.0-78
+-org.apache.hadoop:hadoop-mapreduce-client-core:3.1.1.3.1.0.0-78
+-org.apache.hadoop:hadoop-yarn-common:3.1.1.3.1.0.0-78
+-org.apache.hadoop:hadoop-auth:3.1.1.3.1.0.0-78
and
+-com.syf.gemfire:jdbc-gemfire-dataloader-pcf:2.0.0
+-org.apache.hive:hive-jdbc:3.1.0.3.1.0.0-78
+-org.apache.hive:hive-service:3.1.0.3.1.0.0-78
+-org.apache.hive:hive-llap-server:3.1.0.3.1.0.0-78
+-org.apache.hbase:hbase-server:2.0.2.3.1.0.0-78
+-org.apache.hbase:hbase-http:2.0.2.3.1.0.0-78
+-org.apache.hadoop:hadoop-auth:3.1.1.3.1.0.0-78

To resolve the dependency convergence errors, add entries to <dependencyManagement>, in which you specify the version you want like
<dependency>
<groupId>org.apache.hive</groupId>
<artifactId>hive-jdbc</artifactId>
<version>3.1.0.3.1.0.0-78</version>
</dependency>
Then all transitively found versions are replaced by the one you specified an the conflict is gone.

Related

Maven transitive dependency on system scoped dependency

I have a spring boot project (2.1.3) in which I had to add a jar file supplied by one of our partners (Referred with com.aesenc group id). I added it as a system scoped dependency even though it is against the recommendation as this repo already had other system scoped dependencies (will address this in future). This broke one of the API calls due to a transitive dependency in the parnter-supplied jar (commons-codec). Spring boot started using this commons-codec instead of the one that came with the spring bom. To resolve the issue I added exclusion to the system scoped dependency
<dependency>
<groupId>aesenc.group</groupId>
<artifactId>com.aesenc</artifactId>
<version>1.0</version>
<scope>system</scope>
<exclusions>
<exclusion> <!-- declare the exclusion here -->
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</exclusion>
</exclusions>
<systemPath>${basedir}/src/main/resources/libs/AESEnc/AESEnc.jar</systemPath>
</dependency>
This didn't solve the issue. So after going through the maven documentation I added commons-codec updated version as a dependency in the current project to make it an immediate child in the dependency graph
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.15</version>
</dependency>
This alone also didn't solve the issue. But by moving it above the com.aesenc in the pom file the issue got resolved. So I'm confused about my understanding of how dependency resolution is happening in Maven.
This didn't work:
My project +
|
+-aesenc-+
| |
| +commons-codec-v1.10
|
+commons-codec-v1.15
My assumption is that this is how the dependency tree is and just by adding v1.15 as a dependency would have solved the issue irrespective of the ordering of it in pom.
This worked:
My project +
|
+commons-codec-v1.15
|
+-aesenc-+
|
+commons-codec-v1.10
Would like to know where my assumptions have gone wrong.

javax/inject/Inject.class in lib/javax.inject-1.jar is hidden by lib/javax.inject-2.5.0-b42.jar on onejar executable

I am attempting to create an atomic executable jar (i.e. no dependencies outside of the jar).
To do this I have added a com.jolira:onejar-maven-plugin in my pom.xml. This seems to do the job, but when I execute the jar I get the warnings:
JarClassLoader: Warning: Null manifest from input stream associated with: lib/javax.inject-1.jar
JarClassLoader: Warning: javax/inject/Inject.class in lib/javax.inject-1.jar is hidden by lib/javax.inject-2.5.0-b42.jar (with different bytecode)
JarClassLoader: Warning: javax/inject/Named.class in lib/javax.inject-1.jar is hidden by lib/javax.inject-2.5.0-b42.jar (with different bytecode)
It seems that my dependencies are pulling in both javax.inject-1.jar and javax.inject-2.5.0-b42.jar. To verify this I checked and both have/are being downloaded from the repository. I certainly don't have both listed in the dependencies, so there must be some implied dependency AFAICS.
Anyone know if there is a way to exclude just one jar from a maven dependency, or alternately to prevent onejar-maven-plugin from including it in the executable jar?
Is there a better way to create an atomic (or some call them fat) jar where the java loader can actually load from an embedded jar. I've tried all day with various different recipes and onejar was the only one that actually got the loaded to work.
After some playing I found Alex's solution to be correct, just that I had put the exclude in the wrong place. The solution is to put it here:
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
<version>2.26</version>
<exclusions> <!-- exclude exclude javax.inject-1.jar -->
<exclusion>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
</exclusion>
</exclusions>
</dependency>
Just putting this here for future.
I solved the problem in this way:
(It's for project's dependency which has javax.inject in its own dependencies)
<exclusion>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
</exclusion>

Cannot find openam-oauth2-common 13.0.0 version

We are upgrading openam to version 13. I've set artifacts version to 13.0.0 but when I start building the service with Maven I get a error message saying:
failure to find org.forgerock.openam:openam-oauth2-common:jar:13.0.0.
We are using forgerock repository: http://maven.forgerock.org/repo/repo/
Question: why the dependency is suddendly not available any longer and how to properly upgrade it?
It appears that the artifact you were using has been refactored, moving from a single project (i.e. a library) to a multi-module project (several modules, several libraries). Hence, although its Maven coordinates have not changed (GAV, GroupId, ArtifactId, Version), the usage (the consumption) of this library has been directly affected because its type has changed (again, from jar to pom).
Version 11.0.0, for example, was a jar, hence you could import it as most of the Maven dependency, via a dependency section.
However, since version 12.0.0, the artifact is a pom defining the following modules:
<module>oauth2-core</module>
<module>oauth2-restlet</module>
<module>openid-connect-core</module>
<module>openid-connect-restlet</module>
<module>oauth2-oidc-test-server</module>
Hence, what previously would have been:
<dependency>
<groupId>org.forgerock.openam</groupId>
<artifactId>openam-oauth2-common</artifactId>
<scope>provided</scope>
<version>11.0.0</version>
</dependency>
It cannot be simply upgraded via its version number but must be replaced via several dependencies (you can now narrow down what you actually need):
<dependency>
<groupId>org.forgerock.openam</groupId>
<artifactId>oauth2-core</artifactId>
<version>13.0.0</version>
</dependency>
<dependency>
<groupId>org.forgerock.openam</groupId>
<artifactId>oauth2-restlet</artifactId>
<version>13.0.0</version>
</dependency>
<dependency>
<groupId>org.forgerock.openam</groupId>
<artifactId>openid-connect-core</artifactId>
<version>13.0.0</version>
</dependency>
<dependency>
<groupId>org.forgerock.openam</groupId>
<artifactId>openid-connect-restlet</artifactId>
<version>13.0.0</version>
</dependency>
<dependency>
<groupId>org.forgerock.openam</groupId>
<artifactId>oauth2-oidc-test-server</artifactId>
<version>13.0.0</version>
</dependency>
Most probably version 11.0.0 is provided as a subset of the dependencies above, including them should fix the issue (but you could also investigate later on which one is effectively required by your project, e.g. the last one, oauth2-oidc-test-server, is most probably not required simply looking at its artifactId name, as an immediate guess).

Serialization errors due to jackson-databind version mismatch?

I am running into the following error
java.lang.NoSuchFieldError: WRITE_DURATIONS_AS_TIMESTAMPS
at com.fasterxml.jackson.datatype.joda.ser.DurationSerializer.<init>(DurationSerializer.java:28)
at com.fasterxml.jackson.datatype.joda.ser.DurationSerializer.<init>(DurationSerializer.java:25)
at com.fasterxml.jackson.datatype.joda.JodaModule.<init>(JodaModule.java:45)
I checked to see what versions of jackson-datatype-joda are available. It appears that maven has excluded all version mismatches.
Any other reason this might cause serialization errors?
The problem is that among the maven dependencies (mind that it could be a transitive one) you have incompatible versions of jackson-datatype-joda and jackson-databind. Incompatible in the sense that jackson-databind's SerializationFeature class is missing the WRITE_DURATIONS_AS_TIMESTAMPS field. To see what dependencies maven brings you can run the following command in the terminal (or you can use an IDE's maven plug to search and analyse the maven dependency tree):
mvn dependency:tree | grep databind
the outcome will most probably be something like:
[INFO] | +- com.fasterxml.jackson.core:jackson-databind:jar:2.4.1:compile
The version of course can vary but the important thing is that the WRITE_DURATIONS_AS_TIMESTAMPS field is only available since version 2.5
You can exclude a transitive dependency like this:
<dependency>
<groupId>group.id</groupId>
<artifactId>artifact-id</artifactId>
<version>${artifact.version}</version>
<exclusions>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</exclusion>
</exclusions>
</dependency>
If it's not a transitive dependency you need to update version of jackson-databind.
I got it resolved by using following dependency as this dependency has overridden any other version used:
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-joda</artifactId>
<version>2.5.3</version>
</dependency>
I had same error. I had included all jackson*2.7.0 libraries under WEB-INF/lib/ and i was still getting that error. I am using wildfly 8.2 and it had jackson 2.4.1 libraries under modules and somehow it was loading 2.4.1 jars from that location. So I had to manually upgrade them to 2.7.0 which fixed the issue. I was under impression that if I did not mention it to load jackson jars in deployment configuration file, it would not load wildfly jars. I guess I was wrong.

Spring Jar dependency Presedence

I have one Spring application(CustomerPort). In this I am using one open source jar(commons-lang.2.4). And my CustomerPort using other module, as jar, which using different version "commons-lang.2.2".
Since the other module using commons-lang.2.2, my application also refereeing modules opensource jar instead of commons-lang.2.4.
Could you plz let me how to exclude commons-lang.2.2 in Pom.xml file
use the <scope> tag to correct the scope of these transitive dependencies. Read this for more info on maven dependency scopes
In the pom.xml for CustomerPort, where you specify the dependency on the other jar module, you can specify an exclusion for commons-lang. This will prevent Maven from bringing in the commons-lang transitive dependency from the other jar.
<dependency>
<groupId>otherModuleGroupId</groupId>
<artifactId>otherModuleArtifactId</artifactId>
<version>otherModuleVersion</version>
<exclusions>
<exclusion>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
</exclusion>
</exclusions>
</dependency>
Verify that its doing the right thing by running mvn dependency:tree in CustomerPort.
More info on excluding transitive dependencies here

Resources