okhttp:5.0.0-alpha.10 can run into `java.lang.ClassNotFoundException: kotlin.time.DurationUnit`
staktrace opened this issue · comments
See previous discussions in #7267, #7329, and #7343. This is a continuation of that thread of problems, trying to iron out issues when using okhttp in a gradle plugin where the runtime kotlin version is restricted to 1.5.
Now I have put together a minimal standalone reproduction of the problem. It can be found at https://github.com/staktrace/20220627-okhttp-durationunit/tree/57afefa7bbe4f1cf1ae0b1dd8b6d4e01c4b738ff. To reproduce, clone the repo and run the ./reproduce.sh
script. The setup is that there are two separate gradle projects - one is a plugin that uses okhttp, and the other is a consumer that uses the plugin.
Some things I discovered along the way of creating this reproducer:
- If the plugin lives in the
buildSrc
folder of the consumer project, the problem doesn't reproduce - The
kotlin-dsl
plugin being applied is important since it seems to be the thing that actually pins the gradle version to 1.5.31.
For the cases I care about, I was able to work around this issue by doing this - adding the kotlin 1.6 jvm plugin to the consumer repo made the DurationUnit class available and everything worked fine. In a bunch of cases the consumer already had the kotlin-dsl
plugin which I had to replace with kotlin("jvm")
instead, but this effectively solved all the problems I was seeing in downstream projects.
@staktrace do you still have that repro repo?
The repro is linked in the top comment - https://github.com/staktrace/20220627-okhttp-durationunit (main branch)
@staktrace is it private?
Ah sorry! Yes, it was private. Made it public now.
I'm a bi confused, so want to kick off the discussion of whether this is still needed?
I think this gradle/gradle#19539
and this gradle/gradle#16345, discussed here https://twitter.com/martinbonnin/status/1550035276604522498
Mean that we can revert this. So suggest that we do, I'll put a PR up and compile against 1.6.21.
Or is this the issue? gradle/gradle#19568
Gradle 7.5 will ship with Kotlin 1.6.21 but still target language/api 1/4 for backwards compatibility reasons. This can only be changed in a major version, next one being Gradle 8.0.
Your test PR, with 7.6 works. So going to revert this!
Can you try gradle 7.6 snapshot, or 7.5 release with an older version that you previously had problems with?
I tried your reproducer with the following and it appears to work
implementation("com.squareup.okhttp3:okhttp:5.0.0-alpha.8")
If the plugin lives in the buildSrc folder of the consumer project, the problem doesn't reproduce
Got curious and made a small test there https://github.com/martinbonnin/classloaders. Looks like the dependencies of buildSrc
are also put in the classpath albeit with a lower precedence than the embedded Kotlin jar. This way, you effectively end up with 2 versions of kotlin-stdlib
on the classpath. So kotlin-stdlib
symbols will resolve to the 1.5.31
version, except those that are not present that will fallback and load from the 1.6.10
jar. Gradle classloaders never cease to amaze 🙃 .
In all cases, Gradle 7.5 will fix the issue as it will put 1.6.something
by default and this one has DurationUnit
available.
@martinbonnin sounds like you agree we can revert the existing attempts and ask people to upgrade to 7.5?
Yep, users that want to use OkHttp in Gradle plugin should be able to do so with Gradle 7.5. Maybe you could add a runtime check when building a new client to point to this issue or give an actionable error message?
I know OkHttp already understands Android vs JVM platforms, but doing so for a build system seems a step too far.
Yup, that's fair 👍
I also confirmed that the original problem I was seeing goes away with gradle 7.5. So 👍 from me for reverting all the things.