最近、Qiita記事が進捗報告になってまいりました。
今回も、こちらの記事の続きになります。
tyrus-standalone-clientの追加
普通にクライアントプログラムを書いて実行すると、次のようなエラーが発生します。
Exception in thread "main" java.lang.RuntimeException: Could not find an implementation class.
at javax.websocket.ContainerProvider.getWebSocketContainer(ContainerProvider.java:73)
at Main.main(Main.java:46)
stackoverrunによると、websocketはClientのインターフェースは提供しているものの、実装を提供していないようです。
そこで、glassfishにあるtyrus-standalone-clientを導入します。
StandardWebSocketClientクラスにWebSocketContainerを実装する方法
具体的には、build.gradleのdependenciesに追加します。
dependencies {
// 前回説明した
compileOnly 'javax:javaee-api:8.0'
// 今回追加するのがこれ
compile group: 'org.glassfish.tyrus.bundles', name: 'tyrus-standalone-client', version: '1.14'
}
ClientEndPointを記述する
では、今回は早速プログラムを書いていきましょう。
<プロジェクト名> -> src -> main -> java 内(の適当なパッケージ)に、.javaファイルを作成します。
import javax.websocket.*;
import java.net.URI;
import java.util.Scanner;
// このアノテーションを付けるとクライアントのEndpointだと認識される
@ClientEndpoint
public class Client {
public Client() {
super();
}
// セッション確立時の処理
@OnOpen
public void onOpen(Session session) {
System.out.println("[セッション確立]");
}
// メッセージ受信時の処理
@OnMessage
public void onMessage(String message) {
System.out.println("[受信]:" + message);
}
// メッセージ受信時の処理
@OnError
public void onError(Throwable th) {
System.err.println(th.getMessage());
}
// セッション解放時の処理
@OnClose
public void onClose(Session session) {
System.out.println("[切断]");
}
static public void main(String[] args) throws Exception {
// 初期化のため WebSocket コンテナのオブジェクトを取得する
WebSocketContainer container = ContainerProvider
.getWebSocketContainer();
// サーバー・エンドポイントの URI
URI uri = URI
.create("ws://localhost:8080/<プロジェクト名>/<リンク>");
// サーバー・エンドポイントとのセッションを確立する
// 実行されているクライアントから、引数に渡したクラスと同一の物を探して接続する?
Session session = container.connectToServer(Client.class, uri);
while (!session.isOpen()) {
Thread.sleep(500);
}
System.out.println("open");
try (Scanner s = new Scanner(System.in)) {
String str;
System.out.println("start loop");
while (true) {
str = s.nextLine();
if(str.equals("exit")) break;
//strの内容を送信
session.getBasicRemote().sendText(str);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
面倒なので今回はEndpointクラス内にmainを書きましたが、分けた方がいいような気がします。
実行
まず、tomcatRunなどで、Clientの入ったサーバーを立ち上げ、その後、別窓でmainを実行します。