Get Derived ("Blessed") Version of Dependency from Spring Boot Gradle Plugin - gradle

I have a Spring Boot project which uses "blessed" dependencies via the Gradle plugin. The dependencies block in my build.gradle file looks like this:
dependencies {
compile "org.springframework.boot:spring-boot-starter-web"
compile "org.springframework.boot:spring-boot-starter-data-jpa"
compile "com.fasterxml.jackson.core:jackson-core"
compile "com.fasterxml.jackson.dataformat:jackson-dataformat-csv"
}
(I've removed several other dependencies for brevity.)
The above code is broken because Spring Boot does not have a "blessed" version for the dataformat-csv extension.
All I want to do is get it to use the Spring Boot-derived version for jackson-core and use it for the jackson-dataformat-csv as well for consistency. How do I get the version number for that dependency if it's been derived by a plugin?

Related

reactor.netty error when depending on spring-boot-starter-webflux

I have a java project based on Spring framework, which is based on gradle build tool.
The gradle configures a parent project Par and sub-project Child.
The Par project has the build.gradle setting spring framework boot version as 2.2.6:
plugins {
id 'org.springframework.boot' version '2.2.6.RELEASE'
...
}
The Child project has the build.gradle as below:
ext.versions = [
spring: '5.2.9.RELEASE',
spring_boot: '2.2.10.RELEASE',
slf4j: '1.7.30',
grpc_helpers_java: '^19.0'
]
I tried to use WebClient of spring framework, so I added spring-boot-starter-webflux dependency to the build.gradle file of the child project as below:
dependencies {
...
compile group: 'org.springframework.boot', name: 'spring-boot-starter-webflux', version: versions.spring_boot
...
}
I don't have other code change yet.
However, although the build passed, the bootRun from the Par project failed with the following error:
An attempt was made to call a method that does not exist. The attempt was made from the following location:
org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory.createHttpServer(NettyReactiveWebServerFactory.java:163)
The following method did not exist:
'reactor.netty.transport.Transport reactor.netty.http.server.HttpServer.runOn(reactor.netty.resources.LoopResources)'
The method's class, reactor.netty.http.server.HttpServer, is available from the following locations:
jar:file:/C:/Users/XXX/.gradle/caches/modules-2/files-2.1/io.projectreactor.netty/reactor-netty/0.9.12.RELEASE/41022546d07f1499fb9d8617bba4a1a89d3549db/reactor-netty-0.9.12.RELEASE.jar!/reactor/netty/http/server/HttpServer.class
The class hierarchy was loaded from the following locations:
reactor.netty.http.server.HttpServer: file:/C:/Users/XXX/.gradle/caches/modules-2/files-2.1/io.projectreactor.netty/reactor-netty/0.9.12.RELEASE/41022546d07f1499fb9d8617bba4a1a89d3549db/reactor-netty-0.9.12.RELEASE.jar
Action:
Correct the classpath of your application so that it contains a single, compatible version of reactor.netty.http.server.HttpServer
I think the transitive dependency reactor.netty has a version of 0.9.12 is correct based on the spring-boot-starter-webflux version of 2.2.10. So I do not understand why the bootRun is trying to look for reactor.netty.http.server.HttpServer.runOn method which doesn't exist for reactor.netty version 0.9.12
Thank you very much.

Library version in gradle downgraded

When executing (in gradle 6.5)
./gradlew dependencyInsight --dependency groovy-testng --configuration testRuntimeClasspath
I could find groovy-testng comes from groovy-all library which was added to our build.gradle. I wanted to update version of groovy-testng, so I decided to update groovy-all which, according to mvnrepository, contains groovy-testng in version 3.0.4, but still the version of groovy-testng was the old one and gradle didn't resolve it to the latest version:
org.codehaus.groovy:groovy-testng:2.5.12 (selected by rule)
variant "runtime" [
org.gradle.status = release (not requested)
org.gradle.usage = java-runtime
org.gradle.libraryelements = jar
org.gradle.category = library
Requested attributes not found in the selected variant:
org.gradle.dependency.bundling = external
org.gradle.jvm.version = 11
]
org.codehaus.groovy:groovy-testng:3.0.4 -> 2.5.12
\--- org.codehaus.groovy:groovy-all:3.0.4
\--- testRuntimeClasspath
I have found the line selected by rule but couldn't find any ResolutionStrategy in my project, so I started to comment out and see what causes this. It turned out it's a plugin org.springframework.boot together with io.spring.dependency-management causes this version to be downgraded. Why? And why only when both of them are included? I assume these plugins define some ResolutionStrategy? What is the easiest way to find out where is the ResolutionStrategy coming from?
The Spring Dependency Management plugin is rather heavy handed. If were you build your project with --info or -i, you will see a bunch of these logs:
Applying dependency management to configuration 'bootArchives' in project 'demo'
Applying dependency management to configuration 'archives' in project 'demo'
Applying dependency management to configuration 'default' in project 'demo'
Applying dependency management to configuration 'compile' in project 'demo'
Applying dependency management to configuration 'implementation' in project 'demo'
Applying dependency management to configuration 'runtime' in project 'demo'
Applying dependency management to configuration 'compileOnly' in project 'demo'
From my experience, the dependency management plugin will win/force itself to win.
I can see in your snippet, that you wanted 3.0.4 of Groovy, but Gradle resolved 2.5.12. If you look at the Spring Boot Dependencies BOM, you will see that 2.5.12 is the current version for Spring Boot 2.3.1: https://github.com/spring-projects/spring-boot/blob/2.3.x/spring-boot-project/spring-boot-dependencies/build.gradle#L365..L371
The Spring Boot Gradle plugin detects if the Spring dependency management plugin is present, and if so, configures the plugin to import the Spring Boot dependencies BOM: https://github.com/spring-projects/spring-boot/blob/master/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/DependencyManagementPluginAction.java
From looking at the BOM: https://repo1.maven.org/maven2/org/springframework/boot/spring-boot-dependencies/2.3.1.RELEASE/spring-boot-dependencies-2.3.1.RELEASE.pom
You should be able to override the Groovy version like so:
ext {
set("groovy.version", "3.0.4")
}
The Spring dependency management plugin should pick that up and apply 3.0.4
If that doesn't solve your issue, then you have other plugins or configuration at play here that you will need to figure out.
I also suggest watching Managing Dependencies for Spring Projects with Gradle to learn the differences between Spring dependency management plugin and Gradle's native dependency management.

spring boot plugin and gradle dependency implementation

We have been using gradle spring boot plugin version 1.5.14 and gradle 4.10.3 for our builds. After an upgrade of gradle to 6.2.2, we've also changed dependency-definition from compile group to implementation group i.e.:
compile group: 'org.springframework.boot', name: 'spring-boot-starter-integration'
to
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-integration'.
The fat jar created via gradle assemble does to my surprise not contain the required libs under BOOT-INF/lib anymore? If I replace "implementation" with "compile" it works again as expected.
Is there something which needs to be configured so that spring-boot-plugin adds them? Or do I need to upgrade the project to spring boot 2 beforehand?
Implementation will bring in the dependency only for that module it is declared in.
Compile will allow a module that depends on the module to use the dependency as well.
Say you have Module A depending on Module B.
Module A and B both need the dependency:
com.font:font1:1.1.1
If B uses:
implementation 'com.font:font1:1.1.1'
A will not see font1, and will need to bring it into its own build.gradle file as well.
compile 'com.font:font1:1.1.1'
will make it available to the entire classpath (which should be avoided anyway, and the new equivalent is for libraries which uses 'api' instead of 'compile').
Without seeing your project directory, I'm assuming that some dependency is not being pulled into a place where it used to be grabbed from a lower dependency in the hierarchy. You should be able to find the missing dependencies easily by changing compile to implementation one at a time, unless you have a huge multi-module project.

liquibase.integration.spring.SpringLiquibase is available from 2 locations error in spring boot

I'm trying to integrate spring boot with liquibase, but when I run the application it throws the following error:
An attempt was made to call the method liquibase.integration.spring.SpringLiquibase.setLiquibaseSchema(Ljava/lang/String;)V but it does not exist. Its class, liquibase.integration.spring.SpringLiquibase, is available from the following locations:
jar:file:/C:/Users/Dev/.gradle/caches/modules-2/files-2.1/org.liquibase/liquibase-core/3.5.5/c65051f327382018bd09c30380f25eac96f210da/liquibase-core-3.5.5.jar!/liquibase/integration/spring/SpringLiquibase.class
It was loaded from the following location:
file:/C:/Users/Dev/.gradle/caches/modules-2/files-2.1/org.liquibase/liquibase-core/3.5.5/c65051f327382018bd09c30380f25eac96f210da/liquibase-core-3.5.5.jar
Action:
Correct the classpath of your application so that it contains a single, compatible version of liquibase.integration.spring.SpringLiquibase
It looks like that the problem is given by spring-boot-starter-data-jpa, as soon as I remove the dependency, the application runs fine. This is my full dependency list, but I would also need JPA to write my persistence classes.
dependencies {
compile('org.springframework.boot:spring-boot-starter-actuator')
compile 'org.springframework.boot:spring-boot-starter-web'
runtime('org.postgresql:postgresql:42.2.5')
compile 'org.webjars:bootstrap:4.1.3'
compile 'org.webjars:webjars-locator-core'
compile("org.springframework.boot:spring-boot-starter-data-jpa")
compile("org.hibernate:hibernate-entitymanager:4.3.4.Final")
compile("org.hibernate:hibernate-validator:6.0.16.Final")
compile ("org.hibernate:hibernate-core:5.4.1.Final")
testCompile 'org.springframework.boot:spring-boot-starter-test'
compile("org.liquibase:liquibase-core:3.5.5")
liquibaseRuntime 'org.liquibase:liquibase-gradle-plugin:2.0.1'
liquibaseRuntime 'org.liquibase:liquibase-groovy-dsl:2.0.2'
liquibaseRuntime "org.liquibase:liquibase-core:3.5.5"
liquibaseRuntime 'org.postgresql:postgresql:42.2.5'
}
Any idea why there's a mismatch?
Thanks in advance
Remove the version from your configuration:
compile("org.liquibase:liquibase-core")
Let Spring Dependency Management take care of that for you.
I solved it in my maven project just by removing the Liquibase version in the POM
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
</dependency>
Leave it this way without the version and Spring takes care of the rest.
In my case upgrading to using both Spring Boot 2.1.0.RELEASE and org.liquibase:liquibase-core:3.6.3 solved the issue entirely.
Sounds like two different dependencies include a duplicate jar.
There seems to be a plugin that manages dependencies in Gradle, take a look here.

Gradle: Compile Dependencies

I'm using mongodb with Spring Boot. Recently, my mongodb was upgraded to version 3.0.
I'm using the following Gradle dependencies for Spring:
buildscript {
ext {
springBootVersion = '1.2.6.RELEASE'
}
dependencies {
compile 'org.springframework.boot:spring-boot-starter-data-mongodb'
}
If I look on maven repositories for Gradle: 'org.springframework.boot:spring-boot-starter-data-mongodb:1.2.6.RELEASE', I see the following (http://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-mongodb/1.2.6.RELEASE):
The dependencies for the mongo-java-drivers are 2.12.5 under the "Version" column. I was wondering what the "Update" column is there for and how can I use the version of the mongo-java-drivers listed there instead (3.0.4)?
Since I'm using mongo 3.0, I would like to use the 3.0.4 java-drivers instead of 2.12.5 as I need to update my java-drivers to be at least 2.13 before they will work with my mongodb 3.0: http://docs.mongodb.org/manual/release-notes/3.0-scram/#upgrade-drivers
Just add the following dependency to your project dependencies:
compile 'org.mongodb:mongo-java-driver:3.0.4'
This will explicitly set there mongodb Java driver to the newest version and will overrun the transitive dependency version of spring-boot-starter-data-mongodb.
BTW, the "Updates" column means the newest version for a specific Artifact.
You can force the usage of a newer version of a dependency by just explicitly adding the dependency version that you want to use in the pom.xml.
Then Maven will use the explicitly specified version to compile.
FYI, you can exclude a dependency triggered by a direct dependency by using the exclude element.
See this doc to know how maven manages dependencies.
If you are using Gradle, see this page. In fact, you exclude the MongoDB transitive dependency triggered by spring boot and you explicitly add the latest version as a direct dependency.

Resources