Collaborative Whiteboard using WebSocket in GlassFish 4 - Text/JSON and Binary/ArrayBuffer Data Transfer (TOTD #189)
Posted
by arungupta
on Oracle Blogs
See other posts from Oracle Blogs
or by arungupta
Published on Thu, 29 Nov 2012 23:49:05 +0000
Indexed on
2012/11/30
5:18 UTC
Read the original article
Hit count: 240
/General
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
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:
{The endpoint definition looks like:
"shape": "square",
"color": "#FF0000",
"coords": {
"x": 31.59999942779541,
"y": 49.91999053955078
}
}
@WebSocketEndpoint(value = "websocket",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:
encoders = {FigureDecoderEncoder.class},
decoders = {FigureDecoderEncoder.class})
public class Whiteboard {
public Figure decode(String string) throws DecodeException {And the encode method looks like:
try {
JSONObject jsonObject = new JSONObject(string);
return new Figure(jsonObject);
} catch (JSONException ex) {
throw new DecodeException("Error parsing JSON", ex.getMessage(), ex.fillInStackTrace());
}
}
public String encode(Figure figure) throws EncodeException {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.
return figure.getJson().toString();
}
On the client-side, the Canvas is initialized as:
var canvas = document.getElementById("myCanvas");The
var context = canvas.getContext("2d");
canvas.addEventListener("click", defineImage, false);
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";The important part is to set the
var websocket = new WebSocket(wsUri);
websocket.binaryType = "arraybuffer";
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);This comprehensive sample shows the following features of JSR 356 API:
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);
- 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!
- JSR 356: Java API for WebSocket - Specification (Early Draft) and Implementation (already integrated in GlassFish 4 promoted builds)
- Error handling
- Interface-driven WebSocket endpoint
- Java client API
- Client and Server configuration
- Security
- Subprotocols
- Extensions
- Other topics from the API
© Oracle Blogs or respective owner