X

WebSocket Java Client API in GlassFish 4 (TOTD #208)

Guest Author


The WebSocket API by
W3C defines an API that enables Web pages to use the WebSocket
protocol for two-way communication with a remote host. Java API for
WebSocket (JSR 356)
has added an ability to invoke a WebSocket endpoint from a Java
application. This Tip Of The Day
(TOTD) will explain how you can use that API for invoking a
WebSocket endpoint.



JSR 356 introduces a class-level annotation @WebSocketClient
that converts a POJO into a WebSocket client. The usual lifecycle
annotations such as @WebSocketOpen, @WebSocketClose,
@WebSocketError, and @WebSocketMessage
can be specified on methods.


@WebSocketClient
public class MyClientEndpoint {
@WebSocketOpen
public void onOpen(Session session) {
System.out.println("Connected to endpoint: " + session.getRemote());
try {
String name = "Duke";
System.out.println("Sending message to endpoint: " + name);
session.getRemote().sendString(name);
} catch (IOException ex) {
Logger.getLogger(MyClientEndpoint.class.getName()).log(Level.SEVERE, null, ex);
}
}

@WebSocketMessage
public void processMessage(String message) {
System.out.println("Received message in client: " + message);
Client.messageLatch.countDown();
}
}

This code sends a message to the connected WebSocket endpoint from
the onOpen method and prints the message when it comes
back. This endpoint is bootstrapped using a separate class:

public class Client {

final static CountDownLatch messageLatch = new CountDownLatch(1);

public static void main(String[] args) {
try {
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
String uri = "ws://echo.websocket.org:80/";
System.out.println("Connecting to " + uri);
container.connectToServer(MyClientEndpoint.class, URI.create(uri));
messageLatch.await(100, TimeUnit.SECONDS);
} catch (DeploymentException | InterruptedException ex) {
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
}
}
}

Note that a CountDownLatch is used to ensure that
there is enough time for the client to connect to the endpoint. The
latch counts down in MyClientEndpoint.processMessage
once the echo message is received from the endpoint.



The source code can be href="//cdn.app.compendium.com/uploads/user/e7c690e8-6ff9-102a-ac6d-e4aebca50425/f4a5b21d-66fa-4885-92bf-c4e81c06d916/File/c597f665d0806c5679cbbd8a54718182/totd208_javase_client.zip">downloaded
here, connects to a remote WebSocket endpoint, and displays
the output on the console.



The Maven dependency for now are specified as:
<dependencies>
<dependency>
<groupId>org.glassfish.tyrus</groupId>
<artifactId>tyrus-client</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.glassfish.tyrus</groupId>
<artifactId>tyrus-container-grizzly</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>


Hopefully these could be specified as javax
dependencies only!



The latest specification draft and javadocs can be href="http://java.net/projects/websocket-spec/downloads/directory/Spec%20javadoc%20Drafts/v013">downloaded
here. Share your feedback at href="http://java.net/projects/websocket-spec/lists/users/archive">users@websocket-spec.java.net
(for the specification) or href="http://java.net/projects/tyrus/lists/users/archive">users@tyrus.java.net
(for the implenentation).


Join the discussion

Comments ( 5 )
  • craig Friday, May 24, 2013

    Using something like Apache Apollo, how might you connect via WebSocket and publish a message to channel/topic such that a JavaScript client will see the message?

    Typically what I see is a JavaScript client connects to the WebSocket server (such as Apollo) and then "subscribes" to a destination, such as a topic on Apollo.

    In the example you've provided it looks like a message it published to a WebSocket server but no particular destination, is that correct?


  • craig Friday, May 24, 2013

    ignore my last comment...not sure how I got so confused :) I don't need to connect via WebSocket, I just created a normal MessageProducer and dropped the message on the topic, duh! :)


  • manu Tuesday, June 11, 2013

    Hello,

    I'm trying to use websockets in my Java EE application. I can send messages from the client and echo them from the server but I don't know how to send custom notification messages from the server, based on certain events. Say, notify the client when a job is done.

    On the client side it's simple:

    String uri = "ws://localhost:8080" + request.getContextPath() + "/websocket";

    Session s = container.connectToServer(MyClient.class, null, uri);

    s.getBasicRemote().sendText("message from client");

    How could I do this on the server side ?

    Thanks


  • Arun Gupta Sunday, June 16, 2013

    Take a look at https://blogs.oracle.com/arungupta/entry/collaborative_whiteboard_using_websocket_in for more detailed sample of server-side interaction. Basically, you'll identify your business message on the server-side to respond back and tag it with @OnMessage.


  • manu Thursday, June 20, 2013

    Hello again,

    Thank you for your answer. Eventually I managed to do what I wanted.

    However I had some problems with the websocket initialization which look like a bug.

    session = container.connectToServer(ClientEndpoint.class, null, uri);

    session.getBasicRemote().sendText("hello");

    The API specification states about the connectToServer method: "This method blocks until the connection is established, or throws an error if the connection could not be made."

    I guess it doesn't actually always block until connection is properly established as I got lots of <RuntimeException: socket is closed> errors when sending that text message.

    A Thread.yield() call after the connectToServer line (hint from a professor of mine) solved the problem, which supports the idea above.

    Cheers


Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.