DEV Community

All Things Dev
All Things Dev

Posted on

Spring Boot Multi-Module Project with Gradle Convention Plugin

Hi Everyone,
I have been working with Java and Maven for over a decade. Recently, I started migrating many of my projects to Kotlin and Gradle. Most of these projects are multi-module projects with single parent pom.xml for dependency management.

During my research I learned that Gradle provides similar organization of modules with convention plugin. However, there seems to be no direct guide or reference to create a working Spring Boot multi-module project with Gradle convention plugin configuration. The references that I found were pretty useful in demonstrating the core concepts but nothing which could be directly applicable to our use case. This is the reason I decided to write this article.

Project Structure

<PROJECT-ROOT>
|   settings.gradle.kts
|                       
+---buildSrc
|   |   build.gradle.kts
|   |   settings.gradle.kts
|   \---src
|       \---main
|           \---kotlin
|                   dev.all_things.reference.spring-boot-parent.gradle.kts
|                   
\---web-app
    |   build.gradle.kts
    |   
    \---src
        \---main
            +---kotlin
            |   \---config
            |           Application.kt
Enter fullscreen mode Exit fullscreen mode

Convention Plugin Configuration

It refers to a build configuration file which defines set of plugins, dependencies and compiler settings. Each file is a Gradle script with gradle.kts extension. Gradle will expose each configuration as a plugin with file name as identity e.g. dev.all_things.reference.spring-boot-parent.

buildSrc is a special directory where all convention plugin configurations reside. This directory is nothing but a standalone Gradle project with its own independent dependency and repository configuration.

Like any standard Gradle project buildSrc/settings.gradle.kts specifies repositories required for downloading plugings and dependencies.

// Global plugin management
pluginManagement {
    // Project level repositories for plugins
    repositories {

        // Google mirror of Maven Central for optimized performance
        google()

        // Maven Central (primary) plugin repository
        mavenCentral()

        // Gradle plugin repository
        gradlePluginPortal()
    }
}

// Global dependency management
dependencyResolutionManagement {
    /**
     * Project level repositories for dependencies.
     *
     * Gradle uses its own repository by default.
     * Maven repository needs to be explicitly configured.
     */
    repositories {

        // Google mirror of Maven Central for optimized performance
        google()

        // Maven Central (primary) artifact repository
        mavenCentral()
    }
}
Enter fullscreen mode Exit fullscreen mode

buildSrc/build.gradle.kts specifies common dependencies (and corresponding versions) required by the sub-modules.

description = "kotlin-application-parent"

// Convention plugin configuration
plugins {
    // Enables convention definitions in src/main/kotlin
    `kotlin-dsl`
}

// 'buildSrc' specific dependencies
dependencies {

    // Kotlin
    implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.10")
    implementation("org.jetbrains.kotlin:kotlin-allopen:1.9.10")

    // Spring Boot
    implementation("org.springframework.boot:spring-boot-gradle-plugin:3.1.3")
}
Enter fullscreen mode Exit fullscreen mode

Notice that kotlin-dsl is configured as a plugin. This enables Kotlin DSL for creating reusable build configurations.

// Convention plugin configuration
plugins {
    // Enables convention definitions in src/main/kotlin
    `kotlin-dsl`
}
Enter fullscreen mode Exit fullscreen mode

dev.all_things.reference.spring-boot-parent.gradle.kts specifies the actual build configuration that sub-modules can reuse. This file supports all configurations as a standard build.gradle.kts.

// Plugins common for sub-modules
plugins {

    // Spring Boot plugin configuration
    id("org.springframework.boot")

    // Spring Boot dependency management configuration
    id("io.spring.dependency-management")

    // Kotlin compiler plugin for JVM
    kotlin("jvm")

    // Kotlin plugin for Spring
    kotlin("plugin.spring")
}

group = "dev.all_things.reference"
version = "1.0.0-SNAPSHOT"

// Enabled by 'Kotlin' plugin
kotlin {

    // JDK specific toolchain configuration
    jvmToolchain(20)

}

// Dependencies common for sub-modules
dependencies {

    // ..
}
Enter fullscreen mode Exit fullscreen mode

Module Configuration

Now that convention configuration is ready, it can be imported by sub-modules using generated plugin id i.e. dev.all_things.reference.spring-boot-parent in their build.gradle.kts.

plugins {

    // Other module specific plugins
    // ...

    // Spring Boot parent configuration for dependency management
    id("dev.all_things.reference.spring-boot-parent")
}
Enter fullscreen mode Exit fullscreen mode

Conclusion

A project can have multiple convention configurations. Multiple sub-modules in a project can also import one or more such configurations.

Source Code

GitHub Project

Keep in Touch

Please follow me on Twitter where I regularly share my experiences with useful tools and frameworks.

References

  1. https://www.youtube.com/watch?v=So0j4RnoKkU
  2. https://www.youtube.com/watch?v=iu_Tftpm6L8
  3. https://www.youtube.com/watch?v=1hjle_eqEsw

Top comments (0)