square/retrofit

Retrofit 3.0.0 and 2.12.0 Kotlin compatibility issue with Spring Boot 3.4.5 (Kotlin 1.9.25)

Opened this issue · 12 comments

Hi,

Thanks for the release of Retrofit 3.0.0, it's great to see the OkHttp update.

I'm encountering a compatibility issue with the Kotlin version used in Retrofit 3.0.0 when integrating it with a Spring Boot application. Spring Boot currently provides Kotlin 1.9.25.
Upon updating to Retrofit 3.0.0, I receive the following error:

.m2/repository/com/squareup/retrofit2/retrofit/3.0.0/retrofit-3.0.0.jar!/META-INF/retrofit.kotlin_module: Module was compiled with an incompatible version of Kotlin. The binary version of its metadata is 2.1.0, expected version is 1.9.0.

My project relies on the Kotlin version managed by Spring Boot, and I'm unable to change it independently due to potential compatibility issues with other dependencies.

Based on my understanding, Kotlin 1.9.25 should be compatible with libraries compiled with Kotlin up to version 2.0.0.

Given that Spring Boot isn't expected to include Kotlin 2.1.0 support before their next major version, would it be possible to compile Retrofit 3.0.0 to be compatible with Kotlin 1.9.x? This would allow Spring Boot users to adopt Retrofit 3.x without waiting for a Spring Boot major release.

As a side note, I noticed that OkHttp 4.12 appears to be based on Kotlin 1.8 according to their changelog.

I appreciate your consideration and hope this compatibility can be addressed.

Thanks!

I tried moving to 2.12.0 thinking it would not have the same issue, but it's actually also failing in the same way so I had to roll back to 2.11.0

Could you please show the dependencies and plugins in your Gradle build script?

Generally we have following settings in a SpringBoot application (build.gradle.kts)

plugins {
    kotlin("jvm") version "2.xx"
}

Somewhat related but the okhttp:4.12.0 depends on kotlin-stdlib-jdk8:1.8.21 -> kotlin-stdlib:1.8.21 while the retrofit:3.0.0 depends on kotlin-stdlib:2.1.21. Can this be an issue?

If you explicitly specify the latest Kotlin version in your Gradle (especially Gradle plugin) or Maven build, it should be compatible with different libraries.

@csisy No issue

Hi.

Thanks for your answers.
I understand and I completely agree that upgrading my kotlin version to the latest might work. However, upgrading to the next major version of kotlin, knowing it could impact other dependencies in my code is not a risk I can take in my organization at the moment. We are following the kotlin version provided by spring boot to limit any risks of incompatibilities. I guess that may be the case for many people using spring boot and kotlin.

I understand if you decide to not support older kotlin version with retrofit 3.0.0 (although I would be sad about it) but I think version 2.12.0 should not contain such major changes in any case.

AFAIK kotlin 1.9.25 can support kotlin up to 2.0.x so if you want some in between solution I guess this could be an option.

Thanks

I will downgrade to 2.0.x and do a patch release. However, do not expect 3.1.0 to still be compatible. There are equally as many people who complain about us shipping older versions of dependencies because of CVEs (even though none of our code is affected), so it's an unwinnable battle and we err on the side of staying more current.

The Kotlin 1.9.2x series is from November 2023, and 2.0.x turns a year old tomorrow. From the language and libraries perspective, 2.0 is really just a rebranded 1.10 because of the compiler switch so it's not as significant as the major version bump would imply. Additionally, 2.2 is only a few weeks away from release. I would hope Spring Boot would be more on top of staying current in the future as we can't be expected to stay behind, especially as we look to things like Kotlin multiplatform support.

My own SpringBoot application works with JDK 21 and Kotlin 2.1.20:

plugins {
    kotlin("jvm") version "2.1.20"
    kotlin("plugin.spring") version "2.1.20"
    kotlin("plugin.serialization") version "2.1.20"
    kotlin("plugin.jpa") version "2.1.20"
    id("com.google.devtools.ksp") version "2.1.20-1.0.31"
    id("org.springframework.boot") version "3.4.3"
    id("io.spring.dependency-management") version "1.1.7"
}
dependencies {
        implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
        implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310")
        implementation("org.springframework.boot:spring-boot-starter")
        implementation("org.springframework.boot:spring-boot-starter-data-redis")
// ...
}

I think this is just your configuration issue.

@JakeWharton Thank you. I understand and I'm completely in line with your concerns. I too would wish for spring boot to have switched earlier to kotlin 2.1, that would have made many things easier in more than one way for me.

Thanks again.

vlsi commented

Spring Boot upgrades only patch level for third-party dependencies.
So Kotlin upgrade in Spring Boot happens only with major Spring Boot releases.

See https://github.com/spring-projects/spring-boot/wiki/Supported-Versions#third-party-dependencies

Spring Boot provides managed dependencies for many third-party libraries. These libraries are upgraded only at the patch level for any given Spring Boot patch release. Minor and major version upgrades of third-party libraries are only applied in Spring Boot minor or major releases


The core of the issue is that retrofit uses a too recent apiVersion/languageVersion while none of the Kotlin features in retrofit really need Kotlin 2.1.

It would be great to add something like apiVersion=1.8 and languageVersion=1.8 so the clients could use retrofit with various Kotlin versions in runtime.
An alternative option would be extracting suspend extensions to a separate module so the main artifact does not include retrofit.kotlin_module file altogether.

I will downgrade to 2.0.x and do a patch release. However, do not expect 3.1.0 to still be compatible. There are equally as many people who complain about us shipping older versions of dependencies because of CVEs (even though none of our code is affected), so it's an unwinnable battle and we err on the side of staying more current.

The Kotlin 1.9.2x series is from November 2023, and 2.0.x turns a year old tomorrow. From the language and libraries perspective, 2.0 is really just a rebranded 1.10 because of the compiler switch so it's not as significant as the major version bump would imply. Additionally, 2.2 is only a few weeks away from release. I would hope Spring Boot would be more on top of staying current in the future as we can't be expected to stay behind, especially as we look to things like Kotlin multiplatform support.

Hi @JakeWharton. I hope you're well. Any chance that patch release will come soon for versions 2.x ?
Thanks