Websocket runtime exception couldn't find an implementation class, with gradle dependency, in IntelliJ tool window.
Answered
I'm faced with an interesting problem. I have an intellij plugin which creates an intellij tool window which, as part of its functionality, uses a websocket. In my build.gradle, I have compile group: 'org.glassfish.tyrus.bundles', name: 'tyrus-standalone-client', version: '1.15'
. When I run my java code as an application and trigger the methods programmatically, or using JFrame guis, the websocket runs as it should. However, when using the same compile line in my plugin tool window, I get the following error.
java.lang.RuntimeException: java.lang.RuntimeException: Could not find an
implementation class.
at ElasticsearchClientEndpoint.<init>(ElasticsearchClientEndpoint.java:19)
Caused by: java.lang.RuntimeException: Could not find an implementation class.
at javax.websocket.ContainerProvider.getWebSocketContainer(ContainerProvider.java:73)
at ElasticsearchClientEndpoint.<init>(ElasticsearchClientEndpoint.java:16)
I've tried running the plugin from a project which has the same dependency but I still get this error. I can't work out why I'm getting this error, any help would be excellent.
Please sign in to leave a comment.
Different JDK/JRE used in the two environments? Any accidental duplicated library dependencies?
Just checked, and the plugin development environment is using the same JDK as the gradle :runIde environment (if that's what you mean). In the project loaded in the runIde environment, I had the websocket and tyrus dependencies added, however after removing them the error persists. Do you mean duplicated library dependencies within the plugin development environment? If so, I have the dependencies added in project structure and in gradle, however even after changing this the error persists.
Please double-check the tyrus-client library is indeed deployed with your plugin.
Sorry, I'm not totally sure how to check that. It isn't in the project structure in the runIde environment. That only contains the JDK, however in the plugin development project structure, listed in the libraries is Gradle: org.glassfish.tyrus.bundles:tyrus-standalone-client:1.15. Does this mean it is deployed with my plugin, or not necessarily? Please let me know if this is checked in a different way, thanks a lot.
Can you share your project, please?
Unfortunately I can't share the project, and even if I could you would have to install lots of stuff. I will work on reproducing the problem and leave another comment with that project. Let me know if you have a different idea, thank you.
From what I can guess it looks like the tyrus-client library is not available at runtime/where your plugin is deployed to. I assume you do use https://github.com/JetBrains/gradle-intellij-plugin/ ?
Yes this is also what I think. I'm quite sure that is what I use, I'm using the default gradle plugin included in the latest update of IDEA Ultimate.
I meant the plugin for Gradle itself in order to developer plugins for IntelliJ (see link above). It takes care of packaging all required libraries etc.
Yes, this is what I use.
Hi so I reproduced the problem here: https://github.com/AlexsFabulousFlow/websocket-test
It should work when run with Start.main(), however on my machine it produces an error when run with Gradle Plugin configuration. Please let me know how it goes. Thank you.
Thank you for the sample project, reproduced. It seems the implementation in javax.websocket.ContainerProvider#getWebSocketContainer might fail in plugin runtime environment, investigating more...
Ok great, thanks for your efforts. Please keep me updated as my progress is fairly dependent on this.
For anyone who has the same problem, I found a work around with this https://github.com/AlexsFabulousFlow/functional-websocket-test/tree/master.
Thanks a lot for the help, Yann!
You can fix the problem without switching to a different library. The problem happens because javax.websocket.ContainerProvider uses ServiceLoader.load(Class) method to load service implementations, which loads them from the context classloader of the current thread. Since your plugin's code is executed in a shared thread, its context classloader is set to the platform classloader, which cannot load resources from your plugin code or its libraries. You can fix the problem by invoking Thread.currentThread().setContextClassLoader(getClass().getClassLoader()) before calling ContainerProvider.getWebSocketContainer and restoring the old value after the call.
Hello there, I'm hitting the same error as OP.
My project incudes org.glassfish.tyrus.bundles but classloades still cannot find /META_INF/service/
Re: Alex - Have you removed the workaround from github? The link is not working.
Re: Nikolay - " You can fix the problem by invoking Thread.currentThread().setContextClassLoader(getClass().getClassLoader()) before calling ContainerProvider.getWebSocketContainer and restoring the old value after the call."
- How I would do that? I mean "restoring the old value after the call?"
Thank you gentleman
Thanks, this code definitely helps me out :)
Thank you. This code saved me days of having to figure this out myself if at all.