Reputation: 11
I am trying to set up a websocket client in Java. I've followed the exact steps to this accepted answer, but when it runs I get a
java.lang.RuntimeException: Could not find an implementation class.
at javax.websocket.ContainerProvider.getWebSocketContainer(ContainerProvider.java:73)
at multiplayer.matchmaking.WebsocketClient$1.run(WebsocketClient.java:31)
at java.lang.Thread.run(Thread.java:748)
Exception in thread "Websocket Connection" java.lang.NullPointerException
at multiplayer.matchmaking.WebsocketClient$1.run(WebsocketClient.java:35)
at java.lang.Thread.run(Thread.java:748)
This is my WebsocketClient class:
package multiplayer.matchmaking;
import java.io.*;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Base64;
import javax.websocket.*;
import org.json.JSONException;
import org.json.JSONObject;
@ClientEndpoint
public abstract class WebsocketClient {
private Thread connectionThread;
private Session userSession;
public WebsocketClient(String addr) throws URISyntaxException {
this(new URI(addr));
}
public WebsocketClient(URI endpointURI) {
connectionThread = new Thread(new Runnable() {
@Override
public void run() {
try {
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
container.connectToServer(this, endpointURI);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}, "Websocket Connection");
connectionThread.setDaemon(true);
connectionThread.start();
}
@OnMessage
public void onMessage(String message) {
JSONObject json = null;
try {
json = new JSONObject(message);
} catch (JSONException e) {
System.err.println("Uknown text recieved: " + message);
}
if (json != null)
recieveJSON(json);
}
protected abstract void recieveJSON(JSONObject json);
protected abstract void connected();
public void sendAction(WebsocketCommand c) {
JSONObject msg = new JSONObject();
msg.put("command", "message");
msg.put("identifier", new JSONObject().put("channel", "GameChannel").toString());
msg.put("data", new JSONObject().put("action", "send_action").put("data", b64encode(c)).toString());
sendMessage(msg.toString());
}
public void sendMessage(String message) {
if (!isConnected())
throw new RuntimeException("sendMessage called before connected");
this.userSession.getAsyncRemote().sendText(message);
}
@OnOpen
public synchronized void onOpen(Session userSession) {
this.userSession = userSession;
connected();
}
@OnClose
public synchronized void onClose(Session userSession, CloseReason reason) {
this.userSession = null;
}
public synchronized boolean isConnected() {
return userSession != null;
}
public void join() throws InterruptedException {
connectionThread.join();
}
private static String b64encode(WebsocketCommand cmd) {
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
try (ObjectOutputStream oos = new ObjectOutputStream(baos)) {
oos.writeObject(cmd);
oos.flush();
return new String(Base64.getEncoder().encode(baos.toByteArray()));
}
} catch (IOException e) {
e.printStackTrace();
return "err";
}
}
public static WebsocketCommand b64decode(String enc) {
if (enc.equals("err"))
return null;
try (ByteArrayInputStream bais = new ByteArrayInputStream(Base64.getDecoder().decode(enc))) {
try (ObjectInputStream ois = new ObjectInputStream(bais)) {
return (WebsocketCommand) ois.readObject();
}
} catch (IOException e) {
e.printStackTrace();
return null;
} catch (ClassNotFoundException e) {
e.printStackTrace();
return null;
}
}
}
It looks like the line
container.connectToServer(this, endpointURI)
is looking for a ServerEndpoint
instead of a ClientEndpoint
from the documentation, but I can't find anything describing how to use a ClientEndpoint
.
Has anyone actually used the javax.websocket package as a functional client? I find it strange that the accepted solution to the other question doesn't actually work out of the box.
Upvotes: 0
Views: 1573
Reputation: 11
I solved it. I was missing a maven dependency. If anyone else runs into the same error, make sure you include the full javax dependencies-
<dependency>
<groupId>javax.websocket</groupId>
<artifactId>javax.websocket-client-api</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.glassfish.tyrus</groupId>
<artifactId>tyrus-client</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.tyrus</groupId>
<artifactId>tyrus-container-grizzly</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>javax.json</groupId>
<artifactId>javax.json-api</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.json</artifactId>
<version>1.0.1</version>
</dependency>
Upvotes: 1