WebSocketにてJSON形式のデータをJavaFXとやり取りしてみる。の4

先ほどに続いて送受信部分

送信処理

  1. 画面の送信ボタンからSingleController#handleSendActionが呼ばれる。
  2. SingleController#handleSendActionから@ClientEndpointのsendメソッド(自分で作った普通のメソッド)を呼び出す。
  3. sendメソッド内でSession.getAsyncRemote().sendObject(dataObj)を呼び出す
  4. encodersに指定してあるClientEncoderクラスのencodeメソッドが呼び出される。
  5. encodeメソッドでエンコードされたデータ(JSON形式の文字列)がServerEndpointに送信される。

エコープログラムなのでServerEndpointで受信されたデータは(若干加工され)ClientEndpointに戻される。そのため、続けて受信処理が走る。

 

受信処理

  1. サーバからのデータがPushされる。
  2. @ClientEndpointのdecodersに指定してあるClientDecoderクラスのwillDecodeメソッドが呼び出され入力値がチェックされる。
  3. willDecodeの結果がtrueならば続けてdecodeメソッドが呼び出されてジェネリクスで指定した型(ClientData)にデコードされる。
  4. デコードされたデータを引数に@ClientEndpointの@OnMessageが呼び出される。ここはJavaFXのスレッド配下ではなく、WebSocketのスレッドに移っている。そのため、JavaFXのコントロールを直接操作することはできない。
  5. @OnMessageの中でPlatform.runLaterを呼び、JavaFXの画面操作(接続時処理ViewObj#write)の呼び出しを登録(?)する。
  6. JavaFXスレッドに戻り、JavaFXの画面操作が実行される。

(コントローラーの関連する部分)

public class SingleController implements Initializable {
    @FXML
    private void handleSendAction(ActionEvent event) {
        System.out.println("SingleController#handleSendAction");
        wsClient.send(msgInput.getText(), sess);
    }
}

(ClientEndpointの関連する部分)

@ClientEndpoint( 
   decoders = { ClientDecoder.class }, 
   encoders = { ClientEncoder.class })
public class WSJsonSingleClient {

    @OnMessage
    public void onMessage(ClientData dataObj) {
        System.out.println("WSJsonSingleClient#onMessage");
        final ClientData channeled = dataObj;
        Platform.runLater(new Runnable() {
            @Override
            public void run() {
                viewObj.write(
                        channeled.getSessionId(), 
                        channeled.getMessageTimeString(), 
                        channeled.getMessage());
            };
        });
    }

    public void send(String text,Session sess) {
        System.out.println("WSJsonSingleClient#send");
        ClientData dataObj = new ClientData(text);
        sess.getAsyncRemote().sendObject(dataObj);
    }
}

(ClientEncoder)

public class ClientEncoder implements Encoder.Text<ClientData> {

    @Override
    public void init(EndpointConfig paramEndpointConfig) {
        System.out.println("ClientEncoder#init");
    }

    @Override
    public void destroy() {
        System.out.println("ClientEncoder#destroy");
    }

    @Override
    public String encode(ClientData paramData) throws EncodeException {
        System.out.println("ClientEncoder#encode");
        JsonObject model = Json.createObjectBuilder()
                   .add("message", paramData.getMessage())
                   .add("messageTime",paramData.getMessageTime())
                   .build();
        return model.toString();
    }
}

(ClientDecoder)

public class ClientDecoder implements Decoder.Text<ClientData> {

    @Override
    public void destroy() {
        System.out.println("ClientDecoder#destroy");
    }

    @Override
    public void init(EndpointConfig arg0) {
        System.out.println("ClientDecoder#init");
    }

    @Override
    public ClientData decode(String inputString) throws DecodeException {
        System.out.println("ClientDecoder#decode");
        try{
            JsonObject jsonObject = Json.createReader(new StringReader(inputString)).readObject();
            return  new ClientData(jsonObject);
        } catch(Exception e){
            e.printStackTrace();
            throw new DecodeException(inputString,"ClientDecoder#decode失敗", (Throwable)e);
        }
    }

    @Override
    public boolean willDecode(String inputString) {
        try {
            System.out.println("ClientDecoder#willDecode");
            Json.createReader(new StringReader(inputString)).readObject();
            return true;
        } catch (JsonException ex) {
            ex.printStackTrace();
            return false;
        }
    }
}

github:https://github.com/epea/test01/tree/WF_JSON_FX_SINGLE

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です