How to avoid duplication of children repositories in a parent project - gradle

I have a multi-project build with the following structure:
Root project 'just-another-root-project'
+--- Project ':producer'
\--- Project ':consumer'
The root settings.gradle file:
rootProject.name = 'just-another-root-project'
include 'consumer', 'producer'
...connects created modules.
The producer.gradle file:
plugins {
id 'java-library'
}
group 'com.github.yarbshk.jarp'
version '1.0-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
maven {
url 'http://maven.nuiton.org/release/'
}
}
dependencies {
implementation 'com.sun:tools:1.7.0.13'
}
...has an external dependency (com.sun.tools) that is not published in Maven Central therefore I've added a link to the Nuiton repository.
The consumer.gradle file:
plugins {
id 'java'
}
group 'com.github.yarbshk.jarp'
version '1.0-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
annotationProcessor project(':producer')
}
The build described above is not working! To make it so I was enforced to duplicate all repositories from producer.gradle into consumer.gradle. So the question is how to build the root project without the excessive dependency duplication? How to do it in the right way? Thanks for any answer or hint :)
UPDATE 1:
I get the following error when try to build the project with files shown above:
FAILURE: Build failed with an exception.
* What went wrong:
Could not resolve all files for configuration ':consumer:compile'.
> Could not find com.sun:tools:1.7.0.13.
Searched in the following locations:
https://repo.maven.apache.org/maven2/com/sun/tools/1.7.0.13/tools-1.7.0.13.pom
https://repo.maven.apache.org/maven2/com/sun/tools/1.7.0.13/tools-1.7.0.13.jar
Required by:
project :consumer > project :producer

You can configure repositories directly in the root project like that:
root project build.gradle:
// configure repositories for all projects
allprojects {
repositories {
mavenCentral()
maven {
url 'http://maven.nuiton.org/release/'
}
}
}
EDIT (from you comment on other response)
You can also define only mavenCentral() repository on root project level (it will be added to repositories for all projects) and configure http://maven.nuiton.org/release repository only for producer subproject :
root project
repositories {
// will apply to all project
mavenCentral()
}
producer project
repositories {
maven {
url 'http://maven.nuiton.org/release/'
}
// mavenCentral inherited from root project
}
consumer project
// no need to re-define repositories here.

There is a section in an official gradle tutorial dedicated to this:
https://guides.gradle.org/creating-multi-project-builds/#configure_from_above
The root project can configure all projects:
allprojects {
repositories {
jcenter()
}
}

Related

Gradle not resolving mavenLocal() dependency

I have a problem with resolving local dependency. I have a lib that I want to provide across my projects. So I've published it locally. The build.gradle looks like this:
...
plugins {
...
id("maven-publish")
...
}
publishing {
publications {
create<MavenPublication>("maven") {
groupId = "com.wintermute.chatserver.core"
artifactId = "core"
version = "1.0"
from(components["java"])
}
}
}
In the other project, which is requiring the dependency I've added in the build.gradle this:
repositories {
mavenLocal()
mavenCentral()
}
But when I try to resolve the dependencies gradle complains about not resolvable dependency:
Could not resolve com.wintermute.chatserver.core:core:1.0.
Required by:
project :
It was successfull one time, then I've deleted the cache and since this it does not work anymore. Why is that? What I am doing wrong?

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.

Gradle is unable to locate the bintray repository for kotlinx-serialization

I am trying to use kotlinx.serialization and have had just no luck. Here is the pertinent portion of the build.gradle
buildscript {
ext.kotlin_version = '1.3.71'
repositories {
mavenCentral()
google()
jcenter()
maven("https://kotlin.bintray.com/kotlinx")
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
}
}
This dies on the vine:
Could not find method maven() for arguments [https://kotlin.bintray.com/kotlinx]
on repository container of type org.gradle.api.internal.artifacts.dsl.DefaultRepositoryHandler
What is an up-to-date way to incorporate kotlinx-serialization ?
It looks like the actual version for kotlinx.serialization is 1.3.70, not 1.3.71 At least their master branch depends on 1.3.70 kotlin components
The arguments of method maven in org.gradle.api.internal.artifacts.dsl.DefaultRepositoryHandler is Closure,and the context object is type org.gradle.api.artifacts.repositories.MavenArtifactRepository,so the correct script would be like
repositories {
mavenCentral()
maven {
url="https://kotlin.bintray.com/kotlinx"
}
}
what's more,kotlinx.serialization exists in mavencentral,so there is no need to add your custom maven repository

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.

Could not configure Gradle project (Kotlin code)

I am a pretty fresh in Gradle. I'm trying to build up a project Kotlin code with Gradle.
I have spent some time to learn that by following these instructions: https://kotlinlang.org/docs/reference/using-gradle.html
And so far, I have not succeeded in it and got some errors.
My build.gradle is shown below:
group = "kotlin"
version = "1.0-SNAPSHOT"
buildscript {
ext.kotlin_version = '1.2.50'
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
apply plugin: "kotlin"
repositories {
mavenCentral()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
}
And I got the following error
org.gradle.api.internal.artifacts.ivyservice.DefaultLenientConfiguration$ArtifactResolveException: Could not resolve all files for configuration ':classpath'.
....
Caused by: org.gradle.internal.resolve.ModuleVersionResolveException: Could not resolve org.jetbrains.kotlin:kotlin-gradle-plugin:1.2.50.

Resources