Websockets in Play 2.0
Join the DZone community and get the full member experience.
Join For FreeThe source code for this guide can be found in the github repository.
Websockets allow full-duplex communication over a TCP socket, normally between a browser and a server-side application. In a similar vein to this post on websockets in Play 1.x, this article shows how to create a websockets-enabled application in Play 2.0.
Remember that Play 2.0 is still in beta, so the APIs shown below are
subject to change. If that happens, I’ll endeavour to update this
article with the changes.
Obtaining Play 2.0
I encountered an issue with the packaged beta, so I downloaded the Play source (full instructions):
git clone --depth=1 https://github.com/playframework/Play20.git cd Play20/framework ./build
While it builds, you’ll probably want to get some coffee. Then, at the sbt prompt:
publish-local
Now, create the project:
./play new websocks2
You can run the eclipsify command (or equivalent) if you want to open the project in your IDE.
Creating the Websockets Controller
With setup done, let’s define the controller that will serve our index page and establish a websocket with the client. Open controllers/Application.java and add the following code:
package controllers; import play.*; import play.mvc.*; import views.html.*; public class Application extends Controller { public static Result index() { return ok(index.render()); } public static WebSocket<String> sockHandler() { return new WebSocket<String>() { // called when the websocket is established public void onReady(WebSocket.In<String> in, WebSocket.Out<String> out) { // register a callback for processing instream events in.onMessage(new Callback<String>() { public void invoke(String event) { Logger.info(event); } }); // write out a greeting out.write("I'm contacting you regarding your recent websocket."); } }; } }
As you can see, alongside the pre-generated code, we’ve added a static method sockHandler that returns a websocket. The inner onReady method takes two arguments: the in channel and out channel.
At this point, we could pass those channels to a model which retains
them. But for this example, we simply register a logger for inbound
messages, and write a greeting message to the out socket.
Routing the Websocket Connection
Next, we need to add a route to our websocket connection. In conf/routes, add the following:
# Routes # This file defines all application routes (Higher priority routes first) # ~~~~ # Home page GET / controllers.Application.index() GET /greeter controllers.Application.sockHandler() # Map static resources from the /public folder to the /assets URL path GET /assets/*file controllers.Assets.at(path="/public", file)
We don’t actually request /greeter explicitly; instead, we’ll use a reverse generated URL in our template.
Adding the Template
Now that we have our controller and route in place, we can specify the client-side code for our websocket.
@main(null) { <div class="greeting"></div> <button class="send">Send</button> <script type="text/javascript" charset="utf-8"> $(function() { var WS = window['MozWebSocket'] ? MozWebSocket : WebSocket var sock = new WS("@routes.Application.sockHandler().webSocketURL(request)") sock.onmessage = function(event) { $('.greeting').append(event.data) } $('button.send').click(function() { sock.send("I'm sending a message now.") }); }) </script> }
Here, we declare a greeting which is populated when the
websocket receives a message. We also register a button action to send a
message to the server, so we can demonstrate bi-directional messaging.
If you’re familiar with Play 1.x, you’ll notice that the templating is a
little different.
Now, when we start the app, we see the following.
Clicking the Send button generates the following log line:
[info] application - I'm sending a message now.
Conclusion
So, that’s all that needs to be done to create a websocket-enabled application in Play. We’ve both sent messages from, and to, the browser with simple code on both client and server side. In a real application, we would probably pass the in and out streams to a model, but it should be straightforward to see how this is done from the example.
For further information, you can look at the examples, particularly the websocket chat app, upon which this guide is based. In a future post I’d like to go into more detail by looking at the Akka actor model implementation, which is used in the chat application sample.
This article comes with a small disclaimer – Play is still a new
framework to me, so some of the above code may not demonstrate best
practice (although I did attempt to follow the sample application
closely). If you notice anything that could be improved, let me know and
I’ll update accordingly.
Source: http://blueprintforge.com/blog/2012/02/13/websockets-in-play-2-dot-0/
Opinions expressed by DZone contributors are their own.
Comments