先ほどに続いて送受信部分
送信処理
- 画面の送信ボタンからSingleController#handleSendActionが呼ばれる。
- SingleController#handleSendActionから@ClientEndpointのsendメソッド(自分で作った普通のメソッド)を呼び出す。
- sendメソッド内でSession.getAsyncRemote().sendObject(dataObj)を呼び出す
- encodersに指定してあるClientEncoderクラスのencodeメソッドが呼び出される。
- encodeメソッドでエンコードされたデータ(JSON形式の文字列)がServerEndpointに送信される。
エコープログラムなのでServerEndpointで受信されたデータは(若干加工され)ClientEndpointに戻される。そのため、続けて受信処理が走る。
受信処理
- サーバからのデータがPushされる。
- @ClientEndpointのdecodersに指定してあるClientDecoderクラスのwillDecodeメソッドが呼び出され入力値がチェックされる。
- willDecodeの結果がtrueならば続けてdecodeメソッドが呼び出されてジェネリクスで指定した型(ClientData)にデコードされる。
- デコードされたデータを引数に@ClientEndpointの@OnMessageが呼び出される。ここはJavaFXのスレッド配下ではなく、WebSocketのスレッドに移っている。そのため、JavaFXのコントロールを直接操作することはできない。
- @OnMessageの中でPlatform.runLaterを呼び、JavaFXの画面操作(接続時処理ViewObj#write)の呼び出しを登録(?)する。
- 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