<section title="Inter-Gadget Eventing" anchor="interGadgetEventing">
<t>The inter-gadget eventing feature, common known as "pub/sub", provides
for loosely-coupled and asynchronous inter-gadget communication based
on the <eref target="http://www.openajax.org/member/wiki/OpenAjax_Hub_2.0_Specification_Introduction">
OpenAjax Hub 2.0</eref> specification.</t>
<t>The "pub/sub" feature provides:
<list style="symbols">
<t>An event hub, provided by the container and fully compliant
with OpenAjax Hub 2.0, that manages the subscription and publication
of events,</t>
<t>Methods for publishing and subscribing to events, and </t>
<t>Mechanisms for declaratively specifying metadata within
a gadget's XML definition relevant to publishing and subscribing
to events.</t>
</list>
</t>
<t>The process is straightforward:
<list style="symbols">
<t>First, a container that supports the "pub/sub" feature needs to
initialize the Hub and all default settings.</t>
<t>Second, a container can bootstrap and simplify the connection of
a gadget to the hub by registering an onLoad handler using the
gadgets.util.registerOnLoadHandler API. </t>
<t>Third, once the Hub is initialized by the container, individual gadget's
that declare support for the "pubsub-2" feature using either the
"Optional" or "Required" tag within the Gadget specifications
"ModulePrefs" can use the provided JavaScript APIs to publish
events to the hub using "topics", or use the JavaScript APIs to
subscribe to "topics" published by the Hub. When a gadget publishes
and event to the Hub using a specific topic, all gadget's connected
to that Hub and subscribed to the same topic will receive a copy
of the event.</t>
</list>
</t>
<t>A "topic" is a String value that conforms to the OpenAjax Hub 2.0
specification's <eref target="http://www.openajax.org/member/wiki/OpenAjax_Hub_2.0_Specification_Topic_Names">Topic Name Rules</eref>.
All topic names prefixed with "org.opensocial." are reserved for use by
the OpenSocial specification. Developers MUST NOT use the "org.opensocial."
prefix when defining their own topics.</t>
<section title="Initializing the Hub within the Container" anchor="ContainerExample">
<t>The following example illustrates a non-normative example how a
container could provide support for this feature.</t>
<list style="numbers">
<t>Set default values:
<artwork type="code">
// Create a pubsub settings object
gadgets.HubSettings = {};
// Set default HubClient constructor params object
gadgets.HubSettings.params = {
HubClient: {
onSecurityAlert: function( alertSource, alertType ) {
alert( "Gadget stopped attempted security breach: " + alertType );
window.location.href = "about:blank"; // Forces container to see Frame Phish alert and probably close this gadget
},
scope: gadgetInstance
} };
// Set default onComplete function for HubClient.connect
gadgets.HubSettings.onConnected = function( hub, suc, err ) { };
</artwork>
</t>
<t>
Register an onLoad handler
<t>An onLoad handler to actually create the HubClient and connect it
to the ManagedHub. Delaying the HubClient creation and
connection allows the gadget to override default values stored
in gadgets.HubSettings. For example, IframeHubClient
supports params properties such as seed, tokenLength and log,
which are not set by default; and a gadget might need to
override onSecurityAlert and/or scope, for which default values
are provided. More importantly, the onComplete function for
HubClient.connect usually sets up the gadget's subscriptions by
calling gadgets.Hub.subscribe, or if the connection fails
asynchronously, the onComplete function handles the error.</t>
<artwork type="code">
// Register an onLoad handler
gadgets.util.registerOnLoadHandler( function() {
try {
// Create the HubClient.
gadgets.Hub = new OpenAjax.hub.IframeHubClient( gadgets.HubSettings.params );
// Connect to the ManagedHub
gadgets.Hub.connect( gadgets.HubSettings.onConnect );
} catch(e) {
// TODO: error handling should be consistent with other OS gadget initialization error handling
}
} );
</artwork>
</t>
</list>
</section>
<section title="Gadget Examples" anchor="GadgetExample">
<t>The following illustrates a non-normative example of a gadget that
subscribes to a topic published by the Hub.</t>
<t>Note that, by default, all of the necessary defaults parameters
on the underlying HubClient connected for the gadget were initialized
when the gadget was loaded. If the gadget developer wishes to override the
default parameters to the HubClient constructor, it can do so by
setting values on gadgets.HubSettings as illustrated in the example.</t>
<figure><artwork type="code">
<Module>
<ModulePrefs title="Sample PubSub Subscriber" height="250">
<Require feature="pubsub-2">
<Param name="topics"><![CDATA[
<Topic title="Random Number"
name="org.apache.shindig.random-number"
description="Subscribes to random number generator."
type="number"
subscribe="true"/>
]]></Param>
</Require>
</ModulePrefs>
<Content type="html"><![CDATA[
<script>
var subId;
// Example of setting a parameter to the HubClient used by pubsub-2 feature.
gadgets.HubSettings.params.HubClient.onSecurityAlert = function(alertSource, alertType) {
alert("SECURITY ERROR!");
window.location.href = "about:blank";
};
function callback(topic, data, subscriberData) {
document.getElementById("output").innerHTML =
"message : " + gadgets.util.escapeString(data + "") + "<br/>" +
"received at: " + (new Date()).toString();
}
function subscribe() {
subId = gadgets.Hub.subscribe("org.apache.shindig.random-number", callback);
}
function unsubscribe() {
gadgets.Hub.unsubscribe(subId);
document.getElementById("output").innerHTML = "";
}
</script>
<div>
<input type="button" value="Subscribe" onclick="subscribe()"/>
<input type="button" value="Unsubscribe" onclick="unsubscribe()"/>
</div>
<div id="output"></div>
]]></Content>
</Module>
</artwork></figure>
<t>Similarly, below is a non-normative example of a gadget that
publishes events to the Hub:</t>
<figure><artwork>
<Module>
<ModulePrefs title="Sample PubSub Publisher" height="250">
<Require feature="pubsub-2">
<Param name="topics">
<![CDATA[
<Topic title="Random Number"
name="org.apache.shindig.random-number"
description="Publishes a random number."
type="number"
publish="true" />
]]></Param>
</Require>
</ModulePrefs>
<Content type="html"><![CDATA[
<script>
function publish() {
var message = Math.random();
gadgets.Hub.publish("org.apache.shindig.random-number", message);
document.getElementById("output").innerHTML = message;
}
</script>
<div>
<input type="button" value="Publish a random number" onclick="publish()"/>
</div>
<div id="output"></div>
]]></Content>
</Module>
</artwork></figure>
</section>
<section title="gadgets.Hub" anchor="gadgets.Hub">
<section title="Method Details">
<section title="publish" anchor="publish">
<t>publish(topic, payload)</t>
<t>Description: The publish method conforms to the semantics of the
OA Hub. The OAHub embraces the notion that pubsub is anonymous and
does not automatically include any information about the
identification of the publishing gadget with the message. The
following is an excerpt from their documentation.</t>
<t>Parameters:
<texttable align="left">
<ttcol>Name</ttcol>
<ttcol>Type</ttcol>
<ttcol>Description</ttcol>
<c>topic</c>
<c>String</c>
<c>A string that conforms to the rules defined above and by the
OA Hub to name the channel that the payload will be deliverd on.
Wildcards are NOT permitted.</c>
<c>payload</c>
<c>*</c>
<c>It is permissible to publish any object. The payload MUST
be serializable to JSON.</c>
</texttable>
</t>
<t>See the <eref target="http://www.openajax.org/member/wiki/OpenAjax_Hub_2.0_Specification_Managed_Hub_APIs#OpenAjax.hub.Hub.prototype.publish">OpenAjax Hub 2.0 documentation</eref> for more information.</t>
<section title="subscribe" anchor="subscribe">
<t>subscribe(topic, callback [,scope [,onCompleteCallback [,subscriberData]]])</t>
<t>Description: The subscribe method is used to indicate to the
hub the topic from which the gadget is interested in receiving
information. When information is published on the topic, the hub
will invoke the callback method on the gadget. Since a gadget may
have multiple subscriptions on the same topic, the subscribe
method returns an opaque identifier that is used to uniquely
identify the subscription. This identifier is used to unsubscribe
to the topic. It is gadget developer's responsibility to manage
this identifier.</t>
<t>Parameters:
<texttable align="left">
<ttcol>Name</ttcol>
<ttcol>Type</ttcol>
<ttcol>Description</ttcol>
<c>topic</c>
<c>String</c>
<c>A string that conforms to the rules defined above and by the OA Hub
to name the channel that the payload will be deliverd on. Wildcards
MAY be used.</c>
<c>callback</c>
<c>String</c>
<c>A callback function to be executed when the tab is selected. The
callback function will not be called until after the existing
callstack has completed execution.</c>
<c>scope</c>
<c>object</c>
<c>When onData callback or onComplete callback is invoked, the
JavaScript "this" keyword refers to this scope object. If no scope is
provided, default is window.</c>
<c>onCompleteCallback</c>
<c>function</c>
<c>Function invoked to tell the client application whether the
subscribe operation succeeded or failed.</c>
<c>subscriberData</c>
<c>*</c>
<c>Client application provides this data, which is handed back to the
client application in the subscriberData parameter of the onData
callback function.</c>
</texttable>
</t>
<t>Returns:
<texttable align="left">
<ttcol>Type</ttcol>
<ttcol>Description</ttcol>
<c>String</c>
<c>An opaque subscription identifier. This identifier is an arbitrary
ID string that is unique within this Hub instance</c>
</texttable>
</t>
<t>See the <eref target="http://www.openajax.org/member/wiki/OpenAjax_Hub_2.0_Specification_Managed_Hub_APIs#OpenAjax.hub.Hub.prototype.subscribe">OpenAjax Hub documentation</eref> for
more information</t>
</section>
<section title="unsubscribe" anchor="unsubscribe">
<t>unsubscribe(subscriptionId)</t>
<t>Description: This method is used to remove a subuscription for a
gadget from the hub. The unsubscribe function immediately throws an
exception if there is no subscription with the specified subscription
ID. Otherwise, unsubscribe immediately deactivates the subscription.
</t>
<t>Parameters:
<texttable align="left">
<ttcol>Name</ttcol>
<ttcol>Type</ttcol>
<ttcol>Description</ttcol>
<c>subscriptionId</c>
<c>String</c>
<c>The subscriptionId is the opaque string that is returned from the
subscribe(...) method.</c>
</texttable>
</t>
<t>See the <eref target="http://www.openajax.org/member/wiki/OpenAjax_Hub_2.0_Specification_Managed_Hub_APIs#OpenAjax.hub.Hub.prototype.unsubscribe">OpenAjax Hub documentation</eref> for
more information.</t>
</section>
</section>
<section title="Other Methods" anchor="OtherMethods">
<t>The 'gadgets.Hub' object is an instance of IframeHubClient and supports some additional methods.
Please see the <eref target="http://www.openajax.org/member/wiki/OpenAjax_Hub_2.0_Specification_Managed_Hub_APIs#OpenAjax.hub.IframeHubClient">OpenAjax Hub documentation</eref> for more information.</t>
</section>
</section>
</section>
<section title="Wiring Metadata">
<t>As illustrated by the previous example gadgets, the "pub/sub" feature
provides a means of allowing gadget developers to declaratively describe
the topics their gadget's support directly within the feature declaration
within the "ModulePrefs" element.</t>
<figure><preamble>For example:</preamble>
<artwork>
<Module>
<ModulePrefs title="Sample PubSub Publisher" height="250">
<Require feature="pubsub-2">
<Param name="topics">
<![CDATA[
<Topic title="Random Number"
name="org.apache.shindig.random-number"
description="Publishes a random number."
type="number"
publish="true" />
]]></Param>
</Require>
</ModulePrefs>
...
</Module>
</artwork></figure>
<t>When gadgets use the <Topic> element, containers are able
to "wire" gadgets together either automatically or via a user interface
that allows a user to connect gadgets that publish events to a given
topic to gadgets that subscribe to those events.</t>
<t>The <Topic> element has the following attributes:</t>
<texttable align="left">
<ttcol>Attribute</ttcol>
<ttcol>Type</ttcol>
<ttcol>Usage</ttcol>
<ttcol>Description</ttcol>
<c>name</c>
<c>String</c>
<c>Required</c>
<c>
The dot-delimited topic name, e.g. "org.example.randomNumber". This
name follows the rules defined in the <eref target="http://www.openajax.org/member/wiki/OpenAjax_Metadata_1.0_Specification_Widget_Metadata#topic_element_name_attribute">OpenAjax Widget Metadata
specification</eref>. Developers of gadgets MAY allow the @name attribute to be ovveridden using user preference variables. See <xref target="usingVariablesForNameAttribute">Using Varuables for @name</xref></c>
<c>type</c>
<c>String</c>
<c>Optional</c>
<c>Type name for the event's payload data. When not specificed, any
type wil be allowed. See <xref target="EventDataTypes">Event Data Types</xref>.</c>
<c>title</c>
<c>String</c>
<c>Optional</c>
<c>Title for this type of event that is appropriate for a non-technical reader. When not specified, the value of the "name" attribute will be used.</c>
<c>publish</c>
<c>boolean</c>
<c>Optional</c>
<c>Indicates if the gadget publishes events on this topic. The default value is "false".</c>
<c>subscribe</c>
<c>boolean</c>
<c>Optional</c>
<c>Indicates if the gadget subscribes to events that are published on this topic. The default value is "false".</c>
<c>description</c>
<c>String</c>
<c>Optional</c>
<c>
The textual description of the gadget's publish or subscribe
endpoint.
This can be used as an indication of the gadget's behavior.
Consider a gadget that subscribes to a topic "com.example.address".
The description migh read, "When this gadget receives an event on the com.example.address
topic, it displays mass transit options within 10km of the address received as the event payload."</c>
<c>aboutUrl</c>
<c>String</c>
<c>Optional</c>
<c>
A URL pointing to a resource that provides more extensive
descriptive information than can be provided in the description
attribute.</c>
</texttable>
<section title="Using Variables for @name" anchor="usingVariablesForNameAttribute">
<t>In the absence of a specific standard for events within a given
domain, it is inevitable that different groups of developers,
working in different niches on similar problems, will use different
topic naming schemes for what is essentially the same event. While
some developers in a domain may eventually consolidate around a
standard set of topic names, it's also inevitable that installed
bases, legacy implementations, politics, requirement to integrate
with third party gadgets from other domains, schedule constraints
and other factors will ensure that once a topic space becomes
balkanized, it will remain that way for a long time.</t>
<t>It is important that the specification offer a mechanism that allows
developers to bridge simple mismatches between gadgets. It is
important that gadget developers use this mechanism where possible.
This will maximize the reusability of gadgets -- a major goal.</t>
<figure><preamble>The following is an example showing the use of
variable substituion in the definition of the @name attribute.</preamble>
<artwork xml:space="preserve">
<Require feature="pubsub-2">
<Param name="topics"><![CDATA[
<Topic title="Selected Location" name="__UP_location__"
description="The currently selected location" type="http://nsgs.gov/geo#Place"
publish="false" subscribe="true" aboutUrl="http://nsgs.gov">
</Topic>
<!-- etc. for other topics -->
]]></Param>
</Require>
</artwork></figure>
</section>
<section title="Event Data Types" anchor="EventDataTypes">
<t>The OpenAjax Hub has a predefined set of identifiers that are used
to indicate the data type. Tooling and runtime container code can use
this to infer information about the messages being published
as well as the parameters a gadget expects to receive when it
subscribes to a topic.</t>
<t>The data types provided by the OpenAjax Hub are "built in". These
are referred to as the OpenAjax common types, and they require no
namespace qualifier. When a type other than an OpenAjax common type
is used, it MUST contain a namesake qualifier. The namespace should
conform to reverse DNS rules. The namespace org.opensocial.* MUST NOT be
used and is reserved for types defined by this specification,
e.g. social data types.</t>
<texttable align="left">
<ttcol>Type Name</ttcol>
<ttcol>Comments</ttcol>
<c>string</c>
<c>ECMAScipt string</c>
<c>number</c>
<c>ECMAScipt number </c>
<c>boolean</c>
<c>ECMAScipt boolean </c>
<c>array</c>
<c>ECMAScipt array, e.g. [ 1, 1, 2, 3, 5, 8 ]. The element type/s are not specified when the generic "array" type is used.</c>
<c>object *</c>
<c>ECMAScipt object, e.g. { foo: "bar", baz: "boo" }. The specifics of the object are not specified when the generic "object" type is used.</c>
<c>null *</c>
<c>ECMAScipt null</c>
<c>length *</c>
<c>Any CSS length value <span style="color:red"> Howard 2009.11.10: CSS version?</span></c>
<c>color *</c>
<c>Any CSS color value</c>
<c>id</c>
<c>ID value - probably not useful for OpenSocial Gadgets, but might as well keep the two specs in sync</c>
<c>class *</c>
<c>zero of more CSS class names, separated by spaces</c>
<c>style *</c>
<c>a string that could be used as value for a 'style' attribute</c>
<c>url</c>
<c>A URL <span style="color:red"> Howard 2009.11.09: Do we want "uri" also?</span></c>
<c>html</c>
<c>A fragment of HTML markup.</c>
<c>countrycode *</c>
<c>A string that represents an [http://www.iso.org/iso/country_codes/iso_3166_code_lists.htm A3 ISO 3166 country code].</c>
<c>languagecode *</c>
<c>A string that represents an [http://www.loc.gov/standards/iso639-2/php/code_list.php ISO 639-2 language code].</c>
<c>email</c>
<c>A string that represents an e-mail address.</c>
<c>person</c>
<c>A string that holds a person's name.</c>
<c>postalcode</c>
<c>A string that represents a postal code.</c>
<c>phone</c>
<c>A string that represents a phone number.</c>
<c>date *</c>
<c>A string that represents a date. MUST be expressed using the "Date Time String Format" defined in the [http://www.ecmascript.org/docs/tc39-2009-043.pdf ECMAScript5 specification] using one of the date-only forms. For example: "2009-12-15"</c>
<c>time *</c>
<c>A string that represents a time of day. MUST be expressed using the "Date Time String Format" defined in the [http://www.ecmascript.org/docs/tc39-2009-043.pdf ECMAScript5 specification] using one of the time-only forms. For example: "18:45:00Z" or "10:26:24-05:00"</c>
<c>timestamp *</c>
<c>A string that represents a date and time of day. MUST be expressed using the "Date Time String Format" defined in the [http://www.ecmascript.org/docs/tc39-2009-043.pdf ECMAScript5 specification]. For example: "2009-12-15:18:45.000Z"</c>
<c>duration *</c>
<c>A string that represents a duration. MUST have format "PYYYY-DDDThh:mm:ss.fff". For example, "P0400-152T20:45:33.123" means "400 years, 152 days, 20 hours, 45 minutes, 33.123 seconds, while "P0003-000T01:56:22.000" means "3 years, 1 hour, 56 minutes and 22.000 seconds." (Must use this one variant defined in the ISO 8601 standard). </c>
<c>*</c>
<c>Asterisk, or missing type attribute, means "any datatype"</c>
</texttable>
</section>
</section>
</section>