WebSocket Client API
As discussed in the API Overview chapter, WebSocket has the notion of server and client components. Everything we have seen so far in the previous chapters is applicable to both these aspects. A WebSocket client endpoint
  • implements some business logic (just like it's server side counterpart)
  • connects to existing WebSocket (server) endpoints
In this lesson, we will look at some of the specifics of the Client API and explore topics like
  • Developing annotated and programmatic endpoints
  • Different ways of using them to connect to existing WebSocket server endpoints (they are different for annotated and programmatic client endpoints)

Annotated clients

The code for annotated client endpoints is not very different from their server side counterparts.
Notice the usage of the @ClientEndpoint annotation
//annotated client endpoint in action
@ClientEndpoint
public class AnnotatedChatClient {
private ClientEndpointConfig clientConfig;
private String user;
@OnOpen
public void connected(Session session, EndpointConfig clientConfig){
this.clientConfig = (ClientEndpointConfig) clientConfig;
this.user = session.getUserPrincipal().getName();
System.out.println("User " + user + " connected to Chat room");
}
@OnMessage
public void connected(String msg){
System.out.println("Message from chat server: " + msg);
}
@OnClose
public void disconnected(Session session, CloseReason reason){
System.out.println("User "+ user + " disconnected as a result of "+ reason.getReasonPhrase());
}
@OnError
public void disconnected(Session session, Throwable error){
System.out.println("Error communicating with server: " + error.getMessage());
}
}

Programmatic clients

Again, not much of a difference here - extending the java.websocket.Endpoint class is required to implement a programmatic client
//a bare bone implementation of a programmatic endpoint
public class WeatherClient extends Endpoint {
private Session session;
@Override
public void onOpen(Session session, EndpointConfig config) {
this.session = session;
try {
//sends back the session ID to the peer
this.session.getBasicRemote().sendText("Session ID: " + this.session.getId());
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
}
Understanding the nuances
At first glance, the WebSocket Client API might seem a little odd. Think about other client libraries e.g. a HTTP client, REST client, a custom client for some server side component - their underlying concept is to invoke operations on the component they are connecting to (mostly a server side component). In the case of the Java WebSocket Client API, its slighlty different
  • Business logic is implemented in the form of callback method implementation (annotated client) or overriding methods of a superclass (programmatic client)
  • The connectivity logic is invoked separately (more on this in the next section)
It's important to bear this in mind and align the mental model while working with the client API

Using the Client API to connect to a server endpoint

Looking at the above code samples, its not too hard to figure out that the client API implementation is almost exactly the same as server side endpoints. We write the business logic which gets invoked once the client interacts with the server - before that, it needs to connect with one
In order to initiate a connection to a server endpoint using the WebSocket client API, use the methods available in the javax.websocket.WebSocketContainer. They take the form of overloaded methods - table below provides a summary
Endpoint type
Method
Notes
Annotated
connectToServer(Class<?> annotatedEndpointClass, URI path)
--
Annotated
connectToServer(Object annotatedEndpointInstance, URI path)
no injection support
Programmatic
connectToServer(Class<? extends Endpoint> endpointClass, ClientEndpointConfig cec, URI path)
--
Programmatic
connectToServer(Endpoint endpointInstance, ClientEndpointConfig cec, URI path)
no injection support

Connecting annotated client endpoints

Option 1: Using the class type
WebSockerContainer.connectToServer(AnnotatedChatClient.class,
URI.create("ws://javaee-chat.com"));
Option 2: Using a concrete instance of the client endpoint implementation
WebSockerContainer.connectToServer(new AnnotatedChatClient(),
URI.create("ws://javaee-chat.com"));
The caveat - if the above client code is executed within a JavaEE container, it will not be able to enjoy dependency injection support. More details on this in the Tying in with Java EE Platform chapter

Connecting programmatic client endpoints

Programmatic client endpoints follow the same strategy as their annotated counterparts except for the fact the method requires a ClientEndpointConfig
Client side Configuration has been discussed in depth in the Configuration lesson. For now its just enough to know this fact and understand the samples below
Option 1: Using the class type
WebSockerContainer.connectToServer(WeatherClient.class,
ClientEndpointConfig.Builder.create().build(), //fluent API
URI.create("ws://weather-tracker.com"));
Option 2: Using a concrete instance of the client endpoint implementation
WebSockerContainer.connectToServer(new WeatherClient(),
ClientEndpointConfig.Builder.create().build(), //fluent API
URI.create("ws://weather-tracker.com"));
The caveat - if this client is executed within a JavaEE container, it will not be able to enjoy dependency injection support. More in the Tying in with the Java EE Platform chapter

Client side Configurator

Client side configurators help enapsulate some come common logic across all instances of a client - specifically around intercepting the opening handshake with a server side enpoint. This section just serves as a pointer to the detailed discussion of this topics which is more relevant to the Configurattion chapter

Up next

We will explore how to configure Server and Client side WebSocket endpoints
Copy link
On this page
Annotated clients
Programmatic clients
Using the Client API to connect to a server endpoint
Connecting annotated client endpoints
Connecting programmatic client endpoints
Client side Configurator
Up next