WebSocket Echo Client (Part2)
I amended the previous application(WebSocket Echo Client - tomoTakaの日記)
After reading this article(Java技術最前線 - JavaFX 2ではじめる、GUI開発 第14回 非同期処理:ITpro) about concurrency in JavaFX, I got the advice about the above application from the author.
This code shows how to communicate JavaFX to EchoClientEndPoint using the service class.(F.Y.R seeConcurrency in JavaFX | JavaFX 2 Tutorials and Documentation)
- Echo Client Screen
You click the open button, the connection to the Echo server starts.
When you click the send button or the close button, the messages appear on ListView.
- code1(EchoClienEndpoint.java)
In this code, the message sent from the echo server is added to the Blocking queue.
The blocking queue is set in the EchoClientService class.(see code3)
The Blocking queue role is like a message pipeline between JavaFX and the Echo Client.
public class EchoClienEndpoint extends Endpoint{ private BlockingQueue<String> queue; public EchoClienEndpoint(BlockingQueue<String> queue) { this.queue = queue; } @Override public void onOpen(Session session, EndpointConfig ec) { try { session.getBasicRemote().sendText("open connection"); } catch (IOException ex) { Logger.getLogger(EchoClienEndpoint.class.getName()).log(Level.SEVERE, null, ex); } session.addMessageHandler(new MessageHandler.Whole<String>() { @Override public void onMessage(String message) { queue.offer(String.format("received message is %s", message)); // ***** the message is added to the queue } }); } @Override public void onClose(Session session, CloseReason closeReason) { queue.offer("*** close connection ***"); // ***** the message is added to the queue } }
- code2(EchoClientFX.java)
- code2-1
When you click the open button, the Echo Client Service starts.
And the timer(Timeline) is used to observe the message queue.
public class EchoClientFX extends Application { private BlockingQueue<String> queue = new LinkedBlockingDeque<>(); private EchoClientService service = new EchoClientService(); private Timeline timer; private ObservableList<String> messageList = FXCollections.observableArrayList(); //... openBtn.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent event) { service.reset(); service.start(); timer = new Timeline(new KeyFrame(Duration.millis(100), new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent t) { while (!queue.isEmpty()) { try { String message = queue.take(); messageList.add(0, message); // *** the message appears the ListView } catch (InterruptedException ex) { Logger.getLogger(EchoClientFX.class.getName()).log(Level.SEVERE, null, ex); } } } })); timer.setCycleCount(Timeline.INDEFINITE); } });
- code2-2
After the service task completes successfully, the timer starts. This means the message appears on the ListView.(see code 2-1)
//... service.setOnSucceeded(new EventHandler<WorkerStateEvent>() { @Override public void handle(WorkerStateEvent t) { timer.play(); // *** Timeline starts connectionProp.setValue(Boolean.TRUE); } });
- code2-3
The message is sent to the Echo server through the EchoClientService class.(see code3)
//... sendBtn.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent event) { service.sendText(messageTxt.getText()); messageTxt.clear(); } });
- code3(EchoClientService class in EchoClientFX.java)
This code extends the Service as the background threads.
When the task is executed, the connection to the Echo server starts.
class EchoClientService extends Service<Session> { private Session session; @Override protected Task<Session> createTask() { Task<Session> task = new Task<Session>() { @Override protected Session call() throws Exception { ClientManager client = ClientManager.createClient(); // ***** here is how to start the connection to the Echo server ClientEndpointConfig cec = ClientEndpointConfig.Builder.create().build(); URI uri = new URI("ws://localhost:8080/ws/echo"); session = client.connectToServer(new EchoClienEndpoint(queue), cec, uri); // ***** set the queue to the EchoClienEndpoint return session; } }; return task; } void sendText(String message) { if (session != null) { try { session.getBasicRemote().sendText(message); // ***** send the message to the Echo server } catch (IOException ex) { Logger.getLogger(EchoClientFX.class.getName()).log(Level.SEVERE, null, ex); } } } void closeSession() { if (session != null) { try { session.close(); } catch (IOException ex) { Logger.getLogger(EchoClientFX.class.getName()).log(Level.SEVERE, null, ex); } } }
The whole code is hereGitHub - tomoTaka01/WebSocketTest: The WebSocket client sample in JavaFX.
I am not sure this is the good way to implement the WebSocket client on JavaFX....
just keep coding.....