How to share common Pojos between Javaserver and new Pure Kotlin/Js Multiplattform

I tried out 100% Kotlin Frontend and Backend project demo using Kotlin Multiplattform → Fullstack Web Application. It is nice to see how common code is shared.
But how can I share common pojo between the mulitplattform project and in another non-kotlin project (a java only server)?

I have created a WebApp/Javascript only project (Multiplattform) and tried using it as dependency in the server using api(project(“:company.webapp”).
But when trying to create new Pojo class and assigning a kotlinx.datetime.LocalDateTIme, Intellj complains with this error:


gradle clean build, and Project rebuild do not complain -

  • What is the recommended way sharing Pojos between Javaserver and Kotlin/Javascript?
  • I tried using project company.webapp as dependency in company.server to use somehow the kotlin pojo classes in the server:
    company.server:
GreetingController.java:

        WsResultMessage2 wsResultMessage2 = new WsResultMessage2();
        wsResultMessage2.setName("asds");
        wsResultMessage2.setText("asa");

        kotlinx.datetime.LocalDateTime sa = new kotlinx.datetime.LocalDateTime(2022, 12, 2, 12,23,3,2);

        wsResultMessage2.setTime(sa); //Works in gradle clean build and Rebuild project, but in Editor error highlighting "Required type: kotlinx.datetime.LocalDateTime Provided: kotlinx.datetime.LocalDateTime"


pure Java17 company.server build file:
 api project(':company.webapp')

company.webapp commonMain:
import kotlinx.datetime.LocalDateTime

 open class WsResultMessage2 {
    var time: LocalDateTime? = null
    var name: String? = null
    var text: String? = null

    fun getSpecialTime(): LocalDateTime? {
        return time;
    }
}

company.webapp build.gradle.kts:
plugins {
    kotlin("multiplatform") version "1.9.0-RC"
    kotlin("plugin.serialization") version "1.9.0-RC"
}

tasks
    .withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask<*>>()
    .configureEach {
        compilerOptions.apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9)
        compilerOptions.languageVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9)
        compilerOptions.suppressWarnings.set(false)
        compilerOptions.verbose.set(true)
    }

kotlin {
    jvm {
        compilations.all {
            kotlinOptions.jvmTarget = "17"
        }
        withJava()
        testRuns["test"].executionTask.configure {
            useJUnitPlatform()
        }
    }
    js {
        browser {
            runTask {
                outputFileName = "app.js"
            }
            webpackTask {
                outputFileName = "app.js"
            }
            testTask {
                enabled = true
                useKarma {
                    useChromiumHeadless()
                    useFirefox()
                }
            }
        }
        binaries.executable()
    }
    sourceSets {

        val commonMain by getting {
            dependencies {
               // api(project(":company.server.api"))
                api("org.jetbrains.kotlinx:kotlinx-datetime:0.4.0")
            }
        }
        val commonTest by getting {
            dependencies {
                implementation(kotlin("test"))
            }
        }
        val jsMain by getting {
            dependencies {

                implementation("io.ktor:ktor-client-core:2.3.1")
                implementation("io.ktor:ktor-client-js:2.3.1")
                implementation("io.ktor:ktor-client-websockets:2.3.1")

                implementation("io.ktor:ktor-client-content-negotiation:2.3.1")
                implementation("io.ktor:ktor-serialization-kotlinx-json:2.3.1")
                implementation("org.jetbrains.kotlinx:kotlinx-html:0.8.0")


            }
        }
        val jsTest by getting {
            dependencies {
                implementation(kotlin("test-js"))
            }
        }
        val jvmMain by getting {
            dependencies {
             //   api("org.jetbrains.kotlinx:kotlinx-datetime:0.4.0")
            }
        }
    }
}

What you did in the last code sample is more or less correct way. You need a multiplatform project targeting both JVM and JS. You put your POJO as a common code, then in your Java project you use the JVM artifact.

Why the kotlinx-datetime dependency is commented out for jvmMain?

edit:
Although, I believe it should be enough to put it in commonMain only.

  1. " Why the kotlinx-datetime dependency is commented out for jvmMain?"
    I was trying to get rid of the IDE error highlighting, do you have any suggestions?
    When I have pure Kotlin server/backend, there is no such IDE cerror.
    IDE version is “Build #IU-231.9161.38, built on June 20, 2023”
    Tried already clearing the cache, deleteing .idea folder, reimporting the gradle project…

  2. Is it possible only to target JS as it will be a pure 100% Webapp project and then share somehow its commonMain Pojo classes for the Javaserver?
    In our company this is will be a typical migration path for manay java servers:
    Migrating the GUI, but keeping the Spring Boot Java Server with common Pojo classes.

Thanks!

I’m not an expert in multiplatform projects, but as far as I know: no, you have to target JVM. Common code can’t be shared with a regular Java project (or even Kotlin), because it is not compiled to any specific target.

Also, even by looking at it conceptually: how is it a “pure 100% Webapp” if it provides data structures for the backend? If you don’t want to “spoil” your webapp with backend code, then maybe you should create an entirely separate project for your model (multiplatform: jvm + js), then use it in both your webapp (which doesn’t have to be multiplatform anymore) and in the java service?