Java - WebSocket get response outside of listener

Hexile :

I can't figure out this problem. I have a WebSocket and I want to make a request and get a response outside of the WebSocket object but I can only access the response inside the WebSocket object listener.

I could do all my logic inside the listener, but I would like to only get a String and process it in the main thread.

I am using nv-websocket-client as my WebSocket library.

Here is my example code:

WebSocket webSocket = new WebSocketFactory()
    .createSocket(URL, TIMEOUT)
    .addListener(new WebSocketAdapter(){
          @Override
          public void onTextMessage(WebSocket websocket, String text) throws Exception {
               super.onTextMessage(websocket, text);

               // TODO: pass result to function sendCommand()
          }
    })
    .connect()

public String sendCommand(String command) {
    webSocket.sendText(command);

    // TODO: return result;
}

Thank you!

Alin Corodescu :

What you are trying to achieve is to basically wait for asynchronous operation to finish and then to return to the caller. You send the request to the server and you have no way of knowing when the answer will come back (if at all). The code you are using implements the mechanism of callback to signal completion - it means that whenever the something happens (in your case you receive a response from the server), just call the method that you implemented in the adapter.

The class CompletableFuture is the perfect candidate for doing such a thing. A Future is an interface used to get hold of a result which may complete in the future. The .get() method will block the calling thread until a result is available. My idea is to create a custom adapter which you will use to communicate with the server (both to send data and to receive data from it) :

class MyWebSocketAdapter implements WebSocketAdapter {
   // Store the responseFuture as a member of the adapter. 
   private CompletableFuture<String> responseFuture;

   public String sendCommand(String command) {
       // CompletableFutures can only be "used" once, so create a new object
       responseFuture = new CompletableFuture<String>();
       webSocket.sendText(command);
       // Keep in mind potential errors and a timeout value to this call
       return responseFuture.get();
   }

   @Override
   public void onTextMessage(WebSocket websocket, String text) throws Exception {
      super.onTextMessage(websocket, text);
      // Do what you want to do with the text and then complete the future
      responseFuture.complete(text);
   }
}

Beware though that you will need to create a new adapter for each socket you create. If you pass the same object to more than one socket, you will have concurrency issues because only one of the sockets can write to the responseFuture.

Also, if you are not familiar with asynchronous programming I suggest you read up on that a bit, it usually makes concurrency a bit easier to manage and the core concepts are language-agnostic and lots of languages have either libraries or built-in support for it. Here is a introduction for java.


Disclaimer : I do not currently have a Java IDE installed so I couldn't compile it and it's been a while since I've worked with Java but I hope this helps you :) .

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=133867&siteId=1
Recommended