Processing Text and Binary (Blob, ArrayBuffer, ArrayBufferView) Payload in WebSocket - (TOTD #185)

Posted by arungupta on Oracle Blogs See other posts from Oracle Blogs or by arungupta
Published on Mon, 12 Nov 2012 07:00:00 +0000 Indexed on 2012/11/12 11:10 UTC
Read the original article Hit count: 210

Filed under:

The WebSocket API defines different send(xxx) methods that can be used to send text and binary data. This Tip Of The Day (TOTD) will show how to send and receive text and binary data using WebSocket.

TOTD #183 explains how to get started with a WebSocket endpoint using GlassFish 4. A simple endpoint from that blog looks like:
@WebSocketEndpoint("/endpoint")
public class MyEndpoint {
public void receiveTextMessage(String message) {
. . .
}
}
A message with the first parameter of the type String is invoked when a text payload is received. The payload of the incoming WebSocket frame is mapped to this first parameter.

An optional second parameter, Session, can be specified to map to the "other end" of this conversation. For example:
public void receiveTextMessage(String message, Session session) {
    . . .
}
The return type is void and that means no response is returned to the client that invoked this endpoint. A response may be returned to the client in two different ways. First, set the return type to the expected type, such as:
public String receiveTextMessage(String message) {
String response = . . .
. . .
return response; }
In this case a text payload is returned back to the invoking endpoint.

The second way to send a response back is to use the mapped session to send response using one of the sendXXX methods in Session, when and if needed.
public void receiveTextMessage(String message, Session session) {
    . . .
    RemoteEndpoint remote = session.getRemote();
    remote.sendString(...);
    . . .
    remote.sendString(...);
   . . .
   remote.sendString(...);
}
This shows how duplex and asynchronous communication between the two endpoints can be achieved. This can be used to define different message exchange patterns between the client and server.

The WebSocket client can send the message as:
websocket.send(myTextField.value);
where myTextField is a text field in the web page.

Binary payload in the incoming WebSocket frame can be received if ByteBuffer is used as the first parameter of the method signature. The endpoint method signature in that case would look like:
public void receiveBinaryMessage(ByteBuffer message) {
    . . .
}
From the client side, the binary data can be sent using Blob, ArrayBuffer, and ArrayBufferView. Blob is a just raw data and the actual interpretation is left to the application. ArrayBuffer and ArrayBufferView are defined in the TypedArray specification and are designed to send binary data using WebSocket. In short, ArrayBuffer is a fixed-length binary buffer with no format and no mechanism for accessing its contents. These buffers are manipulated using one of the views defined by one of the subclasses of ArrayBufferView listed below:
  • Int8Array (signed 8-bit integer or char)
  • Uint8Array (unsigned 8-bit integer or unsigned char)
  • Int16Array (signed 16-bit integer or short)
  • Uint16Array (unsigned 16-bit integer or unsigned short)
  • Int32Array (signed 32-bit integer or int)
  • Uint32Array (unsigned 16-bit integer or unsigned int)
  • Float32Array (signed 32-bit float or float)
  • Float64Array (signed 64-bit float or double)
WebSocket can send binary data using ArrayBuffer with a view defined by a subclass of ArrayBufferView or a subclass of ArrayBufferView itself.

The WebSocket client can send the message using Blob as:

blob = new Blob([myField2.value]);
websocket.send(blob);

where myField2 is a text field in the web page.

The WebSocket client can send the message using ArrayBuffer as:

var buffer = new ArrayBuffer(10);
var bytes = new Uint8Array(buffer);
for (var i=0; i<bytes.length; i++) {
bytes[i] = i;
}
websocket.send(buffer);
A concrete implementation of receiving the binary message may look like:

@WebSocketMessage
public void echoBinary(ByteBuffer data, Session session) throws IOException {
    System.out.println("echoBinary: " + data);
    for (byte b : data.array()) {
        System.out.print(b);
    }
    session.getRemote().sendBytes(data);
}

This method is just printing the binary data for verification but you may actually be storing it in a database or converting to an image or something more meaningful.

Be aware of TYRUS-51 if you are trying to send binary data from server to client using method return type.

Here are some references for you:
Subsequent blogs will discuss the following topics (not necessary in that order) ...
  • Error handling
  • Custom payloads using encoder/decoder
  • Interface-driven WebSocket endpoint
  • Java client API
  • Client and Server configuration
  • Security
  • Subprotocols
  • Extensions
  • Other topics from the API

© Oracle Blogs or respective owner

Related posts about /General