Gradle creates circular dependency for runtime dependency - gradle

I have a mutli module gradle project:
subprojects {
apply plugin: 'java-library'
}
project(':core') {
dependencies {
compile project(':module:mod-a')
}
}
project(':module:mod-a') {
dependencies {
compile project(':core')
}
}
project(':module:mod-b') {
dependencies {
compile project(':core')
}
}
Of course this causes a circular compile dependency:
* What went wrong:
Circular dependency between the following tasks:
:core:compileJava
+--- :core:compileJava (*)
\--- :module:mod-a:compileJava
+--- :core:compileJava (*)
\--- :module:mod-a:compileJava (*)
What bothers me is that even if I change the compile dependency from :core to :module:mod-a to a runtime dependency it still is not possible to compile the project:
* What went wrong:
Circular dependency between the following tasks:
:module:mod-a:compileJava
\--- :module:mod-a:compileJava (*)
I don't see why there is a problem. The :core does need the module only at runtime and therefore can be compiled first. Afterwards the modules can be compiled using the core. Furthermore the :core is not part of the error message from Gradle anymore. So Gradle seems to "see" that it is just a runtime dependency.
Where is the problem and how can it be fixed?

Using runtimeOnly instead of runtime seems to solve the problem.

When you do
dependencies {
runtime project(':xxx')
}
It's the same as
dependencies {
runtime project(path: ':xxx', configuration: 'default')
}
See here which states that the default configuration extends runtime.
So by doing this you are making :module:mod-a depend on the runtime configuration from :core. Hence the curcular dependency
You could probably reference the archives configuration instead of default to break the cycle
eg:
subprojects {
apply plugin: 'java'
}
project(':core') {
artifacts {
archives jar
}
}
project(':module:mod-a') {
dependencies {
compile project(path: ':core', configuration: 'archives')
compile project(path: ':core', configuration: 'runtime')
}
}

Related

Gradle implementation project throws exception

I have this hierarchy to my project:
- project
- project-server
- build.gradle
- gradle.properties
- settings.gradle
- project-client
- build.gradle
- gradle.properties
- settings.gradle
- build.gradle
- gradle.properties
- settings.gradle
In the parent build.gradle file I added these lines:
project(':project-client') {
dependencies {
implementation project(':project-server')
}
}
and I am getting:
What went wrong: A problem occurred evaluating root project 'project'.
Could not find method implementation() for arguments [project ':project-client'] on object of type
org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler.
This is my entire build.gradle:
apply plugin: 'java'
println(subprojects.each {it -> it.name})
project(':project-client') {
dependencies {
implementation project(':project-server')
}
}
allprojects {
group = 'com.test'
repositories {
mavenLocal()
maven {
//local nexus config
}
mavenCentral()
jcenter()
}
}
subprojects {
version = {version}
}
This is the setting.gradle:
rootProject.name = 'project'
include 'project-server', 'project-client'
Please help, thanks in advance.
implementation configuration is added by the java plugin.
You've applied java plugin only for the root project, in the provided build.gradle. Your :project-client subproject does not inherit plugins from it's parent (root), so the java plugin was not applied to :project-client project.
That's why it "could not find method implementation() for arguments...". Make sure to apply java plugin to subprojects.

How to upgrade existing Micronaut application to new Micronaut version 1.1.2?

I have been upgrading like this..
plugins {
id "io.spring.dependency-management" version "1.0.6.RELEASE"
id "com.github.johnrengelman.shadow" version "4.0.2"
}
apply plugin:"application"
apply plugin:"groovy"
version "0.1"
group "com.shanky"
repositories {
mavenLocal()
mavenCentral()
maven { url "https://jcenter.bintray.com" }
}
dependencyManagement {
imports {
mavenBom 'io.micronaut:micronaut-bom:1.1.2'
}
}
dependencies {
compile "io.micronaut:micronaut-runtime-groovy"
compile "io.micronaut:micronaut-validation"
compile "io.micronaut:micronaut-http-client"
compile "io.micronaut:micronaut-http-server-netty"
compileOnly "io.micronaut:micronaut-inject-groovy"
runtime "ch.qos.logback:logback-classic:1.2.3"
testCompile "io.micronaut:micronaut-inject-groovy"
testCompile("org.spockframework:spock-core") {
exclude group: "org.codehaus.groovy", module: "groovy-all"
}
compile 'io.micronaut:micronaut-views'
runtime 'org.thymeleaf:thymeleaf:3.0.11.RELEASE'
compile "io.micronaut.configuration:micronaut-hibernate-validator"
compile "io.micronaut.configuration:micronaut-hibernate-gorm"
runtime 'org.postgresql:postgresql:42.2.5'
annotationProcessor "io.micronaut:micronaut-security"
compile "io.micronaut:micronaut-security"
compile "io.micronaut:micronaut-security-session"
runtime "org.hibernate:hibernate-ehcache:5.1.9.Final"
}
shadowJar {
mergeServiceFiles()
}
run.jvmArgs('-noverify', '-XX:TieredStopAtLevel=1')
mainClassName = "com.shanky.Application"
tasks.withType(GroovyCompile) {
groovyOptions.forkOptions.jvmArgs.add('-Dgroovy.parameters=true')
}
So far this is my build.gradle file. I have updated mavenBom to upgrade Micronaut version. I've create a dummy project with Micronaut version 1.1.2 just to differentiate build.gradle file. I don't see any major difference in between them.
Any help would be appreciated
But it is not upgrading.
That is unlikely to be correct. It may be that you aren't seeing the effect of that change in your IDE if the IDE is out of sync with your Gradle build but changing that version number in build.gradle does in fact upgrade the project.

Gradle plugin that loads org.springframework.boot into projects

I'm writing a custom gradle plugin Foo and I want to load the org.springframework.boot plugin
into projects that apply the Foo plugin. I can load various other plugins this way, but this
particular plugin doesn't want to behave the same way.
Foo build.gradle
buildscript {
ext {
springBootVersion = "2.1.3.RELEASE"
}
}
apply plugin: "groovy"
repositories {
maven { url "http://custom.repo/blah" }
}
dependencies {
implementation gradleApi()
implementation localGroovy()
implementation("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
Foo plugin
class BuildPlugin implements Plugin<Project> {
#Override
void apply(Project project) {
project.repositories {
maven { url "http://custom.repo/blah" }
}
project.plugins.apply("org.springframework.boot")
}
}
Project build.gradle
buildscript {
dependencies {
classpath files("/some/cool/path/foo-plugin.jar")
}
}
apply plugin: "com.whatever.foo-id"
Project build output
$ ./gradlew --stacktrace clean build
FAILURE: Build failed with an exception.
* Where:
Build file '/cool/project/location/bar/build.gradle' line: 40
* What went wrong:
A problem occurred evaluating root project 'bar'.
> Failed to apply plugin [id 'com.whatever.foo-id']
> Plugin with id 'org.springframework.boot' not found.
Is it possible to apply a plugin 1 from plugin 2 where plugin 1 is a classpath dependency?
This isn't possible. The classpath is what pulls in the plugins, so it is impossible for them to modify the thing before they are pulled in.

How can I add dependencies to kotlinCompilerClasspath?

I am using the kotlin-gradle-plugin, configuring it as follows in build.gradle:
buildscript {
ext {
springBootVersion = '2.1.2.RELEASE'
kotlinVersion = '1.3.11'
}
repositories {
mavenLocal()
mavenCentral()
maven { url "http://repo.spring.io/plugins-release" }
maven { url "https://plugins.gradle.org/m2/" }
}
dependencies {
classpath "org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlinVersion}"
classpath "org.jetbrains.kotlin:kotlin-allopen:${kotlinVersion}"
}
apply plugin: 'kotlin'
apply plugin: 'kotlin-spring'
When I run gradle dependencies I get the following kotlinCompilerClasspath among other things:
kotlinCompilerClasspath
\--- org.jetbrains.kotlin:kotlin-compiler-embeddable:1.3.11
+--- org.jetbrains.kotlin:kotlin-stdlib:1.3.11
| +--- org.jetbrains.kotlin:kotlin-stdlib-common:1.3.11
| \--- org.jetbrains:annotations:13.0
+--- org.jetbrains.kotlin:kotlin-script-runtime:1.3.11
\--- org.jetbrains.kotlin:kotlin-reflect:1.3.11
\--- org.jetbrains.kotlin:kotlin-stdlib:1.3.11 (*)
When I disabled transitive dependencies in my build.gradle as follows:
configurations {
all {
transitive = false
resolutionStrategy {
// fail eagerly on version conflict (includes transitive dependencies)
// e.g. multiple different versions of the same dependency (group and name are equal)
failOnVersionConflict()
}
}
}
Now when I run gradle dependencies I get the following kotlinCompilerClasspath
kotlinCompilerClasspath
\--- org.jetbrains.kotlin:kotlin-compiler-embeddable:1.3.11
How can I add dependencies to the above kotlinCompilerClasspath while still using transitive = false configuration?
For example, I have tried adding the dependency org.jetbrains.kotlin:kotlin-stdlib to the regular dependencies block and to the buildscript block but still the above kotlinCompilerClasspath does not change.
Gradle version
gradle --version
------------------------------------------------------------
Gradle 5.1.1
------------------------------------------------------------
Build time: 2019-01-10 23:05:02 UTC
Revision: 3c9abb645fb83932c44e8610642393ad62116807
Kotlin DSL: 1.1.1
Kotlin: 1.3.11
Groovy: 2.5.4
Ant: Apache Ant(TM) version 1.9.13 compiled on July 10 2018
JVM: 1.8.0_191 (Oracle Corporation 25.191-b12)
OS: Mac OS X 10.14.2 x86_64
UPDATE
As recommended by hotkey below, I filtered out kotlin from the configuration, as follows.
configurations {
matching { !it.name.toLowerCase().contains('kotlin') }.all {
transitive = false
resolutionStrategy {
// fail eagerly on version conflict (includes transitive dependencies)
// e.g. multiple different versions of the same dependency (group and name are equal)
failOnVersionConflict()
}
}
}
I would recommend not to disable transitive dependencies for the kotlinCompilerClasspath configuration in the first place, the Kotlin Gradle plugin expects that configuration to pull the transitive dependencies of the Kotlin compiler as well:
configurations {
matching { it.name != 'kotlinCompilerClasspath' }.all {
transitive = false
/* ... */
}
}
If you still want to disable transitive dependencies for all configurations, you can instead manually add those dependencies which were reported as transitive for the kotlin-compiler-embeddable module:
dependencies {
kotlinCompilerClasspath 'org.jetbrains.kotlin:kotlin-stdlib'
kotlinCompilerClasspath 'org.jetbrains.kotlin:kotlin-script-runtime'
kotlinCompilerClasspath 'org.jetbrains.kotlin:kotlin-reflect'
kotlinCompilerClasspath 'org.jetbrains:annotations:13.0'
}

Create external dependencies and add it to other project with gradle

I have two spring boot projet
A and B
would like to create a new projet to put common thing there
A
B
commons
how to add commons to A and B like a external dependencies?
Assume your project layout as below:
project
|- common
|- proja
|- projb
you need settings.gradle
rootProject.name = 'project'
include 'common'
include 'proja'
include 'projb'
then you need to update your build.gradle under project like this:
plugins {
id 'org.springframework.boot' version '1.5.4.RELEASE'
}
subprojects { // common configurations for all subprojects
apply plugin: 'groovy'
apply plugin: 'org.springframework.boot'
repositories {
jcenter()
}
dependencies { // common dependencies for all subprojects
compile 'org.codehaus.groovy:groovy-all:2.4.10'
testCompile 'org.springframework.boot:spring-boot-starter-test'
testCompile 'org.spockframework:spock-spring:1.0-groovy-2.4'
}
}
project ("proja") {
dependencies { // proja-specific dependencies
compile 'com.google.guava:guava:21.0'
compile project(":common")
}
}
project ("projb") {
dependencies { // projb-specific dependencies
compile project(":common")
}
}
Let me know if this works.
external solution seem the way to go
my commons build.gradle file
apply plugin: 'java-library-distribution'
repositories {
mavenCentral()
maven { url "https://repo.spring.io/snapshot" }
maven { url "https://repo.spring.io/milestone" }
}
dependencies {
compile group: 'org.springframework.boot', name: 'spring-boot-starter-data-jpa', version: '2.0.0.M2'
}
distributions {
main{
baseName = 'commons-code'
}
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
tasks.withType(JavaCompile) {
options.compilerArgs = ["-Xlint:unchecked", "-Xlint:deprecation", "-parameters"]
}
In my main project
i have an build.gradle
in the dependencies section i have
compile project (':commons-code')
and in the settings.gradle file i have
include ":commons-code"
project(":commons-code").projectDir = file("/home/bob/dev/project/commons/")

Resources