日別アーカイブ: 2013年8月2日

JavaFXとWebsocketを連携してみる(On Glassfish4.0) その4

WebSocketで受け取ったデータをJavaFXのラベルに設定する方法とりあえず動いた。

大まかなフローは、

  1. WebSocket起動
  2. Websocketの@OnMessageでデータ受信
  3. @OnMessageの中でPlatform.runLaterを使ってJavaFXのスレッドを起動(コマンドの依頼??)
  4. Platform.runLaterの中でLabel#setTextを呼び出して値を更新

(ボタンイベントからWebsocketの起動周り)

public class SampleController {

    @FXML
    private Label testLabel;

    @FXML
    private void handleButtonAction(ActionEvent event) {
        kickWebSocket();
    }

    private void kickWebSocket() {
        try {
            CountDownLatch messageLatch = new CountDownLatch(1);
            URI clientURI = new URI("ws://localhost:8080/first/hello/");
            ClientManager cliContainer = org.glassfish.tyrus.client.ClientManager
                    .createClient();
            cliContainer.connectToServer(new WSClient(testLabel), clientURI);
            messageLatch.await(1, TimeUnit.SECONDS);
        } catch (DeploymentException | URISyntaxException
                | InterruptedException ex) {
            Logger.getLogger(SampleController.class.getName()).log(
                    Level.SEVERE, null, ex);
        }
    }
}

(OnMeessageから値の設定)

@ClientEndpoint
public class WSClient {

    private Label testLabel;

    public WSClient(Label testLabel) {
        this.testLabel = testLabel;
    }

    @OnOpen
    public void onOpen(Session session) {
        System.out.println("Connection had opened.");
    }

    @OnMessage
    public void onMessage(String message) {
        if (message.length() == 0) {
            return;
        }
        final String channeled = message;
        Platform.runLater(new Runnable() {
            @Override
            public void run() {
                testLabel.setText(channeled);
            };
        });
    }

    @OnClose
    public void closeConnection(Session session) {
        System.out.println("Connection had closed.");
    }

    @OnError
    public void error(Session sess, Throwable t) {
        System.out.println("エラーです:" + sess.getId());
        t.printStackTrace();
    }
}

(一応サーバ側)

@ServerEndpoint("/hello/")
public class HelloWorld {

    static Set<Session> sessions = Collections
            .synchronizedSet(new HashSet<Session>());

    @OnMessage
    public void onMessage(String message) {
        System.out.println("message[" + message + "]");

        for (Session s : sessions) {
            s.getAsyncRemote().sendText(message);
        }
    }

    @OnOpen
    public void open(Session sess) {
        System.out.println("開始します:" + sess.getId());
        sessions.add(sess);
    }

    @OnClose
    public void close(Session sess) {
        System.out.println("終了します:" + sess.getId());
        sessions.remove(sess);
    }

    @OnError
    public void error(Session sess,Throwable t) {
        System.out.println("エラーです:" + sess.getId());
        t.printStackTrace();
    }
}

まだ、確認できていないのがこの実装で順序の保障できているかどうか。

(実装的にはWebSocketボタン押した回数立ち上がったりと適当な部分はありますが。)