Receiving Messages
From an API perspective, sending WebSocket messages is much simpler because of it's dependency on a simple construct i.e. javax.websocket.RemoteEndpoint
interface. For an understanding of how to receive messages, we need to take into account both annotated as well as programmatic styles
Annotated endpoints: it's all about passing the right type of parameters in the method annotated with
@OnMessage
Programmatic endpoints: implementation of the appropriate
javax.websocket.MessageHandler
(child) interface encapsulates the logic for receiving messages
Receive modes: a quick primer
Here is an overview of the options available when receiving messages
Mode
Description
Complete
The message is received in its entirety
Partial
This works in conjunction with the partial send capability. If the sender sends messages in chunks, the message is received in chunks. The receiver will get a true
boolean flag to notify it of the last message part
Streaming
Receive messages in form of Java Reader
s and InputStream
s
Receving messages can also end up with a lot of permutations and combinations (just like the send APIs). So here is what we'll do in order to help tackle that
Pick up a message type (thankfully there are just two of them - String and Binary!)
For each of the endpoint styles (Annotated and Programmatic), we will look at the possible receiving modes (as mentioned above)
Take a look at how Java objects and Pong messages are handled (separate sections)
Receiving text messages
Annotated endpoints
Receving text messages in annotated endpoints is all about having the appropriate method parameter type and the WebSocket runtime will automatically figure out the rest
Complete
Partial
Streaming
Programmatic endpoints
As mentioned earlier, Programmatic endpoints are inheritance based and thus need some more custom code to set them up as message receviers.
Complete
Partial
Streaming
Receiving binary messages
When it comes to binary messages, the pattern (for both annotated and programmatic endpoints) is the same (except for the data type of course!). Binary messages support is available in the form of byte[]
(array), java.nio.ByteBuffer
and java.io.InputStream
Annotated endpoints
Complete
Partial
Streaming
Programmatic endpoints
The concept remains the same apart from a change in the data types..
Complete
Partial
Streaming
Receiving text, binary messages as Java objects
Text and binary messages sent by a WebSocket peer can be received as Java objects within your message handling logic (annotated or programmatic).
But how would the on-wire format (text/binary) to Java object transformation take place ?
This is where Decoders come into the picture. An implementation of a javax.websocket.Decoder
provides the necessary logic to convert a message from it's on-wire format into it's Java representation.
WebSocket Decoders: the detailsDecoders are complementary to Encoders (which were discussed in the Sending Messages lesson). Take a look at the diagram below to visualize how they work at runtime
Transforming native data types (Text, Binary) into Java objects
A summary of Decoders and their types
Basic Decoder Type
Description
Decoder
The top level interface for different types of Decoders
Decoder.Text<T>
Defines how a custom Java object (of type T
) is produced from a text payload (java.lang.String
)
Decoder.Binary<T>
Defines how a custom Java object (of type T
) is produced from a binary payload (java.nio.ByteBuffer
)
A sample to demonstrate how a Decoder
which creates a Subscription
object from a String
Transforming Streaming inputs into Java objects
Native text and binary messages can be received as streams - as explained in the previous sections. Java objects can also be received in a streaming style
Streaming Decoder Type
Description
Decoder.TextStream<T>
Defines how a custom Java object (of type T
) is produced from a character stream (java.io.Reader
)
Decoder.BinaryStream<T>
Defines how a custom Java object (of type T
) is produced from a binary stream (java.io.InputStream
)
This example shows how you can handle data in a streaming form using a Reader
which creates a Conversation
object
Handling Pong
objects
Pong
objectsPong
messages were introduced in the API Overview chapter and were then discussed in the Sending Messages chapter as well. Receiving a health-check response message (a.k.a javax.websocket.Pong
) is possible in both annotated and programmatic endpoints. Here are the examples
Common notes
Using a MessageHandler
MessageHandler
There are two basic steps involved (common to Programmatic endpoints)
implement appropriate
MessageHandler
implementation based on data type and whole/partial messageattach that implementation using
Session#addMessageHandler
methods (multiple combinations available)
addMessageHandler
permutationsCouple of additional (overloaded)
addMessageHandler
methods were added to theSession
interface as a part of WebSocket 1.1 release. In fact this was the only (minor) change in the 1.1 MR (maintenance release). For details, please check the change log
Other possible parameters for @OnMessage
@OnMessage
In addition to the message itself, a method annotated with OnMessage
can also receive the following information (which will be injected by the implementation at runtime)
zero or more
String
parameters annotated with@javax.websocket.PathParam
(it is similar in spirit to the JAX-RS@javax.ws.rs.PathParam
annotation)an instance of
Session
an instance of
EndpointConfig
(server or client side)
Handling Java primitives
A WebSocket implementation provides default decoders for Java primitive (int-Integer, long-Long, double-Double etc.) data types. It is possible to write a custom decoder for any of these in order to override the default ones
Up next
We'll explore the WebSocket Client API in detail
Last updated