type=page
status=published
title=Using Encoders and Decoders
next=websocket008.html
prev=websocket006.html
~~~~~~
Using Encoders and Decoders
===========================

[[BABGADFG]]

[[using-encoders-and-decoders]]
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:

* link:#CIHBIGBI[Implementing Encoders to Convert Java Objects into
WebSocket Messages]
* link:#CIHGDJFG[Implementing Decoders to Convert WebSocket Messages
into Java Objects]

[[CIHBIGBI]]

[[implementing-encoders-to-convert-java-objects-into-websocket-messages]]
Implementing Encoders to Convert Java Objects into WebSocket Messages
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The procedure to implement and use encoders in endpoints follows.

1.  Implement one of the following interfaces:
* `Encoder.Text<T>` for text messages
* `Encoder.Binary<T>` for binary messages
+
These interfaces specify the `encode` method. Implement an encoder class
for each custom Java type that you want to send as a WebSocket message.
2.  Add the names of your encoder implementations to the `encoders`
optional parameter of the `ServerEndpoint` annotation.
3.  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:

[source,oac_no_warn]
----
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:

[source,oac_no_warn]
----
@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:

[source,oac_no_warn]
----
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.

[[CIHGDJFG]]

[[implementing-decoders-to-convert-websocket-messages-into-java-objects]]
Implementing Decoders to Convert WebSocket Messages into Java Objects
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The procedure to implement and use decoders in endpoints follows.

1.  Implement one of the following interfaces:
* `Decoder.Text<T>` for text messages
* `Decoder.Binary<T>` for binary messages
+
These interfaces specify the `willDecode` and `decode` methods.
+

[width="100%",cols="100%",]
|=======================================================================
a|
Note:

Unlike with encoders, you can specify at most one decoder for binary
messages and one decoder for text messages.

|=======================================================================

2.  Add the names of your decoder implementations to the `decoders`
optional parameter of the `ServerEndpoint` annotation.
3.  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:

[source,oac_no_warn]
----
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:

[source,oac_no_warn]
----
@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:

[source,oac_no_warn]
----
@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.


