How to override a plugin dependency in a Gradle conventions plugin - gradle

I'm using Gradle's conventions as described here:
https://docs.gradle.org/current/samples/sample_convention_plugins.html
And in the convention plugin, I'm applying a plugin (io.freefair.gradle:lombok-plugin:6.5.1) however I now need to override a dependency that it uses (I need org.projectlombok:lombok:1.18.22 not 1.18.24)
I've tried this:
buildscript {
dependencies {
classpath 'org.projectlombok:lombok:1.18.22'
}
}
plugins {
id 'groovy-gradle-plugin'
}
...
dependencies {
implementation 'io.freefair.gradle:lombok-plugin:6.5.1'
...
implementation 'org.projectlombok:lombok:1.18.22'
}
But version 1.18.24 was used. I've also tried adding this to my build.gradle:
buildscript {
dependencies {
classpath 'org.projectlombok:lombok:1.18.22'
}
}
plugins {
id 'billforward.java-conventions'
}
but still 1.18.24 was used.
As an aside, the two underlying issues I'm trying to solve are:
https://github.com/freefair/gradle-plugins/issues/549 - Resolved in 6.5 of lombok-plugin
https://github.com/projectlombok/lombok/issues/3180 - Broken in 1.18.24 of lombok

The lombok version used by io.freefair.lombok can be customized by using the lombok extension property:
plugins {
id "io.freefair.lombok" version "6.5.1"
}
lombok.version = "1.18.22"
This is documented here: https://docs.freefair.io/gradle-plugins/6.5.1/reference/#_io_freefair_lombok_base
Adding lombok itself to the buildscript classpath (or the runtime classpath of your gradle plugin) will not do anything.

Related

Error while trying to get build script read the java file - Could not resolve all artifacts for configuration ':classpath'

I'm trying to follow this by adding my own custom java file into the classpath
https://github.com/gigaSproule/swagger-gradle-plugin#model-converters
This is shown in the example above
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.custom:model-converter:1.0.0'
}
}
...
swagger {
apiSource {
...
modelConverters = [ 'com.custom.model.Converter' ]
}
}
This is my code
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("com.test.app.profile.component.MyOpenApiCustomiser:1.0.0")
}
}
swagger {
apiSource {
...
modelConverters = [ 'com.test.app.profile.component.MyOpenApiCustomiser' ]
}
}
This is the error I'm getting
A problem occurred configuring root project 'profile'.
> Could not resolve all artifacts for configuration ':classpath'.
> Could not find com.test.app.profile.component.MyOpenApiCustomiser:1.0.0:.
Required by:
project :
Possible solution:
- Declare repository providing the artifact, see the documentation at https://docs.gradle.org/current/userguide/declaring_repositories.html
I tried removing 1.0.0
Caused by: org.gradle.api.IllegalDependencyNotation: Supplied String module notation 'com.test.app.profile.component.MyOpenApiCustomiser' is invalid. Example notations: 'org.gradle:gradle-core:2.2', 'org.mockito:mockito-core:1.9.5:javadoc'
Not sure how I would get my build script to the use the MyOpenApiCustomiser in my spring boot application
Is there any other way or how to fix this?
The classpath dependency given in the buildscript.dependencies {} block needs to be a external library, given in the standard group:modulde:version notation; in the example from github project it's "com.custom : model-converter : 1.0.0" ( it's a "fake" library, does not really exist in maven central repo, it's just an example)
In your case, it seems you try to refer your class MyOpenApiCustomiser as the classpath library , which cannot work. It needs to be a real library.
If you want to use your own Converter, you'll need to implement it in another library/module, publish it to a private repository and then consume it in your buildscript classpath.
Another simpler way, would be to implement this converter as a class within the buildSrc project: these classes will then be automatically available in your build script classpath, and you can use it in the apiSource configuration.
Sample:
In your buildSrc project
build.gradle
plugins {
id("java")
}
repositories {
mavenCentral()
}
dependencies {
implementation "io.swagger:swagger-core:1.6.2"
}
Your custom ModelConverter class goes under src/main/java, e.g. com.sample.MyCustomConverter
In your root build.gradle script:
You can reference your MyCustomConverter class, it's already available in the script classpath, no need to define a classpath dependency in buildscript
swagger {
apiSource {
modelConverters = [ 'com.sample.MyCustomConverter' ]
// ....

Gradle build fails due to lombok

I'm using Gradle 4.10.2 (but would be fine using the latest version to get it to work). Here's my gradle file:
plugins {
id 'org.springframework.boot' version '2.2.5.RELEASE'
id 'io.spring.dependency-management' version '1.0.9.RELEASE'
id 'java'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
repositories {
jcenter()
}
ext {
set('springCloudVersion', "Hoxton.SR3")
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'
implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-xml'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
runtime 'org.springframework.boot:spring-boot-devtools'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}
When I execute bootJar, it fails with a lot of errors. The errors are all due to not finding getters, setters, etc. that are auto generated by lombok. How can I resolve the errors? I've seen other posts about this issue and they all recommend adding the lombok dependency as a annotationProcessor & compileOnly but I've already done this and still have this issue.
Update
Here are a couple of errors that I get:
C:\Users\user\eclipse-workspace\example\src\main\java\com\example\proj\service\CarService.java:60: error: cannot find symbol
log.debug("calling for cars {} ", cars);
^
symbol: variable log
location: class CarService
C:\Users\user\eclipse-workspace\example\src\main\java\com\example\proj\service\CarService.java:66: error: cannot find symbol
CarDtoBuilder dtoBuilder = dtoBuilderByCar.getOrDefault(
^
symbol: class CarDtoBuilder
location: class CarService
log should come from annotation #Slf4j. And the CarDtoBuilder is from #Builder(builderMethodName = "hiddenBuild") annotated on CarDto. Both are lombok annotations.
Update 2
Now trying Gradle 4.10.3. Same result. Here's output from gradle -v:
------------------------------------------------------------
Gradle 4.10.3
------------------------------------------------------------
Build time: 2018-12-05 00:50:54 UTC
Revision: e76905e3a1034e6f724566aeb985621347ff43bc
Kotlin DSL: 1.0-rc-6
Kotlin: 1.2.61
Groovy: 2.4.15
Ant: Apache Ant(TM) version 1.9.11 compiled on March 23 2018
JVM: 1.8.0_222 ( 25.222-b10)
OS: Windows 10 10.0 amd64
Update 3
I've tried this using Gradle 6 same result. I've tried using Windows and Mac... same result. I've tried using JDK 11 instead of JDK 8... same result.
Update 4
I'm using #Builder lombok annotation. I wonder if that is causing an issue.
I don't see your lombok-plugin configuration on your build.gradle file.
I had to setup lombok on my project for gradle 4.10.3 and this is what I did:
group 'io.metadata'
version '1.11-SNAPSHOT'
apply plugin: 'java'
project.ext.set("spring.boot.version", "2.2.6.RELEASE")
project.ext.set("spring.core.version", "5.2.5.RELEASE")
buildscript {
repositories {
maven {
url "https://plugins.gradle.org/m2/"
}
}
dependencies {
classpath("io.freefair.gradle:lombok-plugin:5.0.0-rc4")
}
}
subprojects {
repositories {
mavenLocal()
mavenCentral()
}
apply plugin: 'java'
apply plugin: 'io.freefair.lombok'
}
Check the apply plugin: 'io.freefair.lombok' and the dependencies defined for it on buildscript.
Note that I am using multi module project but either way you can use lombok plugin and apply it.
It is not mandatory to use lombok-plugin but it works very well and it's easy to do. You can follow the documentation here:
https://plugins.gradle.org/plugin/io.freefair.lombok
Remove any references to static imports involving code generated by lombok. In my case, I had:
import static com.example.car.dto.CarDto.CarDtoBuilder;
CarDtoBuilder was generated via lombok #Builder on the CarDto class. Once resolved, the other lobmok compile related issues such as log symbol not found (created by #Slf4j) go away.

How to avoid repeating dependency versions in a multi-module Gradle project?

There's a sample Spring Boot project here that contains two modules.
The build.gradle for one of the modules looks like this:
buildscript {
ext { springBootVersion = '2.1.4.RELEASE' }
repositories { mavenCentral() }
dependencies { classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") }
}
plugins {
id "io.spring.dependency-management" version "1.0.5.RELEASE"
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
bootJar {
baseName = 'gs-multi-module-application'
version = '0.0.1-SNAPSHOT'
}
sourceCompatibility = 1.8
repositories { mavenCentral() }
dependencies {
compile('org.springframework.boot:spring-boot-starter-actuator')
compile('org.springframework.boot:spring-boot-starter-web')
compile project(':library')
testCompile('org.springframework.boot:spring-boot-starter-test')
}
The other module's build.gradle looks like this:
buildscript {
repositories { mavenCentral() }
}
plugins { id "io.spring.dependency-management" version "1.0.5.RELEASE" }
ext { springBootVersion = '2.1.4.RELEASE' }
apply plugin: 'java'
apply plugin: 'eclipse'
jar {
baseName = 'gs-multi-module-library'
version = '0.0.1-SNAPSHOT'
}
sourceCompatibility = 1.8
repositories { mavenCentral() }
dependencies {
compile('org.springframework.boot:spring-boot-starter')
testCompile('org.springframework.boot:spring-boot-starter-test')
}
dependencyManagement {
imports { mavenBom("org.springframework.boot:spring-boot-dependencies:${springBootVersion}") }
}
The springBootVersion = '2.1.4.RELEASE' is declared in both modules. For a 2 module project that might not be a problem, but if my project had 10 modules and I wanted to make sure that all modules always depend on the same version of Spring Boot, it would be inconvenient and error-prone to repeat this version in every module.
Similarly, I might want to add a dependency on commons-io to both of these modules, and ensure they both always depend on the same version of commons-io.
How can I avoid repeating the version numbers in each and every build.gradle file?
See this Gradle documentation : a good practice in Gradle is to configure subprojects which share common traits in a single place, for example in the root project's build script (or using custom plugins)
EDIT the solution proposed here is no longer considered as good practice from Gradle team (the link above does not even mention subproject bloc in latests Gradle version doc); thank you #buggy for the warning .
In your example taken from Spring boot documentation, this pattern could be applied to centralize Spring boot and other common dependencies versions in a single place, but you could go further and also configure other common traits (Java plugin configuration, repositoties, etc..)
Here is how I would re-write the Spring example to make it cleaner and DRY:
Root project
/**
* Add Springboot plugin into build script classpath (without applying it)
* This is this only place where you need to define the Springboot version.
*
* See https://docs.spring.io/spring-boot/docs/current/gradle-plugin/reference/html/#managing-dependencies-using-in-isolation
*/
plugins {
id "org.springframework.boot" version "2.1.4.RELEASE" apply false
}
// Set version for dependencies share between subprojects
ext {
commonsIoVersion = "2.6"
}
subprojects {
// common config for all Java subprojects
apply plugin: "java"
apply plugin: "eclipse"
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
// apply Spring Boot's dependency management plugin
apply plugin: "io.spring.dependency-management"
}
Library sub-project
// no need for additional plugins
jar {
baseName = 'gs-multi-module-library'
version = '0.0.1-SNAPSHOT'
}
dependencies {
implementation('org.springframework.boot:spring-boot-starter')
implementation "commons-io:commons-io:${commonsIoVersion}"
testCompile('org.springframework.boot:spring-boot-starter-test')
}
dependencyManagement {
imports {
mavenBom org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES
}
}
Application sub-project
plugins {
id "org.springframework.boot"
}
bootJar {
baseName = 'gs-multi-module-application'
version = '0.0.1-SNAPSHOT'
}
dependencies {
implementation project(':library')
implementation ('org.springframework.boot:spring-boot-starter-actuator')
implementation ('org.springframework.boot:spring-boot-starter-web')
implementation "commons-io:commons-io:${commonsIoVersion}"
// could also be configured in root project.
testCompile('org.springframework.boot:spring-boot-starter-test')
}
Notes
this solution uses the new plugins {} DSL only (no need for old buildscript block)
version of the io.spring.dependency-management should not be configured explicitly, it will be inherit from Spring boot plugin
You can move the ext{} block to a new file and reference it in your project's build.gradle file via the apply from: statement.
// project/versions.gradle
ext {
springBootVersion = '2.1.4.RELEASE'
}
// project/build.gradle
buildscript {
apply from: 'versions.gradle'
}
// module/build.gradle
dependencies {
implementation "some.dependency:dependency:$springBootVersion"
}
Now you only have to define your dependency versions in one place.
Typically, a project will have a project-level build.gradle file in addition to module-specific build.gradle files. However, the repo you shared is missing the project-level build script. This is why the ext{} block is defined in each module's build script. This is likely not optimal, and I recommend looking at other repos to see how different developers tackled this issue.
There's a Gradle consistent versions plugin that will handle this:
https://github.com/palantir/gradle-consistent-versions
After you set this plugin up in the root build.gradle file, you will create a versions.props file like this, to use the example from the documentation.
com.fasterxml.jackson.*:jackson-* = 2.9.6
com.google.guava:guava = 21.0
com.squareup.okhttp3:okhttp = 3.12.0
junit:junit = 4.12
org.assertj:* = 3.10.0
There's also a versions.locks file, which is auto-generated by ./gradlew --write-locks. You can then specify version-less dependencies in your build.gradle files.

Spring Boot plugin doesn't add lib folder in jar

I have the following build.gradle:
group 'as'
version '1.0'
buildscript {
ext {
springVersion = '5.0.4.RELEASE'
springBootVersion = '1.5.6.RELEASE'
springJPAVersion = '2.0.5.RELEASE'
javaxVersion = '1.0.2'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
apply plugin: 'java'
apply plugin: 'org.springframework.boot'
jar {
baseName = 'reports'
version = '0.0.1'
manifest {
attributes 'Implementation-Title': baseName,
'Implementation-Version': version
}
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
}
repositories {
jcenter()
maven { url "https://repo.spring.io/snapshot" }
maven { url "https://repo.spring.io/milestone" }
}
dependencies {
implementation "org.springframework.boot:spring-boot-starter-web:${springBootVersion}"
implementation "org.springframework.boot:spring-boot-starter-data-jpa:${springBootVersion}"
implementation "org.springframework.data:spring-data-jpa:${springJPAVersion}"
implementation "javax.persistence:persistence-api:${javaxVersion}"
implementation "mysql:mysql-connector-java:5.1.43"
testImplementation group: 'junit', name: 'junit', version: '4.11'
}
And gradle creates jar with following structure:
BOOT-INF
classes
META-INF
org
But it seems that the structure must be the following:
BOOT-INF
classes
lib
META-INF
org
with lib folder, which contains dependencies, because now after launch I get error:
Exception ...
Caused by: java.lang.NoClassDefFoundError:
org/springframework/boot/SpringApplication at com.as.reports.Application.main(Application.java:12)
So I know this answer is probably too late to help you, but I stumbled across this question while trying to solve the exact same problem, and was reminded of this.
After half a day of trial and error, I found the solution, so hopefully I can save someone else the pain of finding this unanswered question.
The problem is with using the implementation keyword in your dependencies. The 1.x Spring Boot Gradle plugin doesn't appear recognize that keyword as notating required dependencies for repackaging a fat jar. If you change those back to the older compile keyword, you should get the necessary lib folder.

gradle error Could not find method dependencyManagement()

Below is my build.gradle
buildscript {
ext {
springBootVersion = '2.0.0.M3'
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
apply plugin: 'org.springframework.boot'
apply plugin: 'maven-publish'
dependencyManagement {
imports {
mavenBom 'org.springframework.cloud:spring-cloud-starter-parent:Brixton.SR7'
}
}
dependencies {
compile("org.springframework.cloud:spring-cloud-starter-eureka")
compile "org.elasticsearch:elasticsearch:5.5.0"
testCompile('org.springframework.boot:spring-boot-starter-test')
}
I was using gradle 2.14 and got the below error
> Failed to apply plugin [id 'org.springframework.boot']
> Spring Boot plugin requires Gradle 3.4 or later. The current version is Gra
dle 2.14
Then I upgraded gradle to 3.4 as suggested in the error message.
Now I get the below error
Could not find method dependencyManagement() for arguments [build_79bcact4bkf1
sckkod1j3zl7l$_run_closure1#4a2d71c9] on root project 'myproject'
of type org.gradle.api.Project.
Is the method dependencyManagement() no longer available in gradle 3.4 ?
If anybody is aware of the alternate method to be used in gradle 3.4 , kindly revert
To use this DSL you have to provide the dependency-management-plugin:
buildscript {
repositories {
maven {
jcenter() //or mavenCentral()
}
}
dependencies {
classpath "io.spring.gradle:dependency-management-plugin:1.0.3.RELEASE"
}
}
apply plugin: "io.spring.dependency-management"
Or you can use:
plugins {
id "io.spring.dependency-management" version "1.0.3.RELEASE"
}
More details here.
For me the fix was replacing the distributionUrl in the gradle-wrapper.properties with:
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip
and updating the dependencies in the build.gradle file to:
dependencies { classpath "com.android.tools.build:gradle:7.0.4" }
In Gradle 7 this error is also caused by importing a BOM using:
dependencyManagement {
imports {
mavenBom "tech.jhipster:jhipster-dependencies:${jhipsterDependenciesVersion}"
}
}
In Gradle 7 you need to import your BOM in the following way:
implementation platform("tech.jhipster:jhipster-dependencies:${jhipsterDependenciesVersion}")

Resources