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.

15 comments
Comment actions Permalink

Different JDK/JRE used in the two environments? Any accidental duplicated library dependencies?

1
Comment actions Permalink

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.

0
Comment actions Permalink

Please double-check the tyrus-client library is indeed deployed with your plugin.

0
Comment actions Permalink

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.

0
Comment actions Permalink

Can you share your project, please?

0
Comment actions Permalink

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.

0
Comment actions Permalink

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/ ?

0
Comment actions Permalink

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.

0
Comment actions Permalink

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.

0
Comment actions Permalink

Yes, this is what I use.

0
Comment actions Permalink

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.

0
Comment actions Permalink

Thank you for the sample project, reproduced. It seems the implementation in javax.websocket.ContainerProvider#getWebSocketContainer might fail in plugin runtime environment, investigating more...

1
Comment actions Permalink

Ok great, thanks for your efforts. Please keep me updated as my progress is fairly dependent on this. 

0
Comment actions Permalink

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!

0
Comment actions Permalink

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.

0

Please sign in to leave a comment.