Fullstack Kotlin with Maven?

Hello, everybody.

I’d like to get my team to use Kotlin Multiplatform as we could share a lot of code, but I’ve encountered some obstacles myself that make it impossible to work with it effectively at the moment.
I would be grateful for a little discussion about possible best practices and caveats with our current setup!


We currently use a JVM-backend, which serves as an HTTP server, similar to Ktor. The frontend is a simple vue-app written in Typescript.

Contrary to the examples and Gradle templates, these are not two projects:
Our bundled fullstack app is one fat JAR.
How would you structure your Maven project, then?
The current setup is as follows:

/project
-shared
-frontend
|- pom.xml
|- package.json
-backend
|- src
|- resources (we want our frontend here!)
-assemble

The “assemble” module will build the frontend and put it inside the backend/resources folder (as we cannot do this inside the root module).
This kinda works, but it’s not as smooth as Gradle:

  • How would you handle auto/hot-reload? File watchers with “compile-on-save” are quite cumbersome.
  • Where do you declare frontend dependencies, inside the package.json or in the pom.xml?
    Both options exclude some features; a dependency inside package.json will not be detected by Kotlin, a dependency inside pom.xml will not put the package inside node_modules. One solution would be to declare it in both, but why the redundancy?
    Nevertheless, I was not able to import the kotlinx.html package as the browser was complaining about missing scripts. Is it necessary to declare the dependency in the index.html as well?

The current workflow with Kotlin Multiplatform and Maven is extremely confusing and not as flexible and smooth as I’d like. But maybe I’m just missing something. :slight_smile:

1 Like

Kotlin MPP only supports Gradle: https://kotlinlang.org/docs/reference/building-mpp-with-gradle.html. We don’t plan to add Maven support currently.

Is there a rough time plan for Maven support yet? I would like to try Kotlin MPP, but I would need to invest time into learning Gradle just for that. I wonder whether I should rather bite the bullet or just wait for Maven support.

Maybe I missed some annoucement but I don’t think they really consider adding maven support. At least not before MPP get’s a full stable release. So unless you want to wait a year or more you should just learn a bit of gradle.

The model of a multiplatform project is too complex to even consider declare it in XML. Also many tasks are project specific and requires a level of flexibility that Maven just can’t offer. Asking such a question means that probably you do not know Gradle at all and mistakenly thought it is similar to Maven!

Give Gradle a shot. It will be hard at first, but after some time you’ll never go back to Maven.

@marcoeckstein I know the switch from Maven to learning Gradle can sometimes feel rough but it’s worth it. Learning how Gradle works will likely improve your knowledge of Maven and build tools in general which is nice :slight_smile:

I enjoyed the Kotlin hands-on for Introduction to Multiplatform. It goes through adding each step of Gradle code and explains why while creating the tutorial project. Really gives you a nice step-by-step intro and there are several other multiplatform hands-on tutorials.

If those tutorials are too much of a jump to get started with Gradle, the Gradle docs are nice. Doing a basic project created by the Gradle CLI can be helpful to learn the basics. After that, IntelliJ has support just like Maven so you can discover new features through the GUI as you update your build script.

I tried both Maven and Gradle with Kotlin scripts. I’m disagree with comments here, Maven provide a standard highly parseable and well supported configs. Gradle provide possibility to program in your build system which is makes mess. Just as confirm I see how IntelliJ IDEA struggling in parsing such scripts to provide for example highlight for dependencies that have updates.

So having Maven support - will be a big plus. I believe if you need to pre-compile something you can create plugin for it in Maven.

3 Likes

Still, it would be interesting to state more precisely the maven limitations in this context, and why a multiplatform build cannot be performed using dedicated maven plugins. Is it the directory structure and the lifecycle of the common sources? The calculation of the classpath? etc.

1 Like

I don’t think they’ll ever add Maven support for MPP.

Whilst I agree with the previous comments that Mavens POM files just aren’t suitable at all for such a complex build model, that isn’t the biggest issue.

The biggest issue is publishing. MPP libraries use Gradle Feature variants which use Gradle Module metadata. This is crucial as it outsources the selection of the correct platform variant to Gradle and not to the kotlin plugin.

To my awareness Maven doesn’t have a replacement for this, your supposed to include project metadata in the published pom.xml (which just can’t be done for the extensive amount of metadata needed by MPP?) and obviously Maven doesn’t understand Gradle Module Metadata, which means that maven projects already need to depend on the -jvm artifact

So I highly doubt that there will ever be Maven support for MPP

I fully agree with you. The main proplems of Maven are:

  • Verbose xml syntax
  • Lack of support from JetBrains :frowning:

Gradle is terrible monster designed the wrong way from top to bottom. It violates SOLID principle in many aspects and turns projects into mess. And graddle documentation is bad. At first look it seems full of information, but in reality it is rather like tiresome PhD theisis, which tries to impress the reader by its verbosity.

It is pitty JB invested so much time it developing kotlin plugins on graddle platform and seem to be continuing investing in this messy swamp, because new JB’s build tool Amper is based on graddle.

I trust JB should have chosen Maven and perhaps invested some of their resources in fixing maven’s main problem, xml syntax, that would provide much more value both to them and kotlin community.

1 Like

Just an illustration:

But why I can use in any other place but in plugins???

And this illogical weird nonsense happens at every step with graddle :rage:

1 Like

Glad to see that people hear what I’m trying to say with cold mind and move away hype component.

I think JB was follow hype driven development.
Now depending on the money situation of JB as company, they may have a chance to follow right path:
Drop investment in gradle with kotlin scripts, drop investment in Amper. Invest in Maven and create stable pipeline to build projects.

@schlaubi I like that you go more specific about issue. I’m not in context of limits that maven have about metadata. But as for me they can do plugin and that plugin may use metadata.xm/yaml/json that placed near pom.xml and we can put whatever metadata needed in that file. From my perspective this is ok approach. Especially if IDE can nicely parse/process it.

As of compilation variants and selecting dependencies, I believe we can handle this by providing different dependencies using maven profiles.

Because the plugins block is compiled seperately than the rest of the buildscript
The gradle script compiler works like this:

  1. Find plugins and buildscript block and compile it
  2. Use content of those to download and apply specified plugins
  3. Generate type safe accessors for items generated by those plugins (tasks, extensions, dependency configurations etc.)
  4. Compile the rest of the buildscript

Therefore you cannot use anything defined outside plugins from within plugins

This issue can be resolved using Gradle Version Catalogs

You can create a file gralde/libs.versions.toml

[versions]
kotlin = "1.9.22"

[plugins]
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }

And then reference it like this

plugins {
  alias(libs.plugins.kotlin.jvm)

I think JB was follow hype driven development.

The reason they use gradle is, that at a developers conference (I don’t remember which one) Gradle and JetBrains were booth neighbours, they talked about their ideas and figured it would be great, and I agree

I like that you go more specific about issue. I’m not in context of limits that maven have about metadata. But as for me they can do plugin and that plugin may use metadata.xm/yaml/json that placed near pom.xml and we can put whatever metadata needed in that file. From my perspective this is ok approach. Especially if IDE can nicely parse/process it.

And that’s precisly the problem, they need to make a plugin, whereas with gradle they don’t, with Gradle every other gradle project, no matter whether it uses java, groovy, scala or any other language supported by Gradle, Gradle will automatically be able to pick the correct artifact, which Maven won’t ever be able to do, because it doesn’t have that feature, and they can’t add it via a plugin, because then everyone depending on a Kotlin Multiplatform project, would need that plugin, even if they don’t use kotlin

E.g. okio is a very popular java lib and Kotlin Multiplatform, if we implemented your proposal every java project using okio would need to use Kotlin’s maven plugin

Ontop of that a language plugin should not re-implement the build-tools entire dependency handling, since that’s one of the most important features of a build tool to begin with, it would be a huge financial investment for something that has little gain