Encoders and decoders

Java WebSocket has the capability to interpret message types beyond the standard java.lang.String. The way it works is through the registration of encoders and decoders on the endpoint.

Let's review our chat server application again. Instead of using hard corded String on the Java, for the actual commands we can elect to use Java enumerations. This is the replacement code:

public enum ChatCommand {
  LOGIN("Login"), LOGOUT("Logout"), SEND("Send"),
  RECEIVE("Receive"), UPDATE("Update");

  private String text;

  ChatCommand( String text) { this.text = text; }

  public static ChatCommand convert( String str) {
    if ( str != null ) {
      for ( ChatCommand item: values() ) {
        if (item.text.equalsIgnoreCase(str)) {
          return item;
        }
      }
    }
    return null;
  }

public String asText() { return text; }
}

The ChatCommand is a Java enum that accepts a text parameter that corresponds to the JavaScript/HTML5 front end. The method convert() attempts to parse a case insensitive string in a ChatCommand. The method asText() returns the text. We use both of these methods in the encoder and decoder types.

We now require a new server endpoint with the registration of encoders and decoders:

@ServerEndpoint(value="/chatserver",
    encoders = ChatCommandEncoder.class,
    decoders = ChatCommandDecoder.class)
public class ChatServerEndpoint {
  /* ... */
}

The new ChatServerEndpoint now informs the WebSocket container so that it accepts two types: ChatCommandEncoder and ChatCommandDecoder. What do these types actually look like? Actually they are sub interface implementations of the javax.websocket.Encoder and javax.websocket.Decoder. The sub interface Encoder.Text is used for String text representations. Here is the starting implementation for an encoder:

import javax.websocket.*;

public class ChatCommandEncoder 
implements Encoder.Text<ChatCommand> {
  @Override
  public String encode(ChatCommand cmd) {
    return cmd.asText();
  }

  @Override
  public void init(EndpointConfig config) { }

  @Override
  public void destroy() { }
}

The ChatCommandEncoder is a generic sub type of Encoder.Text interface and the most important method is encode(), which simply encodes the Java enumeration as a text String. The function for the encoder is to translate the Java type to the WebSocket message type.

An encoder init()is called from the WebSocket container when the web application starts up. The EndpointConfig allows advanced developer to customize the encoder's behavior around the configuration. The container will also call the encoder's destroy() method when the web application gracefully shuts down.

Let's inspect the decoder implementation, which is relatively straightforward too:

import javax.websocket.*;

public class ChatCommandDecoder
  implements Decoder.Text<ChatCommand> {
  @Override
  public ChatCommand decode(String s) throws DecodeException {
    ChatCommand value = ChatCommand.convert(s);
    if ( value == null)
      throw new DecodeException(s, "Cannot decode text");
    return value;
  }

  @Override
  public boolean willDecode(String s) {
    return ChatCommand.convert(s) != null;
  }

  @Override
  public void init(EndpointConfig config) { }

  @Override
  public void destroy() { }
}

The ChatCommandDecoder is a type of generic sub interface of Decoder.Text. The method willDecode() allows the Java WebSocket container to find out if String can be converted. Here we make use the ChatCommand.convert() method from earlier. The decode() method performs the parsing of the input text. If the String cannot be converted, we throw a DecodeException, rather than just returning a null reference pointer. Finally, the Decoder types have the same life-cycle methods.

So far we have seen text message based encoders and decoders. There are other types available in Java WebSocket:

  • The sub interfaces Encoder.TextStream and Decoder.TextStream are designed for sending and receiving Java objects to a character stream.
  • The sub interfaces Encoder.Binary and Decoder.Binary are designed for serializing and de-serializing Java objects to and from binary messages.
  • The sub interfaces Encoder.BinaryStream and Decoder.BinaryStream are designed for writing and reading Java objects to a binary stream.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.137.183.210