https://kotlinlang.org logo
#jewel
Title
# jewel
t

Tomasz Glab

09/22/2023, 5:32 PM
Hey, I am trying to include Jewel as a dependency in IntelliJ plugin I develop and stumbled upon an issue with
kotlinx-coroutines-core
and Java Class loaders. As I am already struggling with it for a longer while, I wonder whether you could help me. Error is as follows: (full error in the attachment, as Slack has characters limit in a message)
Copy code
2023-09-22 18:27:50,396 [   4108] SEVERE - #c.i.o.a.i.CoroutineExceptionHandlerImpl - Unhandled exception in [CoroutineName(org.jetbrains.plugins.bsp.flow.open.BspStartupActivity), StandaloneCoroutine{Cancelling}@52cf8609, Dispatchers.Default]
java.lang.LinkageError: loader constraint violation: when resolving method 'kotlin.coroutines.CoroutineContext com.intellij.openapi.application.CoroutinesKt.getEDT(kotlinx.coroutines.Dispatchers)' the class loader com.intellij.ide.plugins.cl.PluginClassLoader @165caf33 of the current class, org/jetbrains/plugins/bsp/ui/widgets/tool/window/all/targets/BspAllTargetsWidgetFactoryKt, and the class loader com.intellij.util.lang.PathClassLoader @6f79caec for the method's defining class, com/intellij/openapi/application/CoroutinesKt, have different Class objects for the type kotlinx/coroutines/Dispatchers used in the signature (org.jetbrains.plugins.bsp.ui.widgets.tool.window.all.targets.BspAllTargetsWidgetFactoryKt is in unnamed module of loader com.intellij.ide.plugins.cl.PluginClassLoader @165caf33, parent loader 'bootstrap'; com.intellij.openapi.application.CoroutinesKt is in unnamed module of loader com.intellij.util.lang.PathClassLoader @6f79caec)
	at org.jetbrains.plugins.bsp.ui.widgets.tool.window.all.targets.BspAllTargetsWidgetFactoryKt.registerBspToolWindow(BspAllTargetsWidgetFactory.kt:42)
	at org.jetbrains.plugins.bsp.flow.open.BspStartupActivity.doRunActivity(BspStartupActivity.kt:50)
	at org.jetbrains.plugins.bsp.flow.open.BspStartupActivity.execute(BspStartupActivity.kt:45)
	at com.intellij.ide.startup.impl.StartupManagerImplKt$launchActivity$1$1.invokeSuspend(StartupManagerImpl.kt:534)
	at com.intellij.ide.startup.impl.StartupManagerImplKt$launchActivity$1$1.invoke(StartupManagerImpl.kt)
	at com.intellij.ide.startup.impl.StartupManagerImplKt$launchActivity$1$1.invoke(StartupManagerImpl.kt)
	at kotlinx.coroutines.intrinsics.UndispatchedKt.startUndispatchedOrReturn(Undispatched.kt:78)
	at kotlinx.coroutines.BuildersKt__Builders_commonKt.withContext(Builders.common.kt:167)
	at kotlinx.coroutines.BuildersKt.withContext(Unknown Source)
	at com.intellij.ide.startup.impl.StartupManagerImplKt$launchActivity$1.invokeSuspend(StartupManagerImpl.kt:532)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
	at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:584)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:793)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:697)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:684)
2023-09-22 18:27:50,401 [   4113] SEVERE - #c.i.o.a.i.CoroutineExceptionHandlerImpl - IntelliJ IDEA 2023.2 RC  Build #IC-232.8660.142
2023-09-22 18:27:50,402 [   4114] SEVERE - #c.i.o.a.i.CoroutineExceptionHandlerImpl - JDK: 17.0.7; VM: OpenJDK 64-Bit Server VM; Vendor: JetBrains s.r.o.
2023-09-22 18:27:50,402 [   4114] SEVERE - #c.i.o.a.i.CoroutineExceptionHandlerImpl - OS: Linux
2023-09-22 18:27:50,404 [   4116] SEVERE - #c.i.o.a.i.CoroutineExceptionHandlerImpl - Plugin to blame: Build Server Protocol version: 2023.2.0-EAP
Exception in thread "DefaultDispatcher-worker-28" java.lang.LinkageError: loader constraint violation: when resolving method 'kotlin.coroutines.CoroutineContext com.intellij.openapi.application.CoroutinesKt.getEDT(kotlinx.coroutines.Dispatchers)' the class loader com.intellij.ide.plugins.cl.PluginClassLoader @165caf33 of the current class, org/jetbrains/plugins/bsp/ui/widgets/tool/window/all/targets/BspAllTargetsWidgetFactoryKt, and the class loader com.intellij.util.lang.PathClassLoader @6f79caec for the method's defining class, com/intellij/openapi/application/CoroutinesKt, have different Class objects for the type kotlinx/coroutines/Dispatchers used in the signature (org.jetbrains.plugins.bsp.ui.widgets.tool.window.all.targets.BspAllTargetsWidgetFactoryKt is in unnamed module of loader com.intellij.ide.plugins.cl.PluginClassLoader @165caf33, parent loader 'bootstrap'; com.intellij.openapi.application.CoroutinesKt is in unnamed module of loader com.intellij.util.lang.PathClassLoader @6f79caec)
	at org.jetbrains.plugins.bsp.ui.widgets.tool.window.all.targets.BspAllTargetsWidgetFactoryKt.registerBspToolWindow(BspAllTargetsWidgetFactory.kt:42)
	at org.jetbrains.plugins.bsp.flow.open.BspStartupActivity.doRunActivity(BspStartupActivity.kt:50)
	at org.jetbrains.plugins.bsp.flow.open.BspStartupActivity.execute(BspStartupActivity.kt:45)
	at com.intellij.ide.startup.impl.StartupManagerImplKt$launchActivity$1$1.invokeSuspend(StartupManagerImpl.kt:534)
	at com.intellij.ide.startup.impl.StartupManagerImplKt$launchActivity$1$1.invoke(StartupManagerImpl.kt)
	at com.intellij.ide.startup.impl.StartupManagerImplKt$launchActivity$1$1.invoke(StartupManagerImpl.kt)
	at kotlinx.coroutines.intrinsics.UndispatchedKt.startUndispatchedOrReturn(Undispatched.kt:78)
	at kotlinx.coroutines.BuildersKt__Builders_commonKt.withContext(Builders.common.kt:167)
	at kotlinx.coroutines.BuildersKt.withContext(Unknown Source)
	at com.intellij.ide.startup.impl.StartupManagerImplKt$launchActivity$1.invokeSuspend(StartupManagerImpl.kt:532)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
	at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:584)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:793)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:697)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:684)
	Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [CoroutineName(org.jetbrains.plugins.bsp.flow.open.BspStartupActivity), StandaloneCoroutine{Cancelling}@52cf8609, Dispatchers.Default]
2023-09-22 18:27:55,584 [   9296]   WARN - #c.i.u.x.Binding - no accessors for com.intellij.ide.util.TipsUsageManager$State
2023-09-22 18:30:27,052 [ 160764]   WARN - #c.i.u.x.Binding - no accessors for com.intellij.openapi.projectRoots.Sdk
2023-09-22 18:30:27,062 [ 160774]   WARN - #c.i.u.x.Binding - no accessors for java.time.LocalTime
2023-09-22 18:30:27,248 [ 160960]   WARN - #c.i.o.p.i.ProjectManagerImpl - Failed to publish projectClosing(project) event
java.lang.RuntimeException: Cannot invoke (class=ProjectClosingListener, method=projectClosing, topic=ProjectManagerListener)
	at com.intellij.util.messages.impl.MessageBusImplKt.invokeListener(MessageBusImpl.kt:676)
	...
	at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:92)
Caused by: com.intellij.diagnostic.PluginException: Cannot load class kotlinx.coroutines.CoroutineScope (
  error: loader constraint violation: loader com.intellij.ide.plugins.cl.PluginClassLoader @165caf33 wants to load interface kotlinx.coroutines.CoroutineScope. A different interface with the same name was previously loaded by com.intellij.util.lang.PathClassLoader @6f79caec. (kotlinx.coroutines.CoroutineScope is in unnamed module of loader com.intellij.util.lang.PathClassLoader @6f79caec),
  classLoader=PluginClassLoader(plugin=PluginDescriptor(name=Build Server Protocol, id=org.jetbrains.bsp, descriptorPath=plugin.xml, path=~/JetBrains/intellij-bsp/build/idea-sandbox/plugins/intellij-bsp, version=2023.2.0-EAP, package=null, isBundled=false), packagePrefix=null, state=active)
)
	at com.intellij.ide.plugins.cl.PluginClassLoader.loadClassInsideSelf(PluginClassLoader.kt
...
I wanted to have 2 UI tool windows simultaneously, the one being with the old implementation and the new a implemented with Jewel. I wanted to use DemoToolWindow from Jewel IDE-sample. I included necessary dependencies and got this error. To be exact I included in dependecies:
Copy code
libs.versions.toml
[versions]
...
jewel = "0.6.3"

[libraries]
...
jewelComposeUtils = {module = "org.jetbrains.jewel:jewel-compose-utils", version.ref = "jewel" }
jewelCore = {module = "org.jetbrains.jewel:jewel-core", version.ref = "jewel" }
jewelIdeLafBridge = {module = "org.jetbrains.jewel:jewel-ide-laf-bridge", version.ref = "jewel" }
From what I understand the error arises because Intellij Platform comes bundled with different version of kotlinx-coroutines-core than Jewel uses. As our "old" UI uses
Copy code
import com.intellij.openapi.application.EDT
import kotlinx.coroutines.Dispatchers
...
withContext(Dispatchers.EDT) {...}
Do you have any ideas how to overcome this issue?
s

seb

09/22/2023, 5:50 PM
Hi @Tomasz Glab! I'll preface this by saying @Lamberto Basti is probably the best person to help with this, but, out of curiosity, have you tried excluding the coroutines dependency from the Jewel one?
BTW you should only ever need to depend on
org.jetbrains.jewel:jewel-ide-laf-bridge
, the other modules are brought in
l

Lamberto Basti

09/22/2023, 5:52 PM
Never EVER add coroutines in the zip of your IJ plugin. alongside with Kotlin stdlib, kotlinx serialization, store, and many more undocumented 😂
s

seb

09/22/2023, 5:55 PM
I don't think Jewel is bringing those with it, now that I think about it, since the sample plugin is built with Gradle and works just fine (and it only depends on Jewel, nothing else)
l

Lamberto Basti

09/22/2023, 5:56 PM
Compose brings them unfortunately. It should be the IJ Gradle plugin to take care but it does not lol
s

seb

09/22/2023, 5:56 PM
Ah damn
So do they need to be explicitly excluded?
l

Lamberto Basti

09/22/2023, 5:57 PM
Yes, that would be a good start.
@Tomasz Glab btw if you need help, write me moonday or book a 1-to-1 in the calendar
t

Tomasz Glab

09/26/2023, 7:22 AM
Thank you for all the answers. I am new to Gradle, so maybe I miss something. I excluded kotlinx-coroutines-core by using
Copy code
implementation(JewelLafBridge) {
    exclude("org.jetbrains.kotlinx", "kotlinx-coroutines-core")
}
But it didn't help. Even when I removed our UI, the same problem arises with other action using coroutines in our plugin. I also created a simple reproduction on the forked Jewel example, where I added the coroutine, which registers the toolWindow, exactly how it is done in our plugin. You can find it here. When it comes to adding coroutines/stdlib/other to the plugin's zip, I think it does not happen, but as I said, I can be missing something. Also, thank you for you offer Lamberto. Sooner or later, I will probably use it.
s

seb

09/26/2023, 3:32 PM
CC @Lamberto Basti
l

Lamberto Basti

09/27/2023, 1:56 PM
It's... complicated. I sent you an invitation for a 1-to-1!
t

Tomasz Glab

09/27/2023, 1:58 PM
Hopefully exciting then, thanks!
5 Views