OpenAjax Hub 1.1 Roadmap

From MemberWiki

Jump to: navigation, search

Contents

About this wiki page

This wiki page holds a strawman proposal for a roadmap for OpenAjax Hub 1.1. This proposal is brand new and far-reaching, requires collaboration among multiple activities (particularly Interoperability WG, Communications Hub TF and Security TF), and will likely involve much discussion. The OpenAjax Alliance members might decide that this roadmap is misguided and decide to go in a much different direction. Therefore, as it stands today, this wiki page should be considered simply as "ideas to consider".

Note: We had some initial discussion at the Interop phone call on 2007-07-11. One thing in particular that was mentioned was that the @system approach described below is likely to be possible in today's browsers only between windows that are running the same browser.

Introduction

Where OpenAjax is today

The OpenAjax Alliance has now made great progress in completing a lean-and-mean OpenAjax Hub 1.0. The specification only needs final editing; the open source reference implementation at SourceForge implements all features; and there is a complete test suite that fully exercises the open source reference implementation.

Hub 1.0 allows:

  • Multiple Ajax toolkits to work together within the same browser frame - where the key feature is a publish/subscribe event hub that enables Ajax components from different toolkits to pass messages to each other without understanding how the other components are implemented.

In parallel the finishing work on Hub 1.0, other committees at OpenAjax are converging on various technical strategies to address other technical problems important to Ajax developers:

  • Mediating multiple Comet connections - The Communications Hub Task Force is addressing technical issues around Comet (Ajax server-push), particularly how to allow Comet to work in mashup scenarios in today's browsers where the mashup might have multiple push components (and thus exceed the browser's 2 connection limit). After months of discussions, and with cross-pollination with other industry efforts (e.g., the Bayeux project and efforts within the Java community), the Comm Hub task force has agreed on problem definitions and is evaluating specific technical proposals. Simultaneously, outside of OpenAjax, the Bayeux project (server-independent messaging protocol for Comet using JSON) is far along with their technologies and specification.
  • Secure Mashups - The Security Task Force has assigned a top priority to the secure mashup question. The dilemma is finding the correct technical approach that delivers necessary component isolation necessary to achieve the word "secure" while finding a way for components to communicate with each other such that you have a true "mashup". In parallel with OpenAjax work, other parts of the industry are working hard to deliver solutions to the dilemma, such as Crockford's <module> proposal and the Standford/Microsoft Subspaces proposal

Before finalizing OpenAjax Hub 1.0

Before putting an OpenAjax stamp of approval on OpenAjax Hub 1.0, we need two things:

  • Multiple trial implementations and multi-toolkit demonstrations of the Hub in action - In March we had an InteropFest where 12 Ajax toolkits integrated with Hub 0.3/0.4 and successfully passed the conformance test, but the Hub has changed. We need several toolkits to integrate with the latest code and for multi-toolkit demonstrations to have high confidence that the Hub is now suitable for the industry.
  • Sufficient vision about Hub 1.1 that we have reasonable confidence that Hub 1.0 is a suitable foundation for future growth - It would be bad for the industry if we discovered soon after Hub 1.0 receives approval that we need to deprecate key APIs because Hub 1.1 needs a different approach.

This wiki page focuses on the second bullet above. It attempts to provide a vision for suitable APIs to deliver two key features, CommHub and Secure Mashups, that have been proposed for Hub 1.1. It also provides a roadmap for other interesting features, such as extending the Hub to support point-to-point communications (Hub 1.0 only supports public broadcasting of messages), cross-window/same-domain messaging, persistent local storage and offline applications.

Various technologies that overlap but aren't yet unified

Various technologies are attempting to address only one part of the interoperability puzzle, and therefore miss opportunities for a comprehensive unified solution:

  • OpenAjax Hub 1.0 - The first release of the Hub (Hub 1.0) does a fine job of addressing Ajax integration within a single browser frame, where (typically) each of the various Ajax user interface components manifests itself as an HTML DIV element, but Hub 1.0 does not provide a solution for scenarios where the mashup developer isolates components into IFRAMEs (often for security reasons). The Hub also does not address Comet, nor does it address Local Storage.
  • Comet (Communications Hub and Bayeux) - The OpenAjax Communications Hub proposals are moving towards better integration with Hub 1.0 (whereas earlier proposals included redundant features). Both the CommHub and Bayeux are focused on a single technology problem, Comet, and have not attempted to address a more general set of problems (e.g., CommHub and Bayeux are not trying to address the Secure Mashup and Local Store problems).
  • Secure Mashups - In recent months, a number of efforts (<module>, Subspaces) attempt to address secure mashups.
  • Dojo Offline Toolkit and Google Gears - These two technologies are focused on the local storage and offline problem, but are not trying to address cross-component messaging (like Hub 1.0) or Secure Mashups or Comet. Google Gears also provides domain-specific additional threads (WorkerPools), which can communicate with other domains that might be useful in mashup scenarios.

Towards a more comprehensive solution

The Ajax development community is looking for solutions to all of the following:

  • Secure mashups
  • Server-push/Comet
  • Secure messaging between components, including point-to-point (i.e., not just broadcast)
  • Secure cross-frame and cross-window messaging
  • Local storage
  • Disconnected operation (aka offline)

The roadmap below proposes how OpenAjax Hub might evolve such that is provides a unified and more comprehensive approach that helps address all of the above requirements.

Proposed Roadmap

Objectives and requirements

The following sections describe a unified approach which learns from Hub 1.0 and from some of today's leading proposals in the areas of Secure Mashups, Comet, and Local Store. This unified approach is meant to meet the following goals:

  • Works with today's browsers without plugins - In other words, this approach aligns with OpenAjax principles.
  • Supports asynchronous messaging - This is necessary because there is a client-server aspect to these proposals.
  • Cross-component messaging within a single frame - This is what Hub 1.0 delivers, and this proposals leaves those features intact. (Although we might consider minor changes to the APIs in Hub 1.0.)
  • Cross-frame messaging - This proposal extends the features in Hub 1.0 to allow communication between Ajax components across browser frames.
  • Mediated multiple Comet connections - This proposal shows how to package up the Communications Hub such that it integrates seemlessly with the OpenAjax Hub in a manner to allows features in the areas of secure mashups and local storage.
  • Secure mashups - This proposal allows developers to sandbox of mashup components within IFRAMEs (typically for security reasons), but allows mashup components to communicate in a secure manner across IFRAMEs through the OpenAjax Hub's pub/sub engine
  • Point-to-point messaging - OpenAjax Hub 1.0 only supports public broadcasting of messages within a single browser frame. This proposal extends the Hub to support secure private messaging across particular components.
  • Cross-window, same-domain messaging - This proposal provides a mechanism for secure communications across browser windows within the same computer system so long as the windows share the same domain.
  • Local storage and sometimes-disconnected (aka offline) Web applications - The cross-windows, same-domain message approach is meant to be a small step towards technology-independent APIs for storing information in a persistent local storage and sometimes-connected Web applications. Although this proposal does not specifically target the offline problem, the goal is to design an approach that allows for future growth in this direction.

Actors and agents within the proposed roadmap

The following section describes the actors and agents (in grammatical terms, the nouns) within the proposed roadmap.

Hosts

  • A "Host" (shorthand for Message Room Host) is an agent that manages one or more (Message) Rooms.
  • Examples:
    • The OpenAjax Hub is a Host that manages client-side (Message) Rooms.
    • For a push server, a Web server that supports the Bayeux protocol would also be a Host
    • Freenode is an example of a chat server.
  • A Message Room Host is identified by a URL

Rooms

  • A "Room" (shorthand for Message Room) is a common area to which multiple agents can connect. Within a Room, agents send and receive messages to/from each other via publish/subscribe APIs.
  • Each Room is managed by a single Host. The Host controls which clients can join the room.
  • A Room is identified by an arbitrary string (e.g., "StockPrices" or "Weather" or "A39geo25b").
  • Room examples:
    • For a Bayeux server, there might be rooms for "MyCompany/RealTimeInventory" or "WeatherAboveground/Forecasts"
    • For an IRC server, there might be message rooms for "#newbies" or "#TeenZone"
    • In this proposed roadmap for the OpenAjax Hub, there would be:
      • A set of standard public message rooms
        • @frame - For all consumers that are in the same browser frame (this room would be public)
        • @mashup - For all consumers that are part of the same mashup application, which might consists of multiple browser frames (this room would be public)
        • @system - For all consumers on the same computer system which might have multiple browser windows. This room would have same-domain restrictions, and thus public to all active browser windows that share the same domain.
      • Custom message rooms (mediated)
        • Custom message rooms would be fully managed by callbacks to the Hub. Every JavaScript call to routines such as OpenAjax.hub.join(), OpenAjax.hub.publish() or OpenAjax.hub.subscribe() would be redirected to callbacks registered by custom JavaScript logic that would serve as the Host for a given custom message room.
        • For a mediated custom message room that need to be secure, we recommend that the string use a temporary, unpredictable, random string (e.g, A39geo25b) and that the value of this string be passed from the Host to the components in a manner that prevents discovery by other components. (For example, in a mashup, the mashup application might create an IFRAME for a component and include the roomId (e.g., A39geo25b) within a parameter at the end of the URL that loads the component.)
  • Justification - Why introduction a notion of rooms (i.e., we already have hosts and topics)? The notion of rooms adds one extra abstraction layer within the proposed Hub APIs. Here are justifications for this extra bit of complexity in the model:
    • For client-server communications, a single host URL (e.g., freenode.net) might server multiple isolated communities (i.e., the various IRC channels).
    • On the client side, the Hub represents a single (virtual) host that needs to manage both public and private communications channels. (Private channels are required when two client-side components need to talk with each other without letting other unknown components listen.)

Topics

  • A Topic belongs to a Room and is identified by a tokenized string (e.g., "Weather/California/Fresno").
  • Clients subscribe to topics and publish messages on a particular topic.

Messages

  • Messages are published to all subscribers for a given Topic

Client

  • A block of autonomous logic running on a computer (e.g., within the end user's browser) that participates in Message Rooms on behalf of an End User

End User

  • An actual person that operates a computer and manipulates a user interface

Proposed APIs

The following section describes the actions that can be taken (in grammatical terms, the verbs) within the proposed roadmap.

Introductory comments about proposed APIs

Backwards compatibility

The proposed APIs for Hub 1.1 would be backwards compatible with the APIs for Hub 1.0. The pub/sub features in Hub 1.0 would be a proper subset of the more advanced features in Hub 1.1. Developers would only need to invoke the newer APIs found in Hub 1.1 if they needed to use the new features.

To illustrate, to broadcast a message to any listeners within the same frame, a developer would use the same APIs as found in Hub 1.0:

OpenAjax.hub.publish("com.mycompany.mymessage", payload);

And developers who wished to subscribe to messages broadcast within the same frame would continue to use the APIs from Hub 1.0:

function MyCallback(eventname, publisherData, subscriberData) {...}
OpenAjax.hub.subscribe("com.mycompany.mymessage", MyCallback);

Example using new features

However, if a developer needs to use the new features (e.g., point-to-point messaging, communicate with a Comet server, cross-frame messaging), then the developer would need to use the new APIs from Hub 1.1. For example, to subscribe to messages from a Comet server, the developer might have code similar to the following:

function SubscribeCallback(eventname, publisherData, subscriberData) {...}
function JoinCallback(joinData) {
  ...
  OpenAjax.hub.subscribe({connId:joinData.connId, memberId:joindata.memberId, topic:"NewOrders"}, SubscribeCallback)
  ...
}
function ConnectCallback(connectionData) {
  ...
  OpenAjax.hub.join({connId:conectionData.connId, room:"Sales"}, JoinCallback)
  ...
}
OpenAjax.hub.connect({host: "http://MyCompany.com/MyCometServer"}, ConnectCallback);

Note that all of the proposed APIs are designed for asynchronous communications.

Notation used below

  • Each API below indicates that would be new for Hub 1.1 is preceded by [Hub 1.1]
  • Each API below that already exists in Hub 1.0 but will be enhanced for Hub 1.1 is preceded by [Hub 1.0/1.1]

[Hub 1.1] retval = OpenAjax.hub.connect( { host:..., [timeout:...], [extdata:...] }, callback )

  • A client calls OpenAjax.hub.connect to make itself known and connect to a Host.
  • The host parameter is a real URL for a server.
  • The Hub returns immediately with a retval boolean which is true if the Hub sees no problems with the request, and false otherwise. But the request may still fail. The Hub will invoke the provided callback function once the connection has succeeded, failed, or timed out. The callback function receives a single parameter, a JSON object, as follows: {success:<boolean>, [connID:<number>], [ext:...]}. The connId is an unpredictable random number that represents the unique ID that the host provides for that connection.
  • Note that a client should not connect to the OpenAjax Hub for local message messaging. The Hub is a pre-established Host and each Client already has an implicit connection to the Hub. (Under the hood, host == null.)
  • If Hub is connecting via Bayeux to a Bayeux server, connect with server via /meta/handshake (if not yet done already) and then /meta/connect.
  • (Might need a second callback for when connection is lost)

[Hub 1.1] retval = OpenAjax.hub.reconnect( { connId:..., [extdata:...] }, callback )

  • (not yet detailed)
  • If Hub is connecting via Bayeux to a Bayeux server, reconnect with server via /meta/reconnect.

[Hub 1.1] retval = OpenAjax.hub.disconnect( { connId:..., [extdata:...] }, callback )

  • (not yet detailed)
  • If Hub is connecting via Bayeux to a Bayeux server, disconnect with server via /meta/disconnect.

[Hub 1.1] retval = OpenAjax.hub.join( { [connId:...,] room:..., [extdata:...] }, callback )

  • A client calls OpenAjax.hub.join to join a Message Room.
  • The connId parameter MUST be provided when joining a room on a remote server and MUST NOT be provided when joining a room on the local OpenAjax Hub.
  • The Hub returns immediately, with a return value of true if the Hub sees no problems with the request, and false otherwise. But the request may still fail. The Hub will invoke the provided callback function once the connection has succeeded, failed, or timed out. The callback function receives a single parameter, a JSON object, as follows: {success:<boolean>, [memberId:<number>], [ext:...]}. The memberId is an unpredictable random number that represents the unique ID that the host provides for your membership in the room.
    • The Hub maintains a set of pre-established rooms as follows:
    • @frame: The @frame room allows for message passing among clients that live within the same HTML frame. Each client is automatically a member of @frame.
    • @mashup: The @mashup room allows for secure cross-frame (which means potentially cross-domain) message passing for frames that live within the same top-level HTML window. (Note: there are various constraints on how things must be set up in order to achieve secure messaging.)
    • @system: Publish messages to persistent local storage area such as Google Gears, thereby allowing communication with other windows on same computer that share the same domain. Long-term, we want this to use local services, such as Google Gears, but the fallback is a server-based mechanism (a chat room amongst windows) in case no suitable local storage mechanism is available. For server mechanism, try to piggyback on push initiatives such as Jetty or Bayeux. Requires a provider setup such that an Ajax toolkit does heaving lifting to pull this off and Hub is just a shim layer. Requires a handshaking/negotiation mechanism about what local storage mechanism to use.
  • The Hub only allows the top frame within a window to create custom rooms. (See OpenAjax.hub.createRoom() below.)
  • If connection is to a Bayeux server, since Bayeux doesn't have a notion of rooms, then Hub does not talk with Bayeux server and simply returns a memberId.

[Hub 1.1] retval = OpenAjax.hub.createRoom( { room:..., [extdata:...] }, callback )

  • (Can only be invoked from within top frame. Creates a custom room. Need to think about this some more)

[Hub 1.1] retval = OpenAjax.hub.manageRoom( { room:..., [extdata:...] }, callback )

  • (Can only be invoked from within top frame. Allows registration of a management function that is invoked whenever anyone attempts to subscribe or publish within the given room. Any old rights management layer can be plugged in here. Need to think about this some more)

[Hub 1.0/1.1] retval = OpenAjax.hub.subscribe({[memberId:...,] topic:..., [extdata:...] }, callback )

  • (Note: one of the parameters sent to the callback is subId)
  • If connection is to a Bayeux server, Hub sends a /meta/subscribe message to server.

[Hub 1.0/1.1] retval = OpenAjax.hub.unsubscribe( { subId:..., [extdata:...] }, callback)

  • (not yet detailed)
  • If connection is to a Bayeux server, Hub sends a /meta/unsubscribe message to server.

[Hub 1.0/1.1] retval = OpenAjax.hub.publish( { [memberId:...,] topic:..., [extdata:...] }, data )

  • (not yet detailed)
  • If connection is to a Bayeux server, Hub sends a /meta/publish message to server.

Fields

(Insert table here that shows all fields within request/response/error messages, along with an indication of the functions with which they are used, and whether the field is part of the request, successful response, and/or error response. Here are some of the fields that need to be in the table.)

  • host:
  • connId:
  • room:
  • roomID:
  • topic:
  • subId:
  • callback:
  • timeout: (amount of time before Hub should give up)
  • timestamp: (shared field with Bayeux)
  • extdata: (similar in concept to Bayeux' ext, but choose different name to avoid confusion)

Providers

Introductory comments about providers

Some of the proposed APIs above would not be implemented natively within the OpenAjax open source implementation. Instead, our open source implementation would include plugin provider mechanisms so that other Ajax toolkits would provide low-level implementations for some of the new features in Hub 1.1.

The provider mechanisms would probably include protocol negotiation mechanisms where the provider advertises which protocols it supports and the higher-level code indicates protocol preferences. Bayeux has a reasonable approach for negotiation that we might consider adapting.

Here are the provider mechanisms proposed for Hub 1.1:

Client-server communications provider

A client-server communications provider would implement support for particular communications protocols, such as various protocols that can be used to implement Comet-style server push. (Note: Perhaps the Hub could include a simple fallback provider that uses XMLHttpRequest.)

Cross-frame communications provider

A cross-frame communications provider would send messages from one frame to another within the same browser window. (Note: Perhaps the Hub could include a simple fallback provider that provides cross-frame messaging by using the fragment identifier part of window.location.)

Cross-window, same-domain communications provider

Sends messages from one frame to another within the same computer system, where the frames might be in different windows but have to use the same domain. (Note: Perhaps the Hub could include a simple fallback provider that uses cookies in a very painful manner.)

Local storage and offline

The cross-window, same domain communications provider would have to leverage some form of local storage, even if just cookies. As we design this provider mechanism, we should make sure we design the mechanism with foresight towards addressing requirements for local persistent storage and offline applications.

Supplemental comments

Leveraging IFRAMEs for mashup security

Given the requirement that we are looking for solutions that work in today's browsers without plugins, we need to leverage the built-in security features within today's browsers that prevent cross-frame access from documents that come from different domains. IFRAMEs are the only mechanism that allows content from multiple domains to be used within the same browser window while sandboxing the content and logic.

Therefore, the centerpiece of this proposal with regard to mashup security is as follows:

  • If you need sandboxing, use IFRAMEs
  • If you need secure cross-component messaging, use Hub 1.1

The trust model for a mashup application is as follows:

  • The End User should only use trusted mashup applications
  • Trustworthy mashup applications isolate (i.e., sandbox) its mashup components from the mashup application and the other mashup components (where the use of IFRAMEs is the recommended approach) to prevent bad things from happening should the user load a malicious mashup component into his mashup
  • Mashup components that deal with sensitive information should be architected with strong attention to security, and in particular should not use public message rooms for messages containing sensitive data

Secure communications between mashup components

Hub 1.1 would provide a standard API for messaging between mashup components which is designed to allow for the creation of mashup applications; however, just using Hub 1.1 APIs would not be sufficient for addressing mashup security, particularly if some of the cross-component messaging within the mashup cannot be passed via public messaging broadcasting within the mashup. The mashup application developer would have to take supplemental steps in collaboration with mashup component developers.

One approach is as follows:

  • Mashup application
    • Includes OpenAjax Hub 1.1
    • Whenever it loads a mashup component, it runs a random string algorithm to generate a unique roomId. Then it inserts an IFRAME into the document for the given mashup component, where the SRC attribute includes the parameter OpenAjaxRoomId=<string>.
  • Mashup component
    • Includes OpenAjax Hub 1.1
    • A particular mashup component is posted at a particular URL (e.g., http://example.com/mashupcomponents/aaa.php) and is loaded via the insertion of an IFRAME element into the mashup application (see above).
    • The mashup component is front-ended by some server-side logic (PHP in this example) that processes the parameter OpenAjaxRoomId=<string> and places the given roomId into the JavaScript for the mashup component so that the component can attach itself to the given message room.

Integration with Bayeux

  • Bayeux support might or might not be a standard feature in the Hub. We need to think about this some more, but if we decide to jump on the Bayeux bandwagon, we would probably require Bayeux support over regular-old HTTP (using XHR) from any client-server communications provider.
  • The following Bayeux fields would be managed by the Hub under the hood:
    • channel, version, supportedConnectionTypes, minimumVersion, clientID, connectionType, subscription, successful, ext, error, advice, authSuccessful

Integration with Google Gears

Google Gears is clearly a technology that we need to watch. It is a great early attempt at addressing the offline problem, has some good openness attributes (e.g., it is cross-platform, cross-browser, and open source), and comes from a company that has considerable clout with the industry.

For Hub 1.1, Google Gears might be used as a cross-window/same-domain communications provider. Down the road, we need to keep an eye our for Google Gear as a potential provider for future local storage and/or offline services.

We should collaborate with the Google Gears team to see if it makes sense for Gears to use Hub 1.1 mechanisms for communication across worker pools.

Implications for Hub 1.0

OpenAjax.hub.subscribe(stringOrObject, callback)

  • First argument can be a topicName as a string (what we have now) or an object (for more complex things such as subscribing through Bayeux)
  • Second argument is the same as now
  • Move arguments 3, 4 and 5 (all optional now) to become optional fields on the first parameter

OpenAjax.hub.publish(stringOrObject, data)

  • First argument can be a topicName as a string (what we have now) or an object (for more complex things such as publishing through Bayeux)
  • Second argument is the same as now.

Topic names (e.g., org.openajax.hub.* vs /OpenAjax/*)

  • The choice of org.openajax.* for messages (or com.ibm.*) looks silly in the context of this unification proposal. For URL-like uniqueness, we have now two new constructs, URLs and message rooms. Why burden users with the geeky domain-name guideline. We should at least drop the "org.".
Personal tools