This blog has published a few blogs on using JSR 356 Reference
Implementation (Tyrus) as its integrated in GlassFish 4
promoted builds.
TOTD
#183: Getting Started with WebSocket in GlassFish
TOTD
#184: Logging WebSocket Frames using Chrome Developer
Tools, Net-internals and Wireshark
TOTD
#185: Processing Text and Binary (Blob, ArrayBuffer,
ArrayBufferView) Payload in WebSocket
TOTD
#186: Custom Text and Binary Payloads using WebSocket
One of the typical usecase for WebSocket is online collaborative
games. This Tip Of The Day (TOTD)
explains a sample that can be used to build such games easily.
The application is a collaborative whiteboard where different shapes
can be drawn in multiple colors. The shapes drawn on one browser are
automatically drawn on all other peer browsers that are connected to
the same endpoint. The shape, color, and coordinates of the image
are transfered using a JSON structure. A browser may opt-out of
sharing the figures. Alternatively any browser can send a snapshot
of their existing whiteboard to all other browsers. Take a look at
this video to understand how the application work and the underlying
code.
The complete sample code can be downloaded
here.
The code behind the application is also explained below.
The web page (index.jsp) has a HTML5
Canvas as shown:
<canvas id="myCanvas" width="150" height="150" style="border:1px solid #000000;"></canvas>
And some radio buttons to choose the color and shape. By default,
the shape, color, and coordinates of any figure drawn on the canvas
are put in a JSON structure and sent as a message to the WebSocket
endpoint. The JSON structure looks like:
{ "shape": "square", "color": "#FF0000", "coords": { "x": 31.59999942779541, "y": 49.91999053955078 }}
The endpoint definition looks like:
@WebSocketEndpoint(value = "websocket",encoders = {FigureDecoderEncoder.class},decoders = {FigureDecoderEncoder.class})public class Whiteboard {
As you can see, the endpoint has decoder and encoder registered that
decodes JSON to a Figure (a POJO class) and vice versa respectively.
The decode method looks like:
public Figure decode(String string) throws DecodeException { try { JSONObject jsonObject = new JSONObject(string); return new Figure(jsonObject); } catch (JSONException ex) { throw new DecodeException("Error parsing JSON", ex.getMessage(), ex.fillInStackTrace()); }}
And the encode method looks like:
public String encode(Figure figure) throws EncodeException { return figure.getJson().toString();}
FigureDecoderEncoder implements both decoder and encoder
functionality but thats purely for convenience. But the recommended
design pattern is to keep them in separate classes. In certain
cases, you may even need only one of them.
On the client-side, the Canvas is initialized as:
var canvas = document.getElementById("myCanvas");var context = canvas.getContext("2d");canvas.addEventListener("click", defineImage, false);
The defineImage method constructs the JSON structure
as shown above and sends it to the endpoint using websocket.send().
An instant snapshot of the canvas is sent using binary transfer with
WebSocket. The WebSocket is initialized as:
var wsUri = "ws://localhost:8080/whiteboard/websocket";var websocket = new WebSocket(wsUri);websocket.binaryType = "arraybuffer";
The important part is to set the binaryType property
of WebSocket to arraybuffer. This ensures that any
binary transfers using WebSocket are done using ArrayBuffer
as the default type seem to be blob. The actual binary
data transfer is done using the following:
var image = context.getImageData(0, 0, canvas.width, canvas.height);var buffer = new ArrayBuffer(image.data.length);var bytes = new Uint8Array(buffer);for (var i=0; i<bytes.length; i++) { bytes[i] = image.data[i];}websocket.send(bytes);
This comprehensive sample shows the following features of JSR 356
API:
Annotation-driven endpoints
Send/receive text and binary payload in WebSocket
Encoders/decoders for custom text payload
In addition, it also shows how images can be captured and drawn
using HTML5 Canvas in a JSP.
How could this be turned in to an online game ? Imagine drawing a
Tic-tac-toe
board on the canvas with two players playing and others watching.
Then you can build access rights and controls within the
application itself. Instead of sending a snapshot of the canvas on
demand, a new peer joining the game could be automatically
transferred the current state as well. Do you want to build this
game ?
I built a similar game a
few years ago. Do somebody want to rewrite the game using
WebSocket APIs ? :-)
Many thanks to Jitu
and Akshay for helping
through the WebSocket internals!
Here are some references for you:
JSR 356:
Java API for WebSocket - Specification (Early
Draft) and Implementation
(already integrated in GlassFish
4 promoted builds)
Subsequent blogs will discuss the following topics (not necessary in
that order) ...
Error handling
Interface-driven WebSocket endpoint
Java client API
Client and Server configuration
Security
Subprotocols
Extensions
Other topics from the API