Kotlin Multiplatform share Entities between frontend and backend with contraints on dependencies

Viewed 171

This is an Q&A post that i would like to share. If anyone will propose a better solution - i'll gladly accept an answer.
So - recently I had to refactor old Java Maven multi-project (Spring Boot, Data JPA, MVC, Freemarker, Swing, RMI etc) & decided to split front/back and switch to Gradle / Kotlin / Angular.

  1. First problem I came into was moving from Maven to Gradle and maintain dependency constraints, for example Maven simply use <parent> BOM.
  2. Second was to apply Spring Boot dependencies to Kotlin Multiplatform module.
  3. Third was to create ts module definitions for Entities.
1 Answers

To complete first problem I found one solution - composite build. It means to create within root Gradle project new module that will contain dependency constraints and will be build as plugin, later used in sub-projects. That project must be added to settings.gradle with includeBuild("build-conventions") command. As You can see I named project as "build-conventions" and it has following folder structure :

build-conventions\src\main\Constraints.kt  

import org.gradle.api.Plugin
import org.gradle.api.Project

class Constraints : Plugin<Project> {

    override fun apply(prj: Project) {

        prj.dependencies.constraints {
            prj.configurations.filter { it.name.endsWith("implementation", true) }.forEach {
                add(it.name, "org.springframework.boot:spring-boot-dependencies:2.5.4")
                add(it.name, "MY.SOME:DEPENDENCY:1.3-SNAPSHOT")
                add(it.name, "commons-beanutils:commons-beanutils:1.9.4")
                add(it.name, "commons-io:commons-io:2.11.0")
                add(it.name, "org.imgscalr:imgscalr-lib:4.2")
                add(it.name, "org.glassfish:javax.el:3.0.1-b12")
                add(it.name, "org.lz4:lz4-java:1.6.0")
            }
        }
    }

}

build-conventions\build.gradle.kts

plugins {
    `kotlin-dsl`
}

repositories {
    mavenLocal()
    mavenCentral()
    gradlePluginPortal()
}

gradlePlugin {
    plugins {
        create("My Project Dependency Constraints") {
            id = "dependencies-constraints"
            implementationClass = "Constraints"
        }
    }
}

to maintain plugin versions across project i found the only way to declare:

pluginManagement {
    val kotlinVersion = "1.5.21"
    val springBootVersion = "2.5.4"
    val springBootDependencyVersion = "1.0.11.RELEASE"

    plugins {
        id("org.jetbrains.kotlin.jvm") version kotlinVersion apply false
        id("org.jetbrains.kotlin.multiplatform") version kotlinVersion apply false
        id("org.jetbrains.kotlin.kapt") version kotlinVersion apply false
        id("io.spring.dependency-management") version springBootDependencyVersion apply false
        id("org.springframework.boot") version springBootVersion apply false
        id("biz.lermitage.oga") version "1.1.0" apply false
    }
}

in root settings.gradle

To achieve a second goal i added:

  1. add(it.name, "org.springframework.boot:spring-boot-dependencies:2.5.4") to Constraint.kt dependencies
  2. plugin id("dependencies-constraints") to Kotlin Multiplatform module plugins block
  3. to Kotlin Multiplatform sourceSets
val jvmMain by getting {
        dependencies {
         implementation(project.dependencies.platform("org.springframework.boot:spring-boot-dependencies"))
         implementation("MY.SOME:DEPENDENCY")
         implementation("jakarta.persistence:jakarta.persistence-api")
         implementation("jakarta.annotation:jakarta.annotation-api")
         implementation("jakarta.validation:jakarta.validation-api")
         implementation("org.springframework:spring-context")
         implementation("com.fasterxml.jackson.core:jackson-annotations")
        }
    }

To accomplish third goal i used Gradle plugin for Kotlin Multiplatfom (must be version below or equal to 1.5.21) module id("net.akehurst.kotlin.kt2ts") version "1.6.0" https://github.com/dhakehurst/net.akehurst.kotlin.kt2ts

Related