Vinit Sharma
Vinit Sharma

Reputation: 80

Implementing a WebSocketClient in Scala controller

I have a scala controller in which I am calling an external webservice using WS api of Play! framework which returns a json. The same api is now to be called using a WebSocketClient as every connection should be made using a WebSocket instead of http. So normal Action in controller are converted to WebSocket functions, however I am not being able to call a WebSocket function from within the scala code. I have searched and gone through several places on web for the solution, but I didn't found the solution anywhere. How can this be done, calling a WebSocket function and fetch its json using a WebSocketClient in scala code OR we can say, consuming a WebSocket from within scala code ? I found a similar to mine questio on SO but none has given an answer to that! I want to know whether its possible or not in Play framework ?

Consume a WebSocket connection using Scala and Play

Edit: I am implementing the following code:

val c = new AsyncHttpClient()
val webSocketClient = c.prepareGet("ws://0.0.0.0:9000/testSocket").execute(new WebSocketUpgradeHandler.Builder().addWebSocketListener(new WebSocketTextListener {

  override def onMessage(s: String): Unit = {
  }

  override def onOpen(webSocket: websocket.WebSocket): Unit = {
    webSocket.sendTextMessage("test")
  }

  override def onFragment(s: String, b: Boolean): Unit = {}

  override def onError(throwable: Throwable): Unit = {}

  override def onClose(webSocket: websocket.WebSocket): Unit = {
    latch.countDown()
  }
}).build()).get()

val result = webSocketClient.sendTextMessage("true")
println("================================" + result)

The result variable is not printed on console giving a json parser exception.

Update: My WebSocket connection in ws://0.0.0.0:9000/testSocket which is inside a scala controller of different project, is as under:

def sockeTest = WebSocket.tryAccept[JsValue] { request =>
  futureJsonVariable.map { json =>
    val in = Iteratee.ignore[JsValue]
    // Some database computation here which generated a Future[JsValue] value in futureJsonVariable variable.
    val out = Enumerator(json).andThen(Enumerator.eof)
    Right((in, out))
  } recover {
    case err => Left(InternalServerError(err.getMessage))
  }
}

Update2: One last thing I would like to ask regarding this is that, we invoke a WebSocket connection using webSocket.sendMessage("test".getBytes()) which gives us the response of WebSocket in the overridden method onMessage(). I want to know, how can we await until a WebSocket response is being received, so that we can perform the required computations with the WebSocket response data. I have checked by returning a Future[JsValue] variable inside the onMessage() method but that thing is something invalid. So how can we put webSocket.sendMessage("test".getBytes()) in await mode, so that further code is executed upon the response of WebSocket ?

Upvotes: 0

Views: 347

Answers (1)

James Roper
James Roper

Reputation: 12850

Play doesn't support WebSocket client connections. The best option is probably to use AsyncHttpClient, this is the library that Play's WS API is built on so it will already be on your classpath, instructions for accessing WebSockets using it are here:

https://github.com/AsyncHttpClient/async-http-client

Upvotes: 1

Related Questions