When the WebSocket is closed, Play automatically stops the actor bound to it. This binding works in two ways: the WebSocket connection is closed when the underlying actor is killed. If there is a need to free any resources once the connection is closed, we can do so by overriding the actor's postStop
method. In our example, we have initialized a DBActor within WebSocketChannel
. We will need to ensure that it's killed once the WebSocket is closed, since each connection to the WebSocket will lead to the initialization of a DBActor. We can do so by sending it a poison pill, as shown here:
override def postStop() = { backend ! PoisonPill }
Suppose that an incoming JSON has the same fields for every request, instead of parsing it every time; we can define an equivalent class in this way:
case class WebsocketRequest(reqType:String, message:String)
Now, we can define our WebSocket to translate the JSON message to a WebSocketRequest
automatically. This is possible by specifying the data type for the acceptWithActor
method:
def websocketFormatted = WebSocket.acceptWithActor[WebsocketRequest, JsValue]{ request => out => SomeActor.props(out) }
However, for this to work as expected, we need two implicit values. The first is for translating incoming frames to WebsocketRequest
, which requires a JsValue
to the WebSocketRequest
formatter:
implicit val requestFormat = Json.format[WebsocketRequest] implicit val requestFrameFormatter = FrameFormatter.jsonFrame[WebsocketRequest]
Similarly, we can specify the types of the outgoing messages as well:
FrameFormatter
is a helper and can convert org.jboss.netty.handler.codec.http.websocketx.WebSocketFrame
to play.core.server.websocket.Frames
.
3.143.254.151