Thursday Apr 04, 2013

WebSocket Client and Server Endpoint: Annotated and Programmatic (TOTD #212)


JSR 356 defines Java API for WebSocket 1.0. It defines a standard-based programming model for creating WebSocket client and server endpoint. Both kind of endpoints can be created programmatically or using annotations. This Tip Of The Day (TOTD) provide short snippets of how to write a WebSocket client and server endpoint programmatically or using annotations.

The complete source code in this sample can be downloaded from here.

Lets start with annotation-based server endpoint.

@ServerEndpoint("/websocket")
public class MyEndpoint {
   
  @OnMessage
  public String echoText(String name) {
    return name;
  }
}

@ServerEndpoint marks the POJO as a WebSocket server endpoint. URI of the deployed endpoint is as value attribute of the annotation.  echoText method is invoked whenever a message with text payload is received by this endpoint. Payload of the message is mapped to the parameter name. A synchronous response is returned to the client using the return value.

Programmatic server endpoint can be defined as:

public class MyEndpoint extends Endpoint {

  @Override
  public void onOpen(final Session session, EndpointConfig ec) {
    session.addMessageHandler(new MessageHandler.Whole<String>() {

      @Override
      public void onMessage(String text) {
        try {
          session.getBasicRemote().sendText(text);
        } catch (IOException ex) {
          Logger.getLogger(MyEndpoint.class.getName()).log(Level.SEVERE, null, ex);
        }
      }
  });
}

A programmatic server endpoint is defined by extending Endpoint abstract class. onOpen method is overridden to be notified of when a new conversation has started. Session captures the other end of the conversation. EndpointConfig identifies the configuration object used to configure this endpoint. Multiple MessageHandlers are registered to handle text, binary, and pong messages. The first parameter of onOpen captures the other end of the conversation. A synchronous response to the client is sent by calling getBasicRemote().sendText(...) method.

Programmatic server endpoint needs to be configured using ServerApplicationConfig.

public class MyApplicationConfig implements ServerApplicationConfig {

  @Override
  public Set<ServerEndpointConfig> getEndpointConfigs(Set<Class<? extends Endpoint>> set) {
    return new HashSet<ServerEndpointConfig>() {
      {
        add(ServerEndpointConfig.Builder
            .create(MyEndpoint.class, "/websocket")
            .build());
      }
    };
  }

  @Override
  public Set<Class<?>> getAnnotatedEndpointClasses(Set<Class<?>> set) {
    return Collections.emptySet();
  }
}

WebSocket runtime scans the WAR file with all implementations of ServerApplicationConfig and registers the endpoint returned from getEndpointConfigs and getAnnotatedEndpointClasses. The URI of the server endpoint is published using ServerEndpointConfig.Builder.

Now lets take a look at annotated client endpoint.

@ClientEndpoint
public class MyClient {
  @OnOpen
  public void onOpen(Session session) {
    try {
      String name = "Duke";
      System.out.println("Sending message to endpoint: " + name);
      session.getBasicRemote().sendText(name);
    } catch (IOException ex) {
      Logger.getLogger(MyClient.class.getName()).log(Level.SEVERE, null, ex);
    }
  }
}

@ClientEndpoint marks the POJO as a WebSocket client endpoint. onOpen method is invoked whenever a new WebSocket connection is opened and is identified by @OnOpen annotation. Session captures the other end of the conversation. A synchronous message is sent to the server using session.getBasicRemote.sendText() method.

This client can connect to the endpoint as:

WebSocketContainer container = ContainerProvider.getWebSocketContainer();
String uri = "ws://localhost:8080" + request.getContextPath() + "/websocket";
container.connectToServer(MyClient.class, URI.create(uri));

And finally programmatic client endpoint.

public class MyClient extends Endpoint {
  @Override
  public void onOpen(final Session session, EndpointConfig ec) {
    session.addMessageHandler(new MessageHandler.Whole<String>() {

      @Override
      public void onMessage(String text) {
        System.out.println("Received response in client from endpoint: " + text);
      }
  });
  try {
    String name = "Duke";
      System.out.println("Sending message from client -> endpoint: " + name);
      session.getBasicRemote().sendText(name);
    } catch (IOException ex) {
      Logger.getLogger(MyClient.class.getName()).log(Level.SEVERE, null, ex);
    }
  }
}


The first parameter of onOpen captures the other end of the conversation.  EndpointConfig identifies the configuration object used to configure this endpoint. Multiple MessageHandlers are registered to handle text, binary, and pong messages. onMessage method is called whenever a message is received from the endpoint. A synchronous request to the server is sent by calling getBasicRemote().sendText(...) method.

This client can connect to the endpoint as:

WebSocketContainer container = ContainerProvider.getWebSocketContainer();
String uri = "ws://localhost:8080" + request.getContextPath() + "/websocket";
container.connectToServer(MyClient.class,
                null,
                URI.create(uri));

Now go download your GlassFish b82, samples source code, and run them.


About

profile image
Arun Gupta is a technology enthusiast, a passionate runner, author, and a community guy who works for Oracle Corp.


Java EE 7 Samples

Stay Connected

Search

Archives
« April 2013 »
SunMonTueWedThuFriSat
 
1
2
3
5
6
7
8
9
10
11
12
13
14
15
16
18
19
20
21
22
23
24
25
26
27
28
29
30
    
       
Today