Maven dependencies wrong version for okhttp3 mockwebserver - java

I am trying to use okhttp3.mockwebserver with my Spring boot project and I find out that okhttp3:mockwebserver:jar:3.14.9 is included instead of 4.9.1.
I have created small 'mock' projects to reproduce the issue I have in my prod.
The project is here https://github.com/mkarasik/okhttp-test
It contains two folders:
lib
This is a simple library including mockwebserver as dependency
pom.xml dependency
<dependencies>
...
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>mockwebserver</artifactId>
<version>4.9.1</version>
<exclusions>
<exclusion>
<artifactId>junit</artifactId>
<groupId>junit</groupId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
Maven dependencies tree
\- com.squareup.okhttp3:mockwebserver:jar:4.9.1:compile
+- com.squareup.okhttp3:okhttp:jar:3.14.9:compile
This is already wrong. Mockwebserver pom contains 4.9.1 okhttp artifact, however 3.14.9 is shown in tree
project
Simple Spring Boot app including lib project
<dependency>
<groupId>com.example</groupId>
<artifactId>lib</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>test</scope>
</dependency>
Maven dependencies tree
\- com.example:lib:jar:0.0.1-SNAPSHOT:test
\- com.squareup.okhttp3:mockwebserver:jar:3.14.9:test
\- com.squareup.okhttp3:okhttp:jar:3.14.9:test
\- com.squareup.okio:okio:jar:1.17.2:test
The same problem is here. okhttp3:mockwebserver:jar:3.14.9 is included instead of 4.9.1 as it is specified in my lib pom.xml.
Is there anything I am missing in my xml configuration?

Found it it it is described in Introducing dependencies in other projects causes Maven to downgrade okhttp3 version
<properties>
<okhttp3.version>4.9.1</okhttp3.version>
</properties>
Fixes the issue

OkHttp provides a Maven BOM you can use to ensure a consistent version
https://github.com/square/okhttp#releases
Also, we have a bill of materials (BOM) available to help you keep
OkHttp artifacts up to date and be sure about version compatibility.
This example is gradle, but you it is originally a feature from maven.
https://docs.gradle.org/6.2/userguide/platforms.html#sub:bom_import
dependencies {
// define a BOM and its version
implementation(platform("com.squareup.okhttp3:okhttp-bom:4.9.3"))
// define any required OkHttp artifacts without version
implementation("com.squareup.okhttp3:okhttp")
implementation("com.squareup.okhttp3:logging-interceptor")
}

Related

Maven not resolving given nested dependency version

I have given following module in module A:
<dependencies>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.9.2</version>
</dependency>
</dependecies>
And included module A in module B like:
<dependencies>
<dependency>
<groupId>com.example.test</groupId>
<artifactId>A</artifactId>
<version>1.01</version>
</dependency>
</dependecies>
But still mvn dependency:tree is showing 3.14.9 version in module B, please help.
[INFO] com.example.test:B:jar:1.01
[INFO] +- com.example.test:A:jar:1.01:compile
[INFO] | +- com.squareup.okhttp3:okhttp:jar:3.14.9:compile
I have also excluded it from all other modules that have 3.14.9 conflicts.
I know I can add okhttp 4.9.2 explicitly in module B but there are many such modules, I don't want to add explicitly 4.9.2 version each time.
For some reason, this is the case only for okhttp, rest other dependencies resolving given version
I don't see the version of artefact A you are trying to use in module B, can you check if it's the same version you are trying to build using okhttp 4.9.2
I solved the dependency resolution by enforcing dependency version in dependencyManagement in parent pom as mentioned in https://stackoverflow.com/a/2684291/5859017 in 2nd point. Maybe some dependency in parent pom was causing problem that has okhttp as transitive dependency.

Provide dependencies in the implementing app / module

I'm writing a library that I'd like to compile into implementable jar which then will be used in other projects / tests.
In my library I depend on various jars: okHttp, guava, etc., What I want to do is to tell maven not to put those dependencies into the final JAR but make that projects / modules that depend on this library provide those dependencies
How can this be done in maven?
library pom.xml
<groupId>com.example</groupId>
<artifactId>testing-library</artifactId>
<packaging>jar</packaging>
<version>1.0.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>28.2-jre</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.3.1</version>
<scope>compile</scope>
</dependency>
</dependencies>
implementation module pom.xml
<groupId>com.example</groupId>
<artifactId>implementation-</artifactId>
<version>1.0.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>testing-library</artifactId>
<version>1.0.0-SNAPSHOT</version>
<scope>test</scope>
</dependency>
</dependencies>
But I'm getting java.lang.NoClassDefFoundError: com/google/common/base/Preconditions error
If you put code into src/test/java, this code will not be part of the final jar. The code is meant for tests during the build of the jar.
If your library is a helper library for tests, put the code into src/main/java and reference it in other projects with <scope>test</scope>.
BTW, don't use Maven shade plugin or Maven assembly plugin for a library. These are mainly meant for standalone jars that run on their own.
Ok, I solved the issue. It seems that the generated POM.xml for the testing-library did not contain any dependencies.
I was using mvn install:install-file ... -DgeneratePom=true for installing jar into local repository for quick debugging and the pom generated this way seemed to be lacking library dependencies'

Override library version in Spring

I have the spring-ws-security dependency in a Spring Boot 2.1.7 project:
<dependency>
<groupId>org.springframework.ws</groupId>
<artifactId>spring-ws-security</artifactId>
</dependency>
Internally, the spring-ws-security pom has this dependency:
<dependency>
<groupId>org.apache.wss4j</groupId>
<artifactId>wss4j-ws-security-dom</artifactId>
<version>${wss4j.version}</version>
<exclusions>
...
</exclusions>
</dependency>
The parent of spring-ws-security is spring-ws, whose pom has a property:
<wss4j.version>2.2.0</wss4j.version>
I am trying to override this property in my pom file:
<properties>
<wss4j.version>2.2.4</wss4j.version>
...
</properties>
But it keeps taking the original 2.2.0 version:
$ mvn dependency:tree | grep wss4j
[INFO] | +- org.apache.wss4j:wss4j-ws-security-dom:jar:2.2.0:compile
[INFO] | | \- org.apache.wss4j:wss4j-ws-security-common:jar:2.2.0:compile
It takes the 2.2.4 version only if I explicitly supply the dependencies:
<dependency>
<groupId>org.apache.wss4j</groupId>
<artifactId>wss4j-ws-security-dom</artifactId>
<version>2.2.4</version>
</dependency>
<dependency>
<groupId>org.apache.wss4j</groupId>
<artifactId>wss4j</artifactId>
<version>2.2.4</version>
<type>pom</type>
</dependency>
Isn't overriding the property enough? Am I doing something wrong?
Here there are two points to consider:
One if you want to override the version in the properties in pom.xml, then your pom should have a parent-child relationship
second is if you want to use a particular version then we need to
declare the required version in your pom.xml explicitly and may
exclude the dependency from the third party jar and do a mvn clean install
Here is more information on dependency management and properties in maven
As I know, if you leave it blank without define any version. it will get the newest version of its library. So, you are right if you want to override the newest version to old version or certain version, by put the specific version. Have you trying to "mvn clean install" for that project?

Maven transitive has compile scope though its in provided scope in dependency management

This is how my application POM looks and it uses a custom framework built on top of spring called myframework. Since it runs on websphere, and the core libraries are available as shared library in run time, I want to only package web library into my WAR. Though I have my shared library dependency defined with provided scope, and added the shared library BOM containing all the core libraries defined in provided scope. One of the transitive dependency which is part of core library slf4j is coming in compile scope, and it gets packaged inside the war, which I don't expect to happen. There are many core dependency like this which are getting into compile scope. Why is this happening?
Based on this post Maven transitive dependency has scope compile while when dependency has provided scope
My core library should be in provided scope, as I have imported a BOM which has all this core library defined in provided scope but that is not happening. I have also provided the maven dependency tree below. Please advice.
Note: I am involved in the development of the framework and I don't want to directly include all of the core jar in dependencymanagement section in provided scope in the application, as there are lot of libraries and I don't want each developers using this framework to be aware of all the core jars, and include them in dependencymanagement section instead want them to use a BOM/POM.
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.myframework</groupId>
<artifactId>myframework-shared-libs-bom</artifactId>
<version>${library.version}</version>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>com.myframework</groupId>
<artifactId>myframework-shared-libs</artifactId>
<version>${library.version}</version>
<type>pom</type>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.myframework</groupId>
<artifactId>myframework-web-libs</artifactId>
<version>${library.version}</version>
<type>pom</type>
</dependency>
</dependencies>
Maven Dependency tree
+- com.myframework:myframework-shared-libs:pom:4.0.0-SNAPSHOT:provided
| \- org.slf4j:jcl-over-slf4j:jar:1.7.6:provided
\- com.myframework:myframework-web-libs:pom:4.0.0-SNAPSHOT:compile
\- com.myframework:myframework-web:jar:4.0.0-SNAPSHOT:compile
\- com.myframework:myframework-core:jar:4.0.0-SNAPSHOT:compile
\- org.slf4j:slf4j-api:jar:1.7.21:compile

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.

Categories