<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>
General
Content
Integrations