jsr340-experts@servlet-spec.java.net

[jsr340-experts] Proposal for WebSocket to be part of JSR 340

From: Rick Hightower <richardhightower_at_gmail.com>
Date: Wed, 5 Oct 2011 02:38:31 -0700

 *
The purpose of this proposal is to table the needs for WebSocket, and state
emphatically that WebSocket needs to be in JSR-340. WebSocket support in JSR
340 needs a simple streaming interface. Two small interfaces and one
additional method to ServletRequest is all that is proposed. This WebSocket
package is at the same level of abstraction as the Servlet API but geared
toward WebSockets.

--- 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*.

The WebSocket API should abstract all of the low level details from the
developer. It should be streamed based and not buffered string, objects or
byte arrays.

The WebSocket API should be built along the lines of the same core
principles that inspired the Servlet API, almost unarguably the most
successful Java standard in existence.

It should be devoid of fluff, and should not be over specified. It should
not be over abstract. *It should not have an SPI and Frame filtering long
before a need or usage pattern has been specified.*

It is a network abstraction like Servlets. It should not be at the level of
JAX-RS for example, it should be at the level of the Servlet API. The
WebSocket API should not deal with JSON, Strings, or serialized Java
objects. It should not fret about serializing Java into XML, JSON or
whatever else. It should not be aware of anything but a simple network
abstraction.

*-- It seems WebSockets not directly on JSR 340 radar ---*

WebSockets should be part of JSR 340, and it does not seem like it is based
on landing page and conversations on the JSR 340 list. It seems that
WebSockets is not directly on the radar of the Servlet JSR 340

The landing page for the specification says the following:

*
*
*"Enable support for WebSockets and other such protocols that work on / do
initial handshake over HTTP."*
*
*
*"Add necessary support to enable WebSocket and other protocols that do
initial handshake over HTTP or work on top of HTTP in the Servlet API by
adding ability upgrade the underlying socket protocol. Add support where
possible to enable such functionality in the web container so we can build
easier to use higher level protocol support for things like WebSockets."*

*
*
WebSocket is like HTTP. There is no next coming. WebSocket is the next
thing. There is no need to build an generic HTTP upgrade mechanism to handle
upgrades successfully. The HTTP upgrade has been around for a long time.
WebSockets is the only major technology to use it. JSR 340 Servlets does not
need a low level network handler for whatever comes next. Once the upgrade
happens WebSockets has more in common with TCP/IP than it does with HTTP. It
is a different beast. It is ubiquitous.

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.

SPDY is an HTTP binary replacement not an HTTP upgrade. Having a generic
support for HTTP upgrade is the wrong path. Supporting WebSockets is the
right path.
*
---Minimal changes to Servlet API to support WebSocket API:---*

Due to the simple and focused scope of WebSocket, a useful WebSocket API is
simple. 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.

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 and description of threading model employed
by this WebSocket API.

Most of the ideas in this proposal are based on the design of the WebSocket
API that Scott Ferguson wrote for Resin's WebSocket support. Scott Ferguson
has contributed many additional ideas to this proposal. Scott has been
involved on the IETF WebSocket working group for the last 18 months. He has
been involved with Servlet engine design and implementation since the
start.

*---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.
   - * WebSocket API must be Stream based
      - ** Reader, Writer, InputStream, OutputStream
      - ** 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 API shall not fall victim to premature frameworking
      - ** WebSockets although pervasive is newly formed and time will tell
      exactly how it will be used. The focus on the API should be as simple and
      future thinking as possible without guessing which way things will go.
      - ** First release of WebSocket API should not have a Frame API or
      frame handlers or an WebSocket SPI.
      - ** Hard to tell where the extension points should be until there are
      some WebSocket protocol extensions are built.
      - ** Common extensions like multiplexing, compression, security will
      most likely be specified and added by Server Engine providers as they are
      specified and become prominent.
      - ** SPI and Frame handlers should be specified in next revision of
      WebSocket extension.
      - ** Frame handlers are to WebSocket handlers what FIlters are to
      Servlets (not quite but close), Filters did not come out in the first
      release of Servlets. There needs to be some shakeout to figure
out the best
      way to abstract this.
   - * WebSockets are very likely to be used beyond initial proposed usage
   because it handles things like framing that other protocols like IIOP, JRMP,
   and video streaming need. If you were going to build IIOP or JRMP today, you
   would naturally build it on top of WebSockets.
   - * 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 WebSocket Handler interface.

package javax.websockets;

interface WebSocketHandler {

  void onStart(WebSocketContext context) throws IOException;

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

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

  void onClose(WebSocketContext context) throws IOException;

}

The reader and the input stream represent the incoming data from WebSockets.

The WebSocketContext is as follows:

package javax.websockets;

interface WebSocketContext {

  OutputStream startBinaryMessage() throws IOException;

  PrintWriter 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--*

It is very likely that a given *WebSocketHandler* will want to schedule one
or more response to happen asynchronously. A simple hander for a simplistic
application could merely use the *WebSocketContext* to start a conversation
and the entire response could be in the websocket handler. A more complex,
scalable, non-blocking handler would use the *WebSocketContext.start* method
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.

The *WebSocketContext* manages it so only one message is sent at a time from
server (Servlet engine) to client (Browser). *WebSocketContext* ensures that
once *startTextMessage* or *startBinaryMessage* is called that no other
thread can send a message until the current thread stops sending the
message. Essentially, the *startTextMessage* or *startBinaryMessage* creates
a lock which is only released by calling *close* on the *OutputStream* or *
Writer*. The *close* method on the WebSocketContext, will call close output
stream or writer which will then release the write lock. This allows many
threads of execution to send messages, but only one thread at a time can
send messages to the client.

*--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 WebSocketContext ensures that only one of them talk to
   the client at a time.
   - * 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