jsr340-experts@servlet-spec.java.net

[jsr340-experts] Websocket Proposal with NIO support

From: Rick Hightower <richardhightower_at_gmail.com>
Date: Thu, 6 Oct 2011 16:04:15 -0700

*The purpose of this proposal to come up with an API for WebSockets.
WebSocket needs to be in JSR-340. *

*--- JSR 340 needs WebSocket Support ---*

Given the following facts: 1) Every known desktop browser and almost all
mobile browser supports WebSockets. 2) WebSockets are in the final stages of
IETF approval. The right time for the Servlet API to support WebSockets is
now.

The initial version of the WebSocket API should be in the next release of
the Servlet specification JSR 340. Java *developers should not have to wait
another three to five years for a version of Servlets that support the
WebSocket API*.

WebSocket is the next Internet protocol. It will be pervasive and it is
generic enough for other things to be built on top of it.

*---Minimal changes to Servlet API to support WebSocket API:---*

Due to the simple and focused scope of WebSocket, a useful WebSocket API is
simple. WebSockets needs to support non-blocking IO. Support for WebSocket
by the Servlets spec would require minimal API support as follows:


   - * one method to the HttpServletResponse namely startWebSocket,
   - * one WebSocketContext interface and
   - * one WebSocketHandler interface.


In many respect the support for WebSockets will mirror the support for Async
and Comet, with differences. It will be built on top of the asynchronous IO
support.

http://java.net/projects/servlet-spec/lists/jsr340-experts/archive/2011-09/message/0

Enclosed are the definitions of these changes along with a further
explanation of the WebSocket API design principles, rough draft of proposed
Java interfaces and API changes.


*---Design goals and principles for WebSocket support in the Servlets:---*


   - * WebSocket is a client/server protocol which potentially can be peer
   to peer without a Servlet Engine.
   - * Java can use WebSockets in a peer to peer fashion without a Servlet
   Engine
   - * After initial handshake there should be no required Servlet API
   dependency, WebSockets is independent of Servlets
      - ** If, for example, you have a WebSocket handler that needs an
      HttpSession, then it is the application developers job to pass
and store the
      HttpSession where the WebSocket handler can access it.
      - ** No callbacks are needed as you can pass whatever objects you need
      to your custom implementation of the handler.
   - * WebSocket API must be Stream based
      - ** NIOReader, NIOWriter, NIOInputStream, NIOOutputStream
         - *** To be defined and enhanced by Remy and Rajeev so it can be
         used with WebSockets
         - *** This might be renamed at some point to
         AsyncReader, AsyncWriter, AsyncInputStream, AsyncOutputStream: TBD
      - ** No buffered objects. No byte [] or Strings just streams
   - * WebSockets handling is based on simple handler API
   - * WebSocket API is analogous to Servlet API, low level network
   abstraction and not a higher order framework
      - ** No JSON support
      - ** No Strings
      - ** No object serialization
      - ** Other frameworks can build on top of WebSocket and provide those
      things
   - * Other JSRs will be formed at some point to do the equivalent of
   JAX-RS with WebSockets. That is where WebSockets will get its JSON support.
   - * WebSocket Extension SPI to be defined by Remy and/or Greg W. not part
   of the Websocket API
   - * All websocket interfaces should be in the package javax.websocket
      - ** This package shall have no ties to the Servlet packages. No
      dependencies to Servlet API.

*
--API Changes and classes:--*

Due to the simple and focused scope of WebSocket, you can define an API that
is simple. Support for WebSocket in the Servlet engine would require adding
one method to the ServletRequest, namely, startWebSocket, one
WebSocketContext interface and one WebSocketHandler interface. This is very
similar to the support for Comet.

package javax.websockets;

interface WebSocketHandler {

  void onStart(WebSocketContext context) throws IOException;

  void onBinaryMessage(WebSocketContext context, NIOInputStream is) throws
IOException;

  void onTextMessage(WebSocketContext context, NIOReader reader) throws
IOException;

  void onClose(WebSocketContext context) throws IOException;

}

The reader and the input stream represent the incoming data from WebSockets.
Changes need to be made to NIO support to include support for WebSockets.
The changes seem doable.

see
http://java.net/projects/servlet-spec/lists/jsr340-experts/archive/2011-09/message/0



The WebSocketContext is as follows:

package javax.websockets;
interface WebSocketContext {

  NIOOutputStream startBinaryMessage() throws IOException;

  NIOPrintWriter startTextMessage() throws IOException;

  WebSocketContext start(Runnable);

  void close() throws IOException;

}

The *WebsocketContext* is used to send responses to client or peer.

The method added to ServletRequest would be

  void startWebSocket(WebSocketHandler) throws IOException,
ServletException;

*--Threading model--*

*WebSocketContext.start* method can be used to start an asynchronous
response so that it does not block. This is analogous to the *
javax.servlet.AsyncContext.start* method in purpose and usage.

*--Use Case Scenario / Example --*

   - * A Stock ticker application exists.
   - * A page is loaded from a Servlet engine.
   - * This page contains HTML5 and JavaScript code.
   - * The JavaScript code sends a message to a URL called
   /fooapp/stockTicker to initiate a WebSocket conversation.
   - * The server has a servlet mapped under the URI /fooapp/stockTicker.
   - * Since this is WebSocket the browser is going to send a WebSocket
   upgrade request to /fooapp/stockTicker URI which is a GET request with
   special headers to upgrade to the WebSocket protocol (see
   http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17#section-1.3
   ).
   - * The Servlet mapped to this URI will need to call
   ServletRequest.startWebSocket in its doGet method.
      - a WebSocketHandler is passed to the ServletRequest.startWebSocket
      that has access to the WebSocketContext
   - * Once ServletRequest.startWebSocket, the engine will verify that this
   was a real WebSocket upgrade request, if not it will throw a
   ServletException
   - * Inside of the WebSocketHandler implementation, the onTextMessage
   method will get called.
   - * This WebSocketHandler uses the WebSocketContext.start to do an async
   operation (like periodically look up stock ticker info) using a Runnable
   that has access to the WebSocketContext.
   - * Inside of the Runnables spawned by the hander
   calling WebSocketContext.start, the Runnables are initiating communication
   back to the client (browser) by invoking WebSocketContext.startTextMessage
   to get a Writer so it can publish stock quotes that the browser can read and
   display. The Runnables could do this in a loop that pauses periodically by
   calling sleep. If there are many Runnables sending data on the same client
   connection, then the application code most synchronize the responses to
   avoid frame corruption, i.e. synchronize on the WebSocketContext.
   Synchronizing method sending is not handled by this API. It is the
   application developers job.
   - * The HTML 5 / JavaScript code from the page sends a stop message. The
   handler for this messages calls close on the context and the conversation
   ends.


-- 
*Rick Hightower*
(415) 968-9037
Profile <http://www.google.com/profiles/RichardHightower>