DEV Community

All Things Dev
All Things Dev

Posted on

1

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

Heroku

This site is built on Heroku

Join the ranks of developers at Salesforce, Airbase, DEV, and more who deploy their mission critical applications on Heroku. Sign up today and launch your first app!

Get Started

Top comments (0)

Sentry mobile image

Mobile Vitals: A first step to Faster Apps

Slow startup times, UI hangs, and frozen frames frustrate users—but they’re also fixable. Mobile Vitals help you measure and understand these performance issues so you can optimize your app’s speed and responsiveness. Learn how to use them to reduce friction and improve user experience.

Read the guide

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay