OpenAjax Hub 2.0 Specification Managed Hub Overview

From MemberWiki

Jump to: navigation, search

NOTE: This wiki page holds part of the OpenAjax Hub 2.0 Specification.


<--previous       contents--^       next-->


Contents

5 Managed Hub Overview

Managed Hub Modules

The diagram below shows the various modules within an application that uses the Managed Hub. The colors of the boxes specify which boxes are implemented by application and client component builders (gray background), those that are implemented by the Hub itself (blue background), and those that are implemented by one or more Container suppliers (orange background). The asterisks refer to cardinality; there is exactly one HubClient per Container, but there may be multiple Containers in a window.


ManagedHubModules.png


The modules shown in the picture above are as follows:

  • Manager Application - The Manager Application is the main HTML document for the application. It loads the necessary JavaScript files for the OpenAjax Hub, creates at least one Managed Hub instance, and creates Containers for each of the Client Application components that will be embedded within the Manager Application.
  • Client Applications - Client applications are application components that may be embedded within a parent application. Client applications may be isolated in separate iframe windows from other parts of the application.
  • ManagedHub - A ManagedHub object provides a secure messaging hub through which the embedded Client Applications communicate. The Manager Application can create any number of ManagedHub objects; however, typically, the Manager Application will create only a single ManagedHub instance that controls all of the embedded Client Applications.
  • Containers - The Manager Application creates a Container for each of the Client Applications that are associated with a given Managed Hub. The Container encapsulates a particular Client Application and manages the Client Application's life cycle, including loading/initialization and destruction. The Container performs all interactions with the ManagedHub (publish, subscribe, etc.) on behalf of its Client Application. The OpenAjax Hub 2.0 specification defines two built-in containers:
    • IframeContainer - This container sandboxes its Client Application within an HTML <iframe> element. All messages to/from the Client Application are marshalled across the iframe boundary (between the Client Application and the Manager Application) in a secure manner.
    • InlineContainer - This container places its Client Application into an HTML element (e.g., a <div> element) within the same browser window as the Manager Application. The inline container requires less memory and publishes messages more quickly than the IframeContainer; however, it does not sandbox the Client Application, so the latter can directly access the DOM of the Manager Application. As a result, the InlineContainer should be used only for Client Applications from trustworthy suppliers, such as your own organization's IT department, or when all clients on the page are from the same vendor and access the same information and services.
  • HubClient - When the Manager Application loads and initializes a given Client Application, it makes sure that a OpenAjax.hub.HubClient object is available for the Client Application. The OpenAjax.hub.HubClient interface allows the Client Application to communicate via the ManagedHub by calling publish() and subscribe(). There is a HubClient implementation for each Container implementation, e.g. an InlineContainer has a corresponding InlineHubClient.

Managed Hub Interactions

The following diagram adds arrows to illustrate how the various modules interact with each other:


ManagedHubInteractions.png


The different colors of the arrows illustrate the different types of module interactions:

  • The purplish horizontal arrows toward the sides of the picture represent the public, standard APIs within the OpenAjax Hub through which the Manager Application and Client Applications interact with the Hub. In particular:
    • The Manager Application interacts with each of the Managed Hub instances and each of the Containers
    • The Client Application interacts with the HubClient
  • The orange vertical arrow represents the interaction between the ManagedHub and the Container objects. The interfaces between the Managed Hub and Containers use public, standard APIs defined within the Specification.
  • The black horizontal arrow in the center represents implementation-specific communication between a Container and its associated HubClient. There is no standard for such communication.

Managed Hub Initialization and Usage

The following picture (repeated from the Publish/Subscribe chapter) provides a conceptual overview for how a Manager Application initializes the Managed Hub and the Client Applications in the mashup.


ManagedHubUsage.png


The picture above shows Security manager callbacks. The Manager Application must provide security manager callbacks - onPublish and onSubscribe - that enforce access control policy for messaging passing among the Client Applications and the Manager Application. The architecture for OpenAjax Hub allows for fine-grained access control such that every attempt to publish and every attempt to subscribe runs through the policy manager logic.

Managed Hub Message Passing

Once the Manager Application initializes itself and the client components used within a particular mashup, the client components can pass messages to each other via the OpenAjax Hub's publish and subscribe APIs. The following picture provides a conceptual overview for how a message goes from one Client Application (Component-A) to a different Client Application (Component-B). In the picture below, Component-A uses the IframeContainer, whereas Component-B uses the InlineContainer (presumably because Component-B is a highly trustworthy Client Application from a security perspective).


ManagedHubMessagePassing.png


In some cases, Component-B's publish function might return before Component-A's callback is invoked.

Sample source code

The following sections provide sample source code for the scenario pictured above. The source code shown in the sections below are pasted out of the OpenAjax Alliance open source project, within folder hub20/samples/spec/ManagedHubOverview/. This folder contains instructions for how to set up a Web server to run the sample application.

Manager Application source code

The following source code depicts how the Manager Application's HTML and JavaScript might look to produce the scenario pictured above.

<html>
<head>
  <title>Manager Application</title>

  <!-- 
    Load the OpenAjax Hub before loading other Ajax libraries. 
    This example uses the "release/all" configuration of the Hub.
  -->
  <script src="../../../release/all/OpenAjaxManagedHub-all.js"></script>

  <!-- 
    Next, load any other non-OpenAjax JavaScript libaries that you need: 
  -->
  <script src="xhr.js"></script> 
  
  <!-- 
    Begin application JavaScript:
  -->
  <script type="text/javascript">

    /* 
     * Security Manager Callbacks 
     */

    function onMHPublish(topic, data, publishContainer, subscribeContainer) {
      /* Callback for publish requests. This example approves all publish requests. */
      return true;
    }
    function onMHSubscribe(topic, container) {
      /* Callback for subscribe requests. This example approves all subscribe requests. */ 
      return true;
    }
    function onMHUnsubscribe(topic, container) {
      /* Callback for unsubscribe requests. This example approves all subscribe requests. */ 
      return true;
    }
    function onMHSecurityAlert(source, alertType) {  /* Callback for security alerts */  }

    /* Application initializes in response to document load event */

    function loadEventHandler() {
      var mashupArea = document.getElementById("mashupArea");

      /* 
       * Create a Managed Hub instance 
       */

      var managedHub = new OpenAjax.hub.ManagedHub(
            { 
              onPublish:       onMHPublish,
              onSubscribe:     onMHSubscribe,
              onUnsubscribe:   onMHUnsubscribe,
              onSecurityAlert: onMHSecurityAlert 
            }
      );

      /* 
       * Create an InlineHubClient and InlineContainer for client1
       */

      function onClientSecurityAlert(source, alertType) {  /* Handle client-side security alerts */  }
      function onClientConnect(container) {        /* Called when client connects */   }
      function onClientDisconnect(container) {     /* Called when client disconnects */ }

      /* Create an InlineContainer for this HubClient */

      window.container1 = new OpenAjax.hub.InlineContainer(managedHub , "client1",
        {
          Container: {
            onSecurityAlert: onClientSecurityAlert,
            onConnect:       onClientConnect,
            onDisconnect:    onClientDisconnect
          }
        }
      );

      var div1 = document.createElement( "div" );
      xhrGet("ClientApp1.html", function(responseText) { 
        div1.innerHTML = responseText;
        // Dynamically loaded SCRIPT elements don't execute.
        // The following example logic finds SCRIPT elements, extracts JS content, and executes it.
        responseText.replace(/<script\s*(?:[^>]*?(?:src=(['"]?)([^>]*?)\1[^>]*)?)*>([\s\S]*?)<\/script>/gi, 
          function(ignore, delim, src, code){
            (new Function(code)).call(window);
          }
        );
      }, function(e) {
        alert('XMLHttpRequest failed');
      });
      mashupArea.appendChild(div1);

      /* 
       * Create an IframeContainer for client2
       */

      /*  
       * NOTE: If we wish to completely isolate ClientApp2 from the manager
       * and from all other client applications, the uri parameter container2
       * must have a different subdomain from the main application and all other
       * client applications. In this case, the main application has a URL
       * http://mashup.foo.bar.com/something, and we set client2's URI to
       * c0.foo.bar.com
       */

      var subdomain2 = "c0.foo.bar.com";
      var div2 = document.createElement( "div" );
      mashupArea.appendChild(div2);
      var container2 = new OpenAjax.hub.IframeContainer(managedHub , "client2",
        {
          Container: {
            onSecurityAlert: onClientSecurityAlert,
            onConnect:       onClientConnect,
            onDisconnect:    onClientDisconnect
          },
          IframeContainer: {
            // DOM element that is parent of this container:
            parent:      div2, 
            // Container's iframe will have these CSS styles:
            iframeAttrs: { style: { border:"black solid 1px" }},
            // Container's iframe loads the following URL:
            uri: "http://" + subdomain2 + "/hub20/samples/spec/ManagedHubOverview/ClientApp2.html",
            // Tunnel URL required by IframeHubClient. This particular tunnel URL 
            // is the one that corresponds to release/all/OpenAjaxManagedHub-all.js:
            tunnelURI:  "http://mashup.foo.bar.com/hub20/release/all/tunnel.html"
          }
        }
      );
    }
  </script>
  <body onload="loadEventHandler()">
    <div id="mashupArea"></div>
  </body>
</html>

ClientApp1 source code

The following illustrates a sample code snippet (including JavaScript logic) for ClientApp1. Since ClientApp1 has been loaded into an InlineContainer, the code snippet below should be inserted into the Manager Application as child content of the "div1" element. (See Manager Application example above.)

When ClientApps creates its InlineContainer, it must pass the corresponding InlineContainer object into the InlineHubClient constructor.

<script type="text/javascript">

  // Handle security alerts:
  function client1SecurityAlertHandler(source, alertType) {
  }

  // Callback called when a subscription receives data
  function onData(topic, publisherData, subscriberData) {
    if (typeof publisherData === "string") {
      var messageArea = document.getElementById('messageArea');
      // XSS protection: createTextNode strips HTML markup
      var text = document.createTextNode(publisherData);
	  messageArea.innerHTML = ""; 
	  messageArea.appendChild(text);
    }
  }

  /* 
   * Create a OpenAjax.hub.InlineHubClient
   */

  var hubclient1 = new OpenAjax.hub.InlineHubClient({
    HubClient: {
      onSecurityAlert: client1SecurityAlertHandler
    },
    InlineHubClient: {
      container: container1
    }
  });

  // Callback that is invoked when HubClient's attempt to connect
  // to the Managed Hub completes 
  function clientApp1HubClientConnect( hubClient, success, error ) {
    if (success) {
      /* Call hubClient1.publish(...) to publish messages  */
      /* Call hubClient1.subscribe(...) to subscribe to message topics */
      hubclient1.subscribe('org.example.topics.textmessage', onData);
    }
  }

  // Connect to the ManagedHub
  hubclient1.connect( clientApp1HubClientConnect );

</script>

<div style="width:300; height:150; border:black solid 1px">
  <h3>ClientApp1 content</h3>
  <p>Messages received appear below:</p>
  <p id="messageArea"></p>
</div>

ClientApp2 source code

The following illustrates sample source code for ClientApp2. ClientApp2 uses the IframeContainer, which requires that the Client Application consist of a separate Web page.

<html>
<head>
  <title>ClientApp2 </title>

  <!-- Load the OpenAjax Hub. This example uses the "release/all" configuration -->
  <script src="/hub20/release/all/OpenAjaxManagedHub-all.js"></script>
  <script type="text/javascript">
    function client2SecurityAlertHandler(source, alertType) {
      // Handle security alerts
    }

    /* Callback that is invoked upon successful connection to the Managed Hub */
    function connectCompleted ( hubClient, success, error ) {
      if (success) {
        /* Call hubClient.publish(...) to publish messages  */
        /* Call hubClient.subscribe(...) to subscribe to message topics */
      }
    }

    /* Application initializes in response to document load event */
    function loadEventHandler() {
      hubClient = new OpenAjax.hub.IframeHubClient({
        HubClient: {
          onSecurityAlert: client2SecurityAlertHandler
        }
      });

      // Connect to the ManagedHub
      hubClient.connect( connectCompleted );
    }

    function clickEvent() {
      hubClient.publish('org.example.topics.textmessage','Message from ClientApp2');
    }
  </script>
</head>
<body onload="loadEventHandler();">
  <div style="border:black">
    <h3>ClientApp2 content</h3>
	<p>
	  <input type="button" value="Click to send message" onclick="clickEvent()"/>
	</p>
  </div>
</body>
</html>

Built-in Container Types

The OpenAjax Hub 2.0 standard defines two built-in Containers:

  • IframeContainer - This container sandboxes its Client Application into an HTML <iframe> element. Any messages to/from the Client Application are marshalled across the iframe boundary between the Client Application and the Manager Application.
  • InlineContainer - This container places its Client Application within the same browser frame as the Manager Application.

The inline container tends to be faster and require less memory than the IframeContainer; however, it does not sandbox or isolate the Client Application. Therefore, an InlineContainer can be safely used only when a Client Application can be trusted with complete access to the HTML DOM of the Manager Application, including all business information contained therein. Any Client Application that might contain untrusted or malicious script, and which should therefore be isolated from the Manager Application and all other Client Applications, should always be sandboxed in an IframeContainer.

Notes:

  • A Client Application that is "trusted" (InlineContainer allowed) in the context of one Manager Application might not be "trusted" in the context of a different Manager Application.
  • If your company's IT department controls a Manager Application, then the IT department might allow some of its home-grown Client Applications to use InlineContainers, but would likely require that Client Applications developed by other vendors be sandboxed in IframeContainers.
  • Vendors and customers may develop additional types of Containers.



<--previous       contents--^       next-->
Personal tools