I am writing a desktop Java application as a web service client. I want to use WebSocket to implement notification “callback” from the server.
I am using the Spring framework’s WebSocketStompClient. Below snippet shows how I initialize it:
import org.springframework.web.socket.messaging.WebSocketStompClient; import org.springframework.web.socket.sockjs.client.SockJsClient; import org.springframework.web.socket.sockjs.client.Transport; import org.springframework.web.socket.sockjs.client.WebSocketTransport; ... List<Transport> transports = new ArrayList<>(); transports.add(new WebSocketTransport(new StandardWebSocketClient())); stompClient = new WebSocketStompClient(new SockJsClient(transports)); ...
It works perfectly if I run it in IntelliJ IDE, however, if I run by command line “java -cp my.jar MyPackage.MyMainClass”, it will fail with the following message:
Error: Unable to initialize main class MyMainClass Caused by: java.lang.NoClassDefFoundError: org/springframework/web/socket/client/WebSocketClient
The above was produced by Java SE 12.0.2. If I run it using Java SE 1.8, the error message will be:
Error: A JNI error has occurred, please check your installation and try again Exception in thread "main" java.lang.NoClassDefFoundError: org/springframework/web/socket/client/WebSocketClient at java.lang.Class.getDeclaredMethods0(Native Method) at java.lang.Class.privateGetDeclaredMethods(Unknown Source) at java.lang.Class.privateGetMethodRecursive(Unknown Source) at java.lang.Class.getMethod0(Unknown Source) at java.lang.Class.getMethod(Unknown Source) at sun.launcher.LauncherHelper.validateMainClass(Unknown Source) at sun.launcher.LauncherHelper.checkAndLoadMain(Unknown Source)
Both java.lang.NoClassDefFoundError
and getDeclaredMethods0(Native Method)
suggsted that a native module (a DLL) is missing.
Below is my Gradle script:
dependencies { implementation project(':logman-common') implementation 'org.springframework:spring-web:5.2.2.RELEASE' implementation 'org.springframework:spring-websocket:5.2.2.RELEASE' implementation 'org.springframework:spring-messaging:5.2.2.RELEASE' ... // other unrelated dependencies, such as GUI }
I don’t think it was due to some missing JARs. I tried:
- to add
tyrus-standalone-client
to the dependency list, or - to use
StandardWebSocketClient
instead ofSockJsClient
,
but the error remained.
I guess some native libraries are missing in my OS (Win10), but that can’t explain why I can run it in IntelliJ…
Could you let me know what is missing? or how can I fix this? Thanks!
Advertisement
Answer
Try to create a fat jar which contains all the dependencies and classes.
Update build.gradle
script to this given below :
apply plugin: 'java' version = '...' sourceCompatibility = 1.8 targetCompatibility = 1.8 // to create a fat jar. jar { manifest { attributes "Main-Class": "MyPackage.MyMainClass" } from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } } } dependencies { implementation project(':logman-common') implementation 'org.springframework:spring-web:5.2.2.RELEASE' implementation 'org.springframework:spring-websocket:5.2.2.RELEASE' implementation 'org.springframework:spring-messaging:5.2.2.RELEASE' ... // other unrelated dependencies, such as GUI }
It will generate an executable fat jar in the build/libs
of your root project which will include all the project files (this includes all of your dependencies, resource files, .class files and so on).
Note: For older versions of Gradle, use this configurations.compile.collect
instead of configurations.runtimeClasspath.collect
.
You just need to run the jar with this command : java -jar <project-version>.jar
This should solve your problem.