Dependency issue with Maven - java

I've a Maven project that I want to test using Junit, Mockito and Cucumber, but I've a big problem with the dependencies. The project has no problem with this maven command: clean install package -X with skip tests.

You are overriding Jackson libraries indeed, your pom has this:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.7.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<version>${jackson.version}</version>
</dependency>
jackson-databind comes from fasterxml and has explicit version while other members come from codehaus and have not.
Basically your pom is pretty messy, I would suggest t clean it up, it will be twice smaller after that.
For instance Spring framework also contains Jackson libraries in its modules and re-importing it again is not required or even not recommended but your Spring dependencies are the same messy as the rest of it so its hard to say what's pulled actually.
Try to examine your effective pom first and remove or exclude all duplicates, especially from different vendors.

Related

How to specify certain dependency version for one of my dependencies in Maven

I have a project which uses the latest version of Hibernate (let's say v2.0). I'm using it all around the project. But my project also uses some dependency (let's say MySQL Connector), which uses Hibernate (let's say v1.0). So in my pom.xml I would have something like:
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>Hibernate</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>org.mysql</groupId>
<artifactId>MySQLConnector</artifactId>
<version>3.7</version>
</dependency>
</dependencies>
In the end, when I compile my project, the version of Hibernate downloaded and used is v1.0 because MySQLConnector needs this one. Is there a way to specify some version of a dependency that will be used only by one of my dependencies and the rest of the code to use another version? So something like:
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>Hibernate</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>org.mysql</groupId>
<artifactId>MySQLConnector</artifactId>
<version>3.7</version>
<somemagicaltag>
<groupId>org.hibernate</groupId>
<artifactId>Hibernate</artifactId>
<version>1.0</version>
</somemagicaltag>
</dependency>
</dependencies>
Thus allowing MySQLConnector to use the older version of Hibernate if it likes it, but the rest of my code to use the newer, more updated version of Hibernate?
Is there a way to specify some version of a dependency that will be
used only by one of my dependencies and the rest of the code to use
another version?
No. There can be only one. So in your case either 1.0 or 2.0 (usually using newer version makes more sense). Which version is used depends on the order of dependencies in pom.xml which use such transitive dependency: Why order of Maven dependencies matter?
You can also define which version will be used by specifying such dependency (this overrides transitive dependency version) or by defining such dependency either in dependencyManagement tag: Differences between dependencyManagement and dependencies in Maven or by using BOM mechanism: Maven BOM [Bill Of Materials] Dependency
In all "normal" cases, the dependency that you declare wins against the ones that come transitively. So I would assume that in your setup, you get version 2 of hibernate (and nothing else). You can find out by calling mvn dependency:list.
You cannot load the same class twice in different versions, so normally, you cannot have two versions of hibernate in the same project. There are approaches around this (using the Maven shade plugin), but this should be the exception. Try to make your own code and your dependencies work with the same version of hibernate.
You can skip downloading that default artifact which is getting downloaded by Maven.
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>Hibernate</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>org.mysql</groupId>
<artifactId>MySQLConnector</artifactId>
<version>3.7</version>
<exclusions>
<exclusion> <!-- declare the exclusion here -->
<groupId>org.hibernate</groupId>
<artifactId>Hibernate</artifact>
</exclusion>
</exclusions>
</dependency>
</dependencies>

Looking for JsonParser dependency

I have worked out that JsonParser is in javax.json.stream but i have no idea where i can get a hold of it. Can anyone help me?
https://docs.oracle.com/javaee/7/api/javax/json/stream/package-summary.html
That's the library i am looking for.
I have tried looking at the maven repositories and found something similar called javax.json-api but it does not contain JsonParser.
If you are using Json-simple, use the below maven dependency.
<dependency>
<groupId>com.googlecode.json-simple</groupId>
<artifactId>json-simple</artifactId>
<version>1.1</version>
</dependency>
Link: https://mvnrepository.com/artifact/com.googlecode.json-simple/json-simple/1.1
If you are using maven, you can add the following dependency
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
</dependency>
you can also download the artefact manually here
http://central.maven.org/maven2/javax/javaee-api/7.0/javaee-api-7.0.jar
For Gradle, use
compile group: 'javax', name: 'javaee-api', version: '7.0'
The site https://mvnrepository.com shows you the different dependencies for different build systems.
Please note that this is only one possible dependency. You can certainly find smaller dependencies, which only contain the classes you want. Simply search for it on google or mavencentral.

How to exclude a maven dependency if in the parent project exists a newer version of it

I am working with a Maven project where I have spring framework dependency version 3.2.3.RELEASE and I have to import this project into many others but in some of them I am using spring 4.
How can I exclude this dependency (spring 3) only in case that the project that uses mine has the same or newer version of spring and in those who hasn't use mine?
One thing you can do is to manually exclude unwanted dependencies:
<dependency>
<groupId>com.your.project</groupId>
<artifactId>project-name</artifactId>
<version>1.0.0</version>
<exclusions>
<exclusion>
<artifactId>org.springframework</artifactId>
<groupId>spring-core</groupId>
</exclusion>
</exclusions>
</dependency>
But that can get quite verbose.
It may help if you elaborate a bit more on the problem description as it is not clear to me what exactly are you trying to solve or achieve.
For instance if you include a dependency A which has a dependency B in version 1.0 and then you include B in your pom in 1.1 Maven will use only 1.1. I recommend reading up on it a bit here: https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Transitive_Dependencies

What is the difference between the GeoIP2 MaxMind pom and my local one?

I'm following this guide:
https://github.com/maxmind/GeoIP2-java
It says:
We recommend installing this package with Maven. To do this, add the dependency to your pom.xml:
<dependency>
<groupId>com.maxmind.geoip2</groupId>
<artifactId>geoip2</artifactId>
<version>2.2.0</version>
</dependency>
There is also pom.xml file in the Git repository of GeoIP2 which is much longer - what is the difference between them?
Cited from the official homepage:
Apache Maven is a software project management and comprehension tool. Based on the concept of a project object model (POM), Maven can manage a project's build, reporting and documentation from a central piece of information.
Think of the pom.xml as the heart of Maven. In the file you can specify dependencies (most typically jar files), and other information, such as how the project should be built. Without digging to deep into this, one of Maven's strengths is that it manages the dependencies of projects.
To answer your concrete question, GeoIP2 manages its dependencies using Maven. This section of its pom.xml defines them:
<dependencies>
<dependency>
<groupId>com.maxmind.db</groupId>
<artifactId>maxmind-db</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.http-client</groupId>
<artifactId>google-http-client</artifactId>
<version>1.20.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.5.3</version>
</dependency>
</dependencies>
By using Maven in your own project, you will only need to add the one dependency to GeoIP2. Maven will then search for the dependency in a repository, typically the Maven Central Repository if Maven isn't configured to use another. It will also automatically download all other needed dependencies (transitive dependencies), in this case it would be the dependencies listed above, plus any other dependencies those in turn depend on, and so on.
So, a short recap: Without a dependency management tool like Maven, you would need to manually make sure you have all the correct dependencies on the classpath. Maven fixes this for you.

Jena NoClassDefFoundError with Maven

I have a Java Maven project that I developed a while ago and that doesn't work anymore. It uses a parent pom together with another Maven project in which I think the Jena version was changed and it also uses an external library that uses Jena. The Maven dependency is:
<dependency>
<groupId>com.hp.hpl.jena</groupId>
<artifactId>jena</artifactId>
<version>2.6.4</version>
</dependency>
When I execute my tests I get the following errors:
java.lang.NoClassDefFoundError: Could not initialize class
com.hp.hpl.jena.query.ARQ
java.lang.NoClassDefFoundError: org/apache/jena/iri/IRIFactory
at org.openjena.riot.system.PrefixMap.add(PrefixMap.java:54)
at com.hp.hpl.jena.sparql.util.MappingRegistry.addPrefixMapping(MappingRegistry.java:33)
at com.hp.hpl.jena.query.ARQ.init(ARQ.java:449) [...]
The errors are not thrown by my code directly but by the library I include. Can I prevent this by downgrading the Jena version in the parent pom or what can I do here?
P.S.: I now have a minimal code example that reproduces the error (java.lang.NoClassDefFoundError: org/apache/jena/iri/IRIFactory):
import org.junit.Test;
import com.hp.hpl.jena.query.ARQ;
public class DependencyTest
{
#Test
public void testARQ()
{
ARQ a = new ARQ();
}
}
And I guess it comes from this dependency:
<dependency>
<groupId>org.apache.jena</groupId>
<artifactId>jena-arq</artifactId>
<version>2.9.1-incubating-SNAPSHOT</version>
</dependency>
I know there is probably a factory instead of a constructor but I guess this still shows where the problem is.
P.S.: I noticed that I had the dependencies "jena", "arq" and "jena-arq":
<dependency>
<groupId>com.hp.hpl.jena</groupId>
<artifactId>arq</artifactId>
<version>2.8.8</version>
</dependency>
<dependency>
<groupId>org.apache.jena</groupId>
<artifactId>jena-arq</artifactId>
<version>2.9.1-incubating-SNAPSHOT</version>
</dependency>
dependency>
<groupId>com.hp.hpl.jena</groupId>
<artifactId>jena</artifactId>
<version>2.6.4</version>
</dependency>
So I thought maybe I have too much overlapping dependencies and commented out "jena" and "arq". But I still get the error
java.lang.NoClassDefFoundError: Could not initialize class com.hp.hpl.jena.query.ARQ
at com.hp.hpl.jena.sparql.engine.http.QueryEngineHTTP.<init> [...]
I also tried out forcing a non-snapshot-version 2.9.0-incubating, but then I still get the NoClassDefFoundError with and without using the "jena" and "arq"-dependencies.
P.P.S.:
I still get the same error even when I use the following dependencies:
<dependency>
<groupId>org.apache.jena</groupId>
<artifactId>jena-arq</artifactId>
<version>2.9.0-incubating</version>
</dependency>
<dependency>
<groupId>org.apache.jena</groupId>
<artifactId>jena-core</artifactId>
<version>2.7.0-incubating</version>
</dependency>
<dependency>
<groupId>org.apache.jena</groupId>
<artifactId>jena-iri</artifactId>
<version>2.7.0-incubating</version>
</dependency>
You can search for the missing class using the Maven Central search application
http://search.maven.org/#search|ga|1|fc%3A%22com.hp.hpl.jena.query.ARQ%22
It demonstrates that the dependency you appear to be missing is:
<dependency>
<groupId>com.hp.hpl.jena</groupId>
<artifactId>arq</artifactId>
<version>2.6.0</version>
</dependency>
Doesn't appear to be a version 2.6.4, but you're probabily best advised to go for a more modern version (This project was recently donated to apache)
Instructions for using Apache Jena with Maven are here:
incubator.apache.org/jena/download/maven.html
Specifying ARQ 2.9.0 as a dependency in your project pom.xml will pull in the other Jena components that you need.
I finally resolved this error by excluding the "jena"-Dependency brought in as a transitive dependency from some library.

Categories