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
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()
}
}
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")
}
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`
}
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 {
// ..
}
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")
}
Conclusion
A project can have multiple convention configurations. Multiple sub-modules in a project can also import one or more such configurations.
Source Code
Keep in Touch
Please follow me on Twitter where I regularly share my experiences with useful tools and frameworks.
Top comments (0)