20

What does a correct Gradle configuration look like in a multi-module project that uses the Gradle plugins spring-boot-dependencies and spring-boot?

I have the following project setup:

parent
  |
  + build.gradle
  |
  + alpha
  |   |
  |   + build.gradle
  |
  + beta
  |   |
  |   + build.gradle
  • The parent module contains common project configuration.
  • The alpha module is a module in which I would like to import dependencies using versions numbers specified in the spring-boot-dependencies bom, but the result of the is a standard jar.
  • The beta module is a module that depends on alpha and the result is an executable Spring Boot jar file (including all dependencies). Consequently, this project needs both the spring-boot-dependencies as well as the spring-boot plugin.

In order to keep the Gradle files DRY, I have extracted common module scripts to the parent's build.gradle file.

Attempts to execute $ gradle build using the project configuration below results in:

> Plugin with id 'io.spring.dependency-management' not found.

parent gradle.build

allprojects {
    group = "com.example"
    version '0.0.1-SNAPSHOT'

    ext {
        dependencyManagementPluginVersion = '0.5.3.RELEASE'
        springBootVersion = '1.3.0.RC1'
    }

    apply plugin: 'java'
    apply plugin: 'eclipse'
    apply plugin: 'idea'
}

subprojects {
    sourceCompatibility = 1.8
    targetCompatibility = 1.8

    buildscript {
        repositories {
            jcenter()
            maven { url "https://repo.spring.io/snapshot" }
            maven { url "https://repo.spring.io/milestone" }
        }
        dependencies {
            classpath("io.spring.gradle:dependency-management-plugin:${dependencyManagementPluginVersion}")
            classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
        }
    }

    apply plugin: 'io.spring.dependency-management'

    dependencyManagement {
        imports {
            mavenBom("org.springframework.boot:spring-boot-dependencies:${springBootVersion}")
//            mavenBom("org.springframework.boot:spring-boot-starter-parent:${springBootVersion}")
        }
    }
}

alpha build.gradle

dependencies {
    compile('org.springframework:spring-web')
}

beta gradle.build

apply plugin: 'spring-boot'

dependencies {
    compile project(':alpha')
    compile('org.springframework.boot:spring-boot-starter')
    compile('org.springframework.boot:spring-boot-starter-web')
}

Comments:

  • The behavior of the spring-boot plugin was changed in Spring Boot 1.3.0.M1
  • Gradle version: 2.8
  • Spring Boot version 1.3.0.RC1
matsev
  • 32,104
  • 16
  • 121
  • 156
  • If my answer was helpful, please upvote it. – Opal Nov 17 '15 at 06:13
  • 1
    @Opal Sorry about the delay, I thought I had accepted your answer. I have written a [blog post](http://www.jayway.com/2015/11/23/reusing-spring-boots-dependency-management/) regarding the matter, please check the acknowledgements. :-) – matsev Nov 23 '15 at 20:18
  • Thanks, exactly the problem I had --- to help others googling this issue, I will add: If you naively try: apply plugin 'spring-boot' to ALL your subprojects, (only in order to get spring dependency-management for free) you will get build-error (at least I got under windows), like: Execution failed for task ':xxxxx:bootRepackage'. Unable to rename 'xxxxx.jar' to 'xxxxx.jar.original' – Rop Mar 03 '16 at 18:29
  • @matsev, have just noticed info about the article - looks good. Thanks for being mentioned! – Opal Mar 18 '16 at 12:33

1 Answers1

22

It turns out that parent/build.gradle should be rearranged in the following way:

buildscript {
    ext {
        dependencyManagementPluginVersion = '0.5.3.RELEASE'
        springBootVersion = '1.3.0.RC1'
    }
    repositories {
        jcenter()
        maven { url "https://repo.spring.io/snapshot" }
        maven { url "https://repo.spring.io/milestone" }
    }
    dependencies {
        classpath("io.spring.gradle:dependency-management-plugin:${dependencyManagementPluginVersion}")
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    }
}

allprojects {
    group = "com.example"
    version '0.0.1-SNAPSHOT'

    apply plugin: 'java'
    apply plugin: 'eclipse'
    apply plugin: 'idea'
}

subprojects {
    sourceCompatibility = 1.8
    targetCompatibility = 1.8

    apply plugin: 'io.spring.dependency-management'

    dependencyManagement {
        imports {
            mavenBom("org.springframework.boot:spring-boot-dependencies:${springBootVersion}")
//          mavenBom("org.springframework.boot:spring-boot-starter-parent:${springBootVersion}")
        }
    }
}

The problem lies in the fact that buildscript block for subprojects was indeed configured well but... in a wrong place. This subprojects block relates to subprojects but it will be evaluated in the script it was declared, and there were no dependencies declared for the plugin it was trying to apply.

Opal
  • 81,889
  • 28
  • 189
  • 210
  • 1
    Thanks, but it does not quite work. Now Gradle fails to find repositories for the submodules: `> Cannot resolve external dependency org.springframework.boot:spring-boot-dependencies:1.3.0.RC1 because no repositories are defined. Required by: com.example:alpha:0.0.1-SNAPSHOT` Copying `repositories` to the `allprojects` solves the problem, but is there a way to define `repositories` _once_ so that it is accessible from both `buildscript` and `allprojects`? – matsev Nov 15 '15 at 00:10
  • No :/ Unfortunately, these are separate configurations. It needs to be duplicated. – Opal Nov 15 '15 at 06:52
  • FYI, `buildscript` applies to the `build.gradle`, not to any particular project in it, so what you found isn't surprising. But your answer doesn't do the same thing as shown in your question; the root project doesn't have `dependencyManagement` anymore. – Abhijit Sarkar Nov 28 '18 at 19:24