Maven Dependency Conflict - java

A maven project consisting of some modules. One of my module is using guava dependency of google version 11.0.2. Now i am integrating another module in my project which is also using guava but version 14.
So i want that new module uses guava version 14 but remaining project use guava version 11.0.2. I have tried adding <exclusion></exclusion> of guava to the new module but it didn't work.
Any tips to solve this.
Update: #Guillaume Darmont's Answer solves the problem for different modules. but now my problem is, the new modules has 2 dependency one of the them is using guava 11.0.2 and other is using 14.0. how to manage this. can we specify separately in the pom of the module that which version of the guava it should use.?

As I understand your question, you may add a <dependencyManagement> for guava in your new module pom.xml :
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>14.0.1</version>
</dependency>
</dependencies>
</dependencyManagement>

mvn dependency:tree command will help to determine which module is bringing the Guava 14 jar file.

Firstly try mvn dependency tree and check the output it is possible that 11.0.2 has been transitively referenced from more than one of your projects dependencies and you will need to add exclusion to all the dependencies directly / indirectly pulling down the specific guava version you are trying to exclude.
Secondly resolving this conflict may not be straight forward. Looking at version number transition (11 to 14) sounds to me like a major transition, and you may have better chances keeping the 14 version and excluding the 11 something.
If the version change is not compatible with your application, you have pretty much no option but to use something like OSGi to ensure you can run different versions of same library in the project.

Related

How to add maven dependencies of json to modules in >= Java 9

in java 8 projects you simply add the following dependencys in maven
<dependency>
<groupId>javax.json</groupId>
<artifactId>javax.json-api</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.json</artifactId>
<version>1.1</version>
</dependency>
Using OpenJDK, Eclipse 2018-12
and maven module, it results in getting a error in the module-info.java:
The package javax.json.stream is accessible from more than one module:
java.json, org.glassfish.java.json
So in both dependency projects there is a package called javax.json.stream and due to jigsaw module system this is not allowed anymore?
How to fix this?
EDIT:
I updated the maven dependency to 1.1.4 and put them on the classpath.
The javax.json-api has a module-info.java file and is working fine, eclipse shows no more errors.
But now the packages of the implementation javax.json (org.glassfish) are not found, resulting in a ClassNotFoundException: org.glassfish.json.JsonProviderImpl
What more can I do?
EDIT:
Its working now, i forgot to generate a module-info.java in this project.
So in both dependency projects there is a package called
javax.json.stream and due to jigsaw module system this is not allowed
anymore?
This is still allowed, but with both those dependencies getting resolved on the classpath instead of modulepath i.e. in the unnamed module.
Another alternative to fix this while you create your library as modular is to make sure to fix the downstream libraries exporting the same package which would require a bottom-up migration and you might have to wait for them to fix it in their latest update(or check if one is already out) and then to rely on them.

Maven dependencies for IBM Websphere packages

I'm trying to convert a "classic" JAVA EE project, using IBM websphere 8.0.0.5, into a maven multi module project and facing issues with the IBM dependecies.
We use IBM classes from the following packages:
com.ibm.websphere.asynchbeans
com.ibm.websphere.scheduler
com.ibm.websphere.ce.cm
com.ibm.ws.asynchbeans
com.ibm.ws.util.ThreadPool
To get my local project to be compiled I downloaded the was.installer-8.0.0.pm from IBM and installed it to my maven using
mvn install -f "was.installer-8.0.0.pom" -D serverInstallationFolder="C:\Program Files (x86)\IBM\WebSphere\AppServer"
This step was successfull according to command line output.
I then added the following dependencies to my project as described from IBM:
In parent:
<dependency>
<groupId>com.ibm.tools.target</groupId>
<artifactId>was</artifactId>
<version>8.0.0</version>
<type>pom</type>
<scope>provided</scope>
</dependency>
In module:
<dependency>
<groupId>com.ibm.tools.target</groupId>
<artifactId>was</artifactId>
</dependency>
But I still can't compile my project as the IBM packages are not found.
Can anyone help me to find and correct a mistake I made?
Edit
After following BevynQ tip from the comments I copied the "was_public.jar" to "was_public-8.0.0.jar" (described at IBM here) and added it to my repository:
mvn install:install-file -Dfile="C:\Program Files (x86)\IBM\WebSphere\AppServer\dev\was_public-8.0.0.jar" -DpomFile="C:\Program Files (x86)\IBM\WebSphere\AppServer\dev\was_public-8.0.0.pom"
I then changed the dependencies to:
<dependency>
<groupId>com.ibm.websphere.appserver</groupId>
<artifactId>was_public</artifactId>
<version>8.0.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.ibm.websphere.appserver</groupId>
<artifactId>was</artifactId>
</dependency>
This helped to get the compiling errors for the imports to com.ibm.websphere done.
What I now have still open is the packages com.ibm.ws.* package. Anyone have an idea?
Edit 2
I added the following dependency and then I was rid of the com.ibm.ws.* import errors.
<dependency>
<groupId>com.ibm.websphere.ws</groupId>
<artifactId>com.ibm.ws.runtime</artifactId>
<version>1.0.0</version>
</dependency>
But it still does not compile as now indirectly references can not be found (in my case commonj.work.WorkManager). It seems I need to add further .jars for every single thing. Isn't there an easier way to provide all websphere jars at once as descirbe in the above linked tutorial with the com.ibm.toolsdependency (which do not work)?
In general, com.ibm.websphere are public API for use by applications (this is true of the packages you listed above) which is consistent with these being in was_public.jar
However, com.ibm.ws package is generally product internals. May I ask what interface methods you are using from the com.ibm.ws.asynchbeans package? Maybe there is a public API alternative.
Regarding commonj.work, the only place I can find this in the WebSphere Application Server product image is WAS/plugins/com.ibm.ws.prereq.commonj-twm.jar so it looks like you will need to use that to compile against.
Here's the solution so I solved my dependency problems:
I configured the company repository manager (nexus) as a mirror. In this nexus all ibm packages are present. As you can think that solved the main problem.
I then added the following dependencies according to common maven style:
Dependencies in pom.xml (version numbers extracted to properties):
<dependency>
<groupId>com.ibm.websphere.ws</groupId>
<artifactId>com.ibm.ws.runtime</artifactId>
<version>${ibm.ws.runtime.version}</version>
</dependency>
<dependency>
<groupId>com.ibm.ws.prereq</groupId>
<artifactId>commonj-twm</artifactId>
<version>${ibm.ws.prereq.commonj-twm.version}</version>
</dependency>
Sorry I can't provide a "nice" solution that's useable by all people but the answer from njr and the comment from BevynQ helped at lot to get clearer with the problem and helped to solve the problem in a "more manual" way by copying the needed jars by hand.
I was facing this issue as I tried to build a project using Maven version 3.3.9, running on Java version 1.8.0_101, as depicted in the screenshot:
This is how I resolved it: Step 1. Download the commonj.jar from here.
Step 2. Determine which JDK your Maven is using by typing mvn -version in the command prompt.
Step 3. Go to that directory and place the commonj.jar file there in the jre/lib/ext directory, as shown below. Now your project should build in maven without any issues.

Java Maven - How to resolve the version if two third parties depend on different versions of a library

I have a scenario as follows:
I am using maven as a build process. I am creating a web project in which I want to use a specific version of spring. This project also depends on a third party library which internally depends on different version of spring. I have a doubt that this will result two different versions of spring n class-path and unexpected behavior will be observed. I have few information which I wanted to get more clarification on.
Can I use maven BOM concept for this?
Can somebody explain with example how to achieve this?
Can somebody explain how do we make sure that third party wont behave abnormally if overall project depicts using a specific version using BOM?
If somebody can throw light on it and give a detailing reference, that would help me a lot.
Maven should know how to evict one or more of conflicting versions of an artifact.
However, you can influence that by simply excluding one of the transitively included dependency.
Example: the following code excludes the io.netty (transitive) dependency. In this way, you'd leave maven with the only other version as you decide/prefer.
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-client</artifactId>
<version>${hbase.version}</version>
<!-- The exclusion below makes sure that this specific version imported by hbase does not end up deployed -->
<exclusions>
<exclusion>
<artifactId>netty</artifactId>
<groupId>io.netty</groupId>
</exclusion>
</exclusions>
</dependency>
Regarding runtime behavior, you have to test and decide for yourself (that is if you aren't lucky to have your direct artifact that documents versions of its own dependency)
You can use the concept of BOM but this won't avoid the conflicting issue of libraries by itself. It's very common that projects have one or more library which depends on the same other with different versions. In this case, when you want to force some specific library version for that third party library you must explicit it in your POM by using < exclusion > markups. This is not an easy task, once that projects usually have many libraries. So you need a tool to provide you an easy way to visualize a dependency hierarchy of your project libraries. There are some IDE plugins for this. Some versions of Eclipse, for example, have the maven plugin included in it, which provide a Dependency Hierarchy view ( a kind of dashborad of libraries and their dependencies ). Once you detected a library which should not using other library dependency ( wrong version for example ), you go at the this dependency in the pom and use the exclusion markup adjust the dependency version. Using the tool will make this task very simple.

Why do I need adding artifact JSR305 to use Guava 14+?

While looking for informations on stackoverflow, I have seen a question similar to mine, but with no real answer here.
I need migrating my maven project from guava 11.0.2 to guava 14 or higher (I need RangeSet). I updated my maven pom with the dependency:
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>14.0</version>
</dependency>
I then run the maven build, and got this error:
[ERROR] xxx.java: cannot find symbol
[ERROR] symbol : class Nonnull
[ERROR] location: package javax.annotation
I took a look closer, and this annotations is provided with JSR305, on which depends guava 11.0.2, as mvn repository reports it.
What I find strange is that guava 14 also depends on JSR305 as mvn repository reports.
If I add the JSR dependency to my pom, then the compilation just runs fine:
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
<version>1.3.9</version>
<scope>provided</scope>
</dependency>
But why would I have to add this dependency to my pom if guava already depends on it ? This looks more to a workaround than to a solution, and I would prefer to understand and make things clean.
Thanks for participating.
The reason that you need to add it as a dependency is because Guava 14 defines the dependency in their pom as follows:
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
<version>1.3.9</version>
<scope>provided</scope>
</dependency>
The important part for your problem is the <scope>provided</scope> line.
From the maven website they state the following with regards to provided dependencies:
provided:
This is much like compile, but indicates you expect the JDK or a container to provide the dependency at runtime. For example, when building a web application for the Java Enterprise Edition, you would set the dependency on the Servlet API and related Java EE APIs to scope provided because the web container provides those classes. This scope is only available on the compilation and test classpath, and is not transitive.
So basically because Guava have set this as a provided dependency they expect whoever is consuming Guava to provide this dependency which is exactly what you have had to do.
In Guava 11.0.2 it was a normal compile dependency, hence you didn't have to provide it in your own project.
The change was made in Guava 13. From the release notes:
Made findbugs a provided dependency to avert dep conflicts when using findbugs 2.0. The side-effect of this change is that projects which relied upon Guava to grant access to the JSR-305 annotations "for free" will break unless they provide their own direct dependency on that jar (or an equivalent). Projects should always have been directly depending on JSR-305 (per maven best-practice), but this change makes that should into a must.

Eclipse-Maven Complex Project Dependency (ApacheJena)

I'm fairly new to the Eclipse and Maven2 worlds. I'm struggling to comprehend how to add a Maven project dependency on Apache Jena in a simple way. Specifically, I'd like to add a dependency such as
<dependency>
<groupId>org.apache.jena</groupId>
<artifactId>jena</artifactId>
<version>${jena.version}</version>
</dependency>
And this would automatically pull in the modules(eg. jena-arq, jena-core, etc). However, adding this dependency results in a Missing artifact org.apache.jena:jena:jar:2.11.1 error. If I add <type>pom</type> to the dependency the error is gone but I do not get the jars in my project.
In any event, as I understand it, POM is more suited to project <--modules dependencies and what I'm really looking for is project --> lib archive dependencies.
How do I establish such a relationship? I considered simply replicating the dependency for each module in Jena since it's using a property anyway. However, it is possible, and Jena is a prime example, that not all modules in a project share the same version. For example jena-core is on 2.11.1 where jena-tdb is on 1.0.1 however jena-2.11.1 encompasses jena-tdb.
Thanks
See http://jena.apache.org/download/maven.html for details.
In brief:
<dependency>
<groupId>org.apache.jena</groupId>
<artifactId>apache-jena-libs</artifactId>
<type>pom</type>
<version>2.11.1</version> <!-- Set version -->
</dependency>
Note that it is type pom.
there is not a easy way do this.
you must define every dependency jar with special version.

Categories

Resources