X

WebSocket Applications using Java: JSR 356 Early Draft Now Available (TOTD #183)

Guest Author


WebSocket provide a full-duplex and bi-directional communication
protocol over a single TCP connection. href="http://jcp.org/en/jsr/detail?id=356">JSR 356 is defining
a standard API for creating WebSocket applications in the Java EE 7
Platform. This Tip Of The Day (TOTD)
will provide an introduction to WebSocket and how the JSR is
evolving to support the programming model.



First, a little primer on WebSocket!



WebSocket is a combination of href="http://tools.ietf.org/html/rfc6455">IETF RFC 6455 Protocol
and W3C JavaScript API
(still a Candidate Recommendation). The protocol defines an opening
handshake and data transfer. The API enables Web pages to use the
WebSocket protocol for two-way communication with the remote host.



Unlike HTTP, there is no need to create a new TCP connection and
send a chock-full of headers for every message exchange between
client and server. The WebSocket protocol defines basic message
framing, layered over TCP. Once the initial handshake happens using
href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.42">HTTP
Upgrade, the client and server can send messages to each
other, independent from the other. There are no pre-defined message
exchange patterns of request/response or one-way between client and
and server. These need to be explicitly defined over the basic
protocol.



The communication between client and server is pretty symmetric but
there are two differences:
  • A client initiates a connection to a server that is listening
    for a WebSocket request.
  • A client connects to one server using a URI. A server may
    listen to requests from multiple clients on the same URI.

Other than these two difference, the client and server behave
symmetrically after the opening handshake. In that sense, they are
considered as "peers".


After a successful handshake, clients and servers transfer data back
and forth in conceptual units referred as "messages". On the wire, a
message is composed of one or more frames. Application frames carry
payload intended for the application and can be text or binary data.
Control frames carry data intended for protocol-level signaling.



Now lets talk about the JSR!



The Java API for
WebSocket
is worked upon as href="http://www.jcp.org/en/jsr/detail?id=356">JSR 356 in the
Java Community Process. This will define a standard API for building
WebSocket applications. This JSR will provide support for:
  • Creating WebSocket Java components to handle bi-directional
    WebSocket conversations
  • Initiating and intercepting WebSocket events
  • Creation and consumption of WebSocket text and binary messages
  • The ability to define WebSocket protocols and content models
    for an application
  • Configuration and management of WebSocket sessions, like
    timeouts, retries, cookies, connection pooling
  • Specification of how WebSocket application will work within
    the Java EE security model


Tyrus is the Reference
Implementation for JSR 356 and is already integrated in href="http://dlc.sun.com.edgesuite.net/glassfish/4.0/promoted/">GlassFish
4.0 Promoted Builds.



And finally some code!



The API allows to create WebSocket endpoints using annotations and
interface. This TOTD will show a simple sample using annotations. A
subsequent blog will show more advanced samples.



A POJO can be converted to a WebSocket endpoint by specifying @WebSocketEndpoint
and @WebSocketMessage.
@WebSocketEndpoint("/hello")
public class HelloBean {

    @WebSocketMessage
    public String sayHello(String name) {
        return "Hello " + name + "!";
    }
}
  • @WebSocketEndpoint marks this class as a
    WebSocket endpoint listening at URI defined by the value
    attribute.

  • The @WebSocketMessage identifies the method that
    will receive the incoming WebSocket message. This first method
    parameter is injected with payload of the incoming message. In
    this case it is assumed that the payload is text-based. It can
    also be of the type byte[] in case the payload is
    binary. A custom object may be specified if decoders
    attribute is specified in the @WebSocketEndpoint.
    This attribute will provide a list of classes that define how a
    custom object can be decoded.



    This method can also take an optional Session
    parameter. This is injected by the runtime and capture a
    conversation between two endpoints.
  • The return type of the method can be String, byte[]
    or a custom object. The encoders attribute on @WebSocketEndpoint
    need to define how a custom object can be encoded.


The client side is an index.jsp with embedded
JavaScript. The JSP body looks like:


<div style="text-align: center;">
<form action="">
    <input onclick="say_hello()" value="Say Hello" type="button">
        <input id="nameField" name="name" value="WebSocket" type="text"><br>
   </form>
</div>
<div id="output"></div>

The code is relatively straight forward. It has an HTML form with a
button that invokes say_hello() method and a text
field named nameField. A div placeholder
is available for displaying the output.



Now, lets take a look at some JavaScript code:


<script language="javascript" type="text/javascript">
var wsUri = "ws://localhost:8080/HelloWebSocket/hello";
    var websocket = new WebSocket(wsUri);
    websocket.onopen = function(evt) { onOpen(evt) };
    websocket.onmessage = function(evt) { onMessage(evt) };
    websocket.onerror = function(evt) { onError(evt) };

    function init() {
        output = document.getElementById("output");
    }
    function say_hello() {
     websocket.send(nameField.value);
        writeToScreen("SENT: " + nameField.value);
    }


  • This application is deployed as "HelloWebSocket.war" (href="//cdn.app.compendium.com/uploads/user/e7c690e8-6ff9-102a-ac6d-e4aebca50425/f4a5b21d-66fa-4885-92bf-c4e81c06d916/File/32a0dc79bfc79c0633696348dcd3b6f5/hellowebsocket.war">download
    here) on href="http://dlc.sun.com.edgesuite.net/glassfish/4.0/promoted/glassfish-4.0-b57.zip">GlassFish
    4.0 promoted build 57. So the WebSocket endpoint is
    listening at "ws://localhost:8080/HelloWebSocket/hello". A new
    WebSocket connection is initiated by specifying the URI to
    connect to.

  • The JavaScript API defines callback methods that are invoked
    when the connection is opened (onOpen), closed (onClose),
    error received (onError), or a message from the
    endpoint is received (onMessage).

  • The client API has several send methods that
    transmit data over the connection. This particular script sends
    text data in the say_hello method using nameFields
    value from the HTML shown earlier.
  • Each click on the button sends the textbox content to the
    endpoint over a WebSocket connection and receives a response
    based upon implementation in the sayHello method
    shown above.


How to test this out ?

  1. Download the entire source project href="//cdn.app.compendium.com/uploads/user/e7c690e8-6ff9-102a-ac6d-e4aebca50425/f4a5b21d-66fa-4885-92bf-c4e81c06d916/File/b003cbabe839fd5a061ec8d232cb5fbf/totd183_hellowebsocket.zip">here
    or just the href="//cdn.app.compendium.com/uploads/user/e7c690e8-6ff9-102a-ac6d-e4aebca50425/f4a5b21d-66fa-4885-92bf-c4e81c06d916/File/32a0dc79bfc79c0633696348dcd3b6f5/hellowebsocket.war">WAR
    file.

  2. Download href="http://dlc.sun.com.edgesuite.net/glassfish/4.0/promoted/glassfish-4.0-b57.zip">GlassFish4.0
    build 57 or href="http://dlc.sun.com.edgesuite.net/glassfish/4.0/promoted/">later
    and unzip.
  3. Start GlassFish as "asadmin start-domain".
  4. Deploy the WAR file as "asadmin deploy HelloWebSocket.war".
  5. Access the application at href="http://localhost:8080/HelloWebSocket/index.jsp">http://localhost:8080/HelloWebSocket/index.jsp.

After clicking on "Say Hello" button, the output would look like:



src="//cdn.app.compendium.com/uploads/user/e7c690e8-6ff9-102a-ac6d-e4aebca50425/f4a5b21d-66fa-4885-92bf-c4e81c06d916/Image/21c9f29e32a65e15dfc278b53e2fe06c/totd183_screen_output.png"
height="303" width="659">


Here are some references for you:
  • WebSocket - Protocol
    and JavaScript API
  • JSR 356: Java API for WebSocket - href="http://websocket-spec.java.net/">Specification (href="http://jcp.org/aboutJava/communityprocess/edr/jsr356/index.html">Early
    Draft) and Implementation
    (already integrated in href="http://download.java.net/glassfish/4.0/promoted">GlassFish
    4 promoted builds)


Subsequent blogs will discuss the following topics (not necessary in
that order) ...
  • Binary data as payload

  • Custom payloads using encoder/decoder
  • Error handling

  • Interface-driven WebSocket endpoint
  • Java client API
  • Client and Server configuration
  • Security
  • Subprotocols
  • Extensions

  • Other topics from the API
  • Capturing WebSocket on-the-wire messages

Join the discussion

Comments ( 16 )
  • sajid mestri Wednesday, October 17, 2012

    Dear sir,

    I reads all socket java information related with client/server. This is very importantant info. and helpful to all.

    Regards

    Sajid Mestri

    India(Maharashtra- Sangli)

    +91 9922272229


  • James Velasco Friday, October 19, 2012

    Arun,

    Thanks for the tutorial !

    On note, the send_echo() function did not work properly on IE10,

    below are the changes I made to get it to work for IE10 as well as the latest Firefox, Chrome, and Safari:

    function send_echo() {

    var send_val = document.getElementById( "textID" ).value;

    websocket.send( send_val );

    writeToScreen("SENT: " + send_val );

    }

    James


  • Arun Gupta Monday, October 22, 2012

    James,

    I did try on the almost latest Chrome (22.0.1229.94) and Firefox (15.0.1) on Mac (10.7.4) and it worked seamlessly. Which platform did you try ?


  • James Velasco Monday, October 22, 2012

    Arun,

    Just to be clear, the original send_echo() function worked fine for all browser/platforms I tested EXCEPT IE10 on the release version of Windows 8 Pro.

    The fix I posted will allow the example to work on IE10 as well as all of the previously tested platforms.

    James


  • Neil Wednesday, January 9, 2013

    Hi Arun, somehow I am getting error resolving the imports

    http://i47.tinypic.com/2zp6ogo.png


  • Arun Gupta Wednesday, January 9, 2013

    Neil,

    Are you using GlassFish 4 ?

    Also, the API has changed from javax.net.websocket.annotations.* -> javax.websocket. Read https://blogs.oracle.com/arungupta/entry/websocket_samples_in_glassfish_4 for more details.


  • Neil Thursday, January 10, 2013

    Yes Arun

    I just installed glassfish-4.0-b70-windows.exe from the promoted directory

    Pointed my Netbeans to use this installation in the Web projec. Even javax.websocket did not get resolved.

    Which jar should be present as library so that I can use websocket API ? I can try to debug this. Emailed to issues@websocket-spec.java.net also.


  • Arun Gupta Thursday, January 10, 2013

    Neil,

    issues@websocket-spec.java.net is for posting issues about the specification. Please post your implementation-related questions to http://java.net/projects/tyrus/lists/users/archive.

    Have you updated your pom.xml to include the dependency ?


  • guest Friday, January 11, 2013

    Hi Arun,

    Thanks for the tutorial. The sample works good for me when I deploy it in glassfish-4.0-b57. Under glassfish/modules I see websocket-osgi.jar, I wanted to know/ validate if I can use this jar for websockets sample to execute on the jboss app server

    Thanks,

    Nivedita


  • Arun Gupta Friday, January 11, 2013

    Nivedita,

    There are several JARs together that provide WebSocket support in GlassFish. None of this has been tested on JBoss but I'll be looking forward to your blog entry if you are able to get it working.

    Arun


  • Ly Friday, January 18, 2013

    Hello Arun,

    is it possible to use session beans with asychronous methods in a @WebSocketEndpoint annotated class with Context & Dependency Injection 1.1 (JSR 346) in Glassfish 4 beta x?

    Ly


  • Arun Gupta Wednesday, January 23, 2013

    JSR 356 Expert Group is still discussing how EJB and WebSocket are going to play with each other, stay tuned for details on that. You can always participate at: http://java.net/projects/websocket-spec/lists/users/archive


  • Raghu Wednesday, February 27, 2013

    Hi Arun,

    I have a WebSocket web application running in WebLogic 12c Server. I would like to write a Java client program to connect to it.

    Can I download and include the relevant JAR files in order to write a Java Client program. If so, can you please point me to the dowloand URL.

    Thanks,

    Raghu


  • Arun Gupta Sunday, March 3, 2013

    Raghu,

    Please use the WebSocket Client API as explained at:

    https://blogs.oracle.com/arungupta/entry/websocket_java_client_api_in


  • DJ Monday, July 1, 2013

    Hi Arun,

    Is it possible to use WebSockets in clustered JEE environment.

    DJ


  • Arun Gupta Wednesday, July 17, 2013

    DJ,

    GlassFish 4 that provides the implementation of Java EE 7 does not provide support for clustering yet. So you cannot use WebSocket in clustered environment.


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