GeezerVison is showing javaee.github.io — Using Encoders and Decoders
Java Platform, Enterprise Edition (Java EE) 8
The Java EE Tutorial
|
Using Encoders and Decoders
The Java API for WebSocket provides support for converting between
WebSocket messages and custom Java types using encoders and decoders. An
encoder takes a Java object and produces a representation that can be
transmitted as a WebSocket message; for example, encoders typically
produce JSON, XML, or binary representations. A decoder performs the
reverse function; it reads a WebSocket message and creates a Java
object.
This mechanism simplifies WebSocket applications, because it decouples
the business logic from the serialization and deserialization of
objects.
The following topics are addressed here:
Implementing Encoders to Convert Java Objects into WebSocket Messages
The procedure to implement and use encoders in endpoints follows.
-
Implement one of the following interfaces:
-
Add the names of your encoder implementations to the encoders
optional parameter of the ServerEndpoint annotation.
-
Use the sendObject(Object data) method of the
RemoteEndpoint.Basic or RemoteEndpoint.Async interfaces to send your
objects as messages. The container looks for an encoder that matches
your type and uses it to convert the object to a WebSocket message.
For example, if you have two Java types (MessageA and MessageB) that
you want to send as text messages, implement the
Encoder.Text<MessageA> and Encoder.Text<MessageB> interfaces as
follows:
public class MessageATextEncoder implements Encoder.Text<MessageA> {
@Override
public void init(EndpointConfig ec) { }
@Override
public void destroy() { }
@Override
public String encode(MessageA msgA) throws EncodeException {
// Access msgA's properties and convert to JSON text...
return msgAJsonString;
}
}
Implement Encoder.Text<MessageB> similarly. Then, add the encoders
parameter to the ServerEndpoint annotation as follows:
@ServerEndpoint(
value = "/myendpoint",
encoders = { MessageATextEncoder.class, MessageBTextEncoder.class }
)
public class EncEndpoint { ... }
Now, you can send MessageA and MessageB objects as WebSocket
messages using the sendObject method as follows:
MessageA msgA = new MessageA(...);
MessageB msgB = new MessageB(...);
session.getBasicRemote.sendObject(msgA);
session.getBasicRemote.sendObject(msgB);
As in this example, you can have more than one encoder for text messages
and more than one encoder for binary messages. Like endpoints, encoder
instances are associated with one and only one WebSocket connection and
peer, so there is only one thread executing the code of an encoder
instance at any given time.
Implementing Decoders to Convert WebSocket Messages into Java Objects
The procedure to implement and use decoders in endpoints follows.
-
Implement one of the following interfaces:
-
Add the names of your decoder implementations to the decoders
optional parameter of the ServerEndpoint annotation.
-
Use the OnMessage annotation in the endpoint to designate a method
that takes your custom Java type as a parameter. When the endpoint
receives a message that can be decoded by one of the decoders you
specified, the container calls the method annotated with @OnMessage
that takes your custom Java type as a parameter if this method exists.
For example, if you have two Java types (MessageA and MessageB) that
you want to send and receive as text messages, define them so that they
extend a common class (Message). Because you can only define one
decoder for text messages, implement a decoder for the Message class
as follows:
public class MessageTextDecoder implements Decoder.Text<Message> {
@Override
public void init(EndpointConfig ec) { }
@Override
public void destroy() { }
@Override
public Message decode(String string) throws DecodeException {
// Read message...
if ( /* message is an A message */ )
return new MessageA(...);
else if ( /* message is a B message */ )
return new MessageB(...);
}
@Override
public boolean willDecode(String string) {
// Determine if the message can be converted into either a
// MessageA object or a MessageB object...
return canDecode;
}
}
Then, add the decoder parameter to the ServerEndpoint annotation as
follows:
@ServerEndpoint(
value = "/myendpoint",
encoders = { MessageATextEncoder.class, MessageBTextEncoder.class },
decoders = { MessageTextDecoder.class }
)
public class EncDecEndpoint { ... }
Now, define a method in the endpoint class that receives MessageA and
MessageB objects as follows:
@OnMessage
public void message(Session session, Message msg) {
if (msg instanceof MessageA) {
// We received a MessageA object...
} else if (msg instanceof MessageB) {
// We received a MessageB object...
}
}
Like endpoints, decoder instances are associated with one and only one
WebSocket connection and peer, so there is only one thread executing the
code of a decoder instance at any given time.
Copyright © 2017, Oracle and/or its affiliates. All rights reserved.
|