Skip to content

Dependency Management ​

Overview ​

ArchForge uses two mechanisms to manage dependency versions, achieving functionality similar to Maven's dependencyManagement:

  1. Spring Boot BOM -- manages versions for all Spring Boot ecosystem dependencies
  2. Custom BOM (archforge-dependencies module) -- manages versions for third-party libraries

With these two BOMs (Bill of Materials), submodules declare dependencies without specifying version numbers.

How It Works ​

Spring Boot BOM ​

The root build.gradle.kts imports the Spring Boot BOM so that all Spring-managed library versions are resolved automatically:

kotlin
dependencies {
    // Spring Boot BOM for dependency version management
    add("implementation", platform("org.springframework.boot:spring-boot-dependencies:4.1.0"))

    // JUnit BOM
    add("testImplementation", platform("org.junit:junit-bom:6.0.3"))
}

Custom BOM (java-platform) ​

The archforge-dependencies/build.gradle.kts module uses Gradle's java-platform plugin to define version constraints for every third-party library used in the project:

kotlin
plugins {
    `java-platform`
}

dependencies {
    constraints {
        api("com.baomidou:dynamic-datasource-spring-boot4-starter:4.5.0")
        api("cn.dev33:sa-token-spring-boot3-starter:1.45.0")
        api("org.flywaydb:flyway-core:12.4.0")
        api("com.google.guava:guava:33.6.0-jre")
        api("commons-io:commons-io:2.19.0")
        api("org.apache.commons:commons-lang3:3.20.0")
        api("org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.11")
        api("org.mapstruct:mapstruct:1.6.3")
        api("org.testcontainers:testcontainers:2.0.4")
        // ... all versions in one place
    }
}

Root Project Wiring ​

The root build.gradle.kts applies both BOMs to every subproject (except the archforge-dependencies module itself):

kotlin
subprojects {
    if (name != "archforge-dependencies") {
        apply(plugin = "java-library")

        dependencies {
            // Spring Boot BOM
            add("implementation", platform("org.springframework.boot:spring-boot-dependencies:4.1.0"))

            // Custom BOM
            add("implementation", platform(project(":archforge-dependencies")))
        }
    }
}

Usage in Submodules ​

With both BOMs applied, submodules declare dependencies without version numbers:

kotlin
// archforge-domain/archforge-admin-user/build.gradle.kts
dependencies {
    // Spring Boot starters (version from Spring Boot BOM)
    implementation("org.springframework.boot:spring-boot-starter-web")
    implementation("org.springframework.boot:spring-boot-starter-data-jpa")
    implementation("org.springframework.boot:spring-boot-starter-aop")
    implementation("org.springframework.boot:spring-boot-starter-actuator")

    // Third-party libraries (version from custom BOM)
    implementation("com.google.guava:guava")
    implementation("org.apache.commons:commons-lang3")
    implementation("org.springdoc:springdoc-openapi-starter-webmvc-ui")

    // Lombok (version from Spring Boot BOM)
    compileOnly("org.projectlombok:lombok")
    annotationProcessor("org.projectlombok:lombok")

    // Test dependencies (version from JUnit BOM + custom BOM)
    testImplementation("org.junit.jupiter:junit-jupiter-api")
    testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")
    testImplementation("org.testcontainers:testcontainers")
}

Adding a New Dependency ​

Spring Boot Ecosystem ​

If the dependency is part of the Spring Boot ecosystem, simply add it without a version -- the Spring Boot BOM resolves it:

kotlin
dependencies {
    implementation("cn.dev33:sa-token-spring-boot3-starter")
}

Third-Party Library ​

For non-Spring-Boot dependencies, first add a version constraint to archforge-dependencies/build.gradle.kts:

kotlin
dependencies {
    constraints {
        api("org.example:example-library:1.0.0")
    }
}

Then reference it in any submodule without a version:

kotlin
dependencies {
    implementation("org.example:example-library")
}

Benefits ​

  1. Centralized version control -- all dependency versions live in one or two places, making upgrades straightforward
  2. Clean submodule declarations -- no version numbers scattered across dozens of build.gradle.kts files
  3. No version conflicts -- the BOM guarantees consistent versions across the entire project
  4. Easy maintenance -- upgrading a library requires a single-line change in the platform module

Released under the MIT License.