OpenSocial is a community-driven specification that defines a browser-based component model, known as gadgets, and an API for accessing information about users' profile information, as well as their social graph (including things such as their friends and activities). Applications implementing the APIs will be interoperable with a broad set of social networking sites such as: iGoogle, MySpace, Yahoo, Orkut, Hi5, LinkedIn, and others. In this article, we will focus on OpenSocial gadgets and show how they can be a powerful way to extend the reach of your application across the Web.
What is an OpenSocial gadget?
- An OpenSocial gadget is the small presentation of a Web application that implements a specific set of APIs. A gadget is described by an XML document that conforms to the OpenSocial specification. This definition contains the user interface such as HTML, CSS stylesheets, and JavaScript for the business logic, and additional metatdata for the author, title, and so on.
- A site that implements the OpenSocial specification and can host applications is called an OpenSocial container. This means that it can process the gadget XML definitions, and serve up the proper HTML to the browser. It's important to realize that the gadget definitions are not required to be hosted on the site that provides the container. Further, gadgets typically expose a service from a completely different site. The container provides mechanisms, such as signed HTML requests, to provide a level of assurance that the calls originated from the gadget in its site. By being an OpenSocial container, a site can provide an easy way to aggregate a collection of services from across the Web.
This page provides the user a facility to test the basic set of functions provided by the Universal Services and displays the results to the user.
Figure 1 is a screen capture of the sample test application. This will serve as the template you use to build the sample OpenSocial gadget. This provides the user with the basic UI capabilities required to interact with the Universal Services.
Figure 1. The sample test application
First, you will create a few JavaScript functions to provide the basic queries that control the connections to the pureXML services. Then you will add the supporting HTML along with the gadget specification. Finally, you see how to create and deploy this application.
JavaScript functions to connect to pureXML services
Listing 1 provides the sample JavaScript that was created to handle the requests.
Listing 1. PureJSON JavaScript functions
var prefs = new gadgets.Prefs();
function getPrimaryKeys() {
var args = {};
doPOST("getPrimaryKeys",args,displayJSONobj);
};
function getJSONDocumentByKey(key) {
var args = {
id: key
};
doPOST("getDocumentByKey",args,displayJSONobj);
};
function insertJSON(key, data) {
var args = {
id: key,
doc: data
};
doPOST("insert",args,response);
};
function updateJSON(key, data) {
var args = {
id : key,
doc : data
};
doPOST("update",args,response);
};
function deleteDocument(key) {
var args = {
id : key
};
doPOST("delete",args,response);
};
function doPOST(command,args,processResponseCallback) {
var url = "http://" + prefs.getString("pureXMLHostAddress") +
"/" + prefs.getString("contextRoot") + "/query/"+command;
var params = {};
postdata = gadgets.io.encodeValues(args);
params[gadgets.io.RequestParameters.METHOD] = gadgets.io.MethodType.POST;
params[gadgets.io.RequestParameters.POST_DATA]= postdata;
gadgets.io.makeRequest(url, processResponseCallback, params);
};
function response(obj) {
alert("Gadget implementation responsibility.");
};
function displayJSONobj(obj) {
alert("Gadget implementation responsibility.");
};
|
Look at the purpose of each function:
getPrimaryKeysposts a getPrimaryKeys request to the service to retrieve all primary keys from the DB2 table and display the result using the callback functiondisplayJSONobjwhen the transaction is completed.getJSONDocumentByKeyuses a key value to post a getDocumentByKey to the service to retrieve a single JSON record with the primary key matching the input value. It displays the result using the callback functiondisplayJSONobj.insertJSONexpects two input parameters: the unique key value for primary key and the row data in JSON format. It posts a request to the service to create a new row in the DB2 table, and confirms the insert status when the transaction returns using the callback functionresponse.updateJSONprovides the capability to post a request to the service to update a JSON record with the primary key matching the input key value, and the updated data specified as the input data in JSON format. It will also invoke the callback functionresponseto confirm the update when the transaction completes.deleteDocumentprovides the interface to post a remove record request to the service based on the specified input primary key. It also invokes theresponsecallback function to confirm the deletion after the request completes.displayJSONobjis an abstract JavaScript function that provides a hook for developers to provide different approaches to rendering the results of the call in the browser.responseis a function that handles return values that are not JSON. It follows a similar strategy as displayJSONobj by expecting developers to override the function with their own implementation.
The above functions call the doPOST function to submit their requests.
The doPOST function expects the service query command, query input values,
and a callback function to process the result returned from the services. It uses these input parameters
to build gadgets.io.makeRequest calls to the services. gadgets.io.makeRequest is an OpenSocial
gadgets function which provides the support for gadgets to get data from and post data to third party sites.
Its signature looks like this:
gadgets.io.makeRequest(url, callback, opt_params)
The parameters are:
url- A string containing the URL of the site you want to send the request to. You can see that, to build the URL, thedoPOSTfunction retrieves two strings from theprefsobject using thegetStringmethod. (The parameters,pureXMLHostAddressandcontextRoot, refer to element names in the gadget definition, which we cover in the next section.) These two strings are concatenated with/query/and the command (insert, getDocumentByKey, update, delete,and so on). For example, when theinsertJSON()function invokesdoPOST, the URL is:
http://xmlim.watson.ibm.com:9080/JSONUniversalServices/query/insertcallback- A reference to a function that will be called when the request returns. For example,responseis a callback function that displays the status of a transaction, anddisplayJSONobjis a callback function that displays the returned JSON object or a message if the object is empty.opt_params- A JavaScript object containing additional parameters for the call (the HTTP method and the POST data). We set the HTTP method of the request togadgets.io.MethodType.POSTto indicate it is a POST method. We also pass the post data in thepostdataobject (specified as an object containing key/value pairs by usinggadgets.io.encodeValues()to format the inputargs).
Save Listing 1 as PureJSON.js. You will build the gadget definition and load this file in the next step.
Now that you have the necessary JavaScript, you will create the gadget definition.
Create a gadget definition XML
You need a simple gadget definition. Listing 2 provides the sample gadget definition.
Each gadget definition is enclosed in a <Module> tag.
The <ModulePrefs> defines the basic information and features for the gadget.
Listing 2. The XML definition for the OpenSocial gadget
<?xml version="1.0" encoding="UTF-8"?> <Module> <ModulePrefs title="Universal Services"> <Require feature="opensocial-0.8"/> <Require feature="dynamic-height"/> <Require feature="minimessage"/> </ModulePrefs> <UserPref name="pureXMLHostAddress" display_name="PureXML Host Address" default_value="xmlim.watson.ibm.com:9080"/> <UserPref name="contextRoot" display_name="Context Root" default_value="JSONUniversalServices"/> <Content type="html"> <![CDATA[ <!-- Note: We will add more code and expand this section later --> ]]> </Content> </Module> |
The first thing you'll notice in the gadget definition is the <title>
attribute on the <ModulePrefs> element. You can
specify attributes defining information for the gadget such as title, author, e-mail, and so on. For the purpose this demo,
we'll use only the title
attribute. It's important to note, however, that some containers require certain attributes to be provided for
live deployment. You'll need to refer to the platform developer documentation for
this information.
You'll also provide features that the gadget requires. The sample gadget will load the following features:
opensocial-0.8- This gadget uses the OpenSocial version 0.8 implementation APIs and therefore it can be deployed on containers that support OpenSocial v0.8 specification.dynamic-height- With this feature, the gadget developer has the ability to resize the gadget height as content is added or removed. This is invoked when you display or remove the DB2 transaction messages in the gadget.minimessage- This feature provides a set of APIs to create and display messages to users within the gadget. We useminimessageto create DB2 transaction status messages in this example.
You also defined a set of user preferences (<UserPref>) to dynamically set the pureXML
Universal Service endpoint and the context path of the application that the gadget will be deployed to.
The defined <UserPref> elements are exposed as user input in the gadget interface when the gadget is rendered. The user can
then edit and modify these settings appropriately. Note that the name attribute for these <UserPref> elements are the same names used in the JavaScript doPOST function in Listing 1 to get the strings used to construct the endpoint URL.
Fourth, the content section <Content> defines the content type of the gadget which is
HTML. Within the CDATA (character data) section, you define the gadget content itself where an HTML table is
created to capture user input, combined with minimessage, user preferences, and JavaScript functions to become
a running gadget. You will expand this section in the next step to build a client connecting to the pureXML services.
Within the CDATA section of gadget definition described in
the previous step, now add the sample HMTL table
and JavaScript functions to capture user input and actions.
First, add the stylesheet used in the HTML table as in Listing 3.
Listing 3. The stylesheet used for the table
<style type="text/css">
table.layout {border:0; width:50%;}
td.green {background-color:#BFFF80;
font-family:sans-serif, verdana;}
td.white {background-color:#FFFFFF;
font-family:sans-serif, verdana;}
th.green {background-color:#BFFF80;
font-family:sans-serif, verdana;}
th.white {background-color:#FFFFFF;
font-family:sans-serif, verdana;}
td.row-bright{background-color:#FFFFBF;
font-family:sans-serif, verdana;
text-align:center;}
td.row-dark {background-color:#FFFF8C;
font-family:sans-serif, verdana;
text-align:center;}
tr.row-bright {background-color:#FFFFBF;
font-family:sans-serif, verdana;}
tr.row-dark {background-color:#FFFF8C;
font-family:sans-serif, verdana;}
tr.empty {background-color:#FFFFFF;
height: 10px;}
tr.empty-small {background-color:#FFFFFF;
height: 5px;}
</style>
|
Second, include the JavaScript file, PureJSON.js from Listing 1. At the time the gadget is loaded,
the PureJSON.js will be included on the page making all the POST request functions available to the HTML table
actions.
Listing 4. Loading the JavaScript file
<script type="text/javascript" src="./PureJSON.js"></script>
|
Third, add another <script> tag as in Listing 5. Each JavaScript function matches a user action declared
in the HTML table (which you will define in the next section), and calls one of the functions defined in PureJSON.js
from Listing 1. When this
block of code is loaded, a minimessage object is created using new gadgets.MiniMessage(_MODULE_ID_).
Function gadgets.util.registerOnLoadHandler(gadgets.window.adjustHeight),
at the bottom of the tag, is called to register the gadget with the OpenSocial container, telling it to modify
the frame to fit the gadget content at render time. Within this script tag, we also override response
and displayJSONobj functions to display query result to users.
Listing 5. Adding gadget functions
<script type="text/javascript" src="./PureJSON.js"></script>
<script type="text/javascript">
var msg = new gadgets.MiniMessage(__MODULE_ID__);
function displayJSONobj(obj) {
var str = "The returned record is empty, it might not exist";
if(obj.text!=""){
str = obj.text;
}
msg.createDismissibleMessage(str);
gadgets.window.adjustHeight();
};
function callGetJSONDoc() {
getJSONDocumentByKey(document.getElementById("key1").value);
};
function getJSONDocumentByKeyReturn(obj) {
var str = obj.text;
msg.createDismissibleMessage(str);
gadgets.window.adjustHeight();
};
function callInsertJSON() {
insertJSON(document.getElementById("key2").value,
document.getElementById("document1").value);
};
function callUpdateJSON() {
updateJSON(document.getElementById("key3").value,
document.getElementById("document2").value);
};
function callDeleteDoc() {
deleteDocument(document.getElementById("key4").value);
};
function response(obj) {
var str = gadgets.json.parse(gadgets.util.unescapeString(obj.text));
if(str.updateCount == 1){
var successMsg = msg.createDismissibleMessage(
"Received returned code = 1. Transaction successful!");
successMsg.style.color = "green";
}
else {
var failMsg = msg.createDismissibleMessage(
"Did not receive returned code = 1. Transaction may have failed!");
failMsg.style.color = "red";
}
gadgets.window.adjustHeight();
};
gadgets.util.registerOnLoadHandler(gadgets.window.adjustHeight);
</script>
|
Finally, add the HTML table to capture the user input and actions. Listing 6 shows the HTML code. Save the gadget definition as JSONclient.xml. The screen capture in Figure 1 is what the table looks like when it is rendered.
Listing 6. The HTML table
<table class="layout" cellspacing="2">
<tr>
<th class="green">Web Service</th>
<th class="green" colspan="2">Input</th>
<th class="green">Action</th>
</tr>
<tr class="row-bright">
<td>getPrimaryKeys</td>
<td colspan="2" align="center">none</td>
<td align="center">
<input type="submit" value="Invoke" onClick="getPrimaryKeys()"/>
</td>
</tr>
<tr class="row-dark" >
<td>getJSONDocumentByKey</td>
<td align="right">ID:</td>
<td align="center"><input type="text" id="key1" size="40" /></td>
<td align="center">
<input type="submit" value="Invoke" onClick="callGetJSONDoc()"/>
</td>
</tr>
<tr class="row-bright">
<td rowspan="2">insertJSON</td>
<td align="right">ID:</td>
<td align="center"><input type="text" id="key2" size="40" /></td>
<td align="center" rowspan="2">
<input type="submit" value="Invoke" onClick="callInsertJSON()"/>
</td>
</tr>
<tr class="row-bright">
<td align="right">Document:</td>
<td align="center">
<textarea id="document1" cols="30" rows="5" ></textarea>
</td>
</tr>
<tr class="row-dark" >
<td rowspan="2">updateJSON</td>
<td align="right">ID:</td>
<td align="center"><input type="text" id="key3" size="40" /></td>
<td rowspan="2" align="center">
<input type="submit" value="Invoke" onClick="callUpdateJSON()"/>
</td>
</tr>
<tr class="row-dark">
<td align="right">Document:</td>
<td align="center">
<textarea id="document2" cols="30" rows="5" ></textarea>
</td>
</tr>
<tr class="row-bright">
<td>deleteDocument</td>
<td align="right">ID:</td>
<td align="center"><input type="text" id="key4" size="40" /></td>
<td align="center">
<input type="submit" value="Invoke" onClick="callDeleteDoc()"/>
</td>
</tr>
</table>
|
You will now deploy the gadget and then test the gadget.
To test the new Universal Services test application, you can simply deploy both the PureJSON.js and JSONclient.xml to an HTTP server. As long as the files are available through a URL, the OpenSocial container should be able to retrieve the gadget specification and render the content accordingly. An OpenSocial server has a number of options for both for local deployment available through open source projects as well as hosted platforms externally. For simplicity, you'll deploy this sample gadget to the iGoogle sandbox which will provide the OpenSocial container.
- Log into http://www.google.com/ig/sandbox
- Once logged in, navigate to the Add stuff link in the upper right section of the page. This will link to a page
that provides search capabilities for existing registered gadgets. See Figure 2. Note that the URL must be accessible from the Web.
For example, if you are running behind a firewall, then your deployment might not work because the gadget definition cannot be loaded
and processed by the OpenSocial container, in this case iGoogle. ((View a larger version of Figure 2.
Figure 2. Add applications to your iGoogle sandbox
- Next you need to add this new gadget by the URL. In the left navigation, you will see a link to Add feed or gadget. This will
open a dialog where you will need to put in the full URL for the JSONclient.xml. See Figure 3.
Figure 3. Add an OpenSocial gadget to the iGoogle sandbox
- You should now be able to return to your iGoogle home page and see the newly added gadget on your page.
Figure 4 shows the gadget rendered in iGoogle.
Figure 4. The gadget rendered in iGoogle
- To edit the gadget settings, select the triangle icon to open the options drop down list. Select Edit settings.
- Update the pureXML host address and the context root path to point to your universal services.
- In the getJSONDocumentByKey field, enter a document key to retrieve a JSON record, then click Invoke. To test other transactions, repeat this step.
- Minimessage displays the result. To remove the messages, select the x at the end of the row.
In this article, we provided a sample set of code that migrates the traditional test Web application to a configurable and portable application that can be quickly deployed to a number of platforms on the Web. While the application itself is relatively simple, this reference can be used to quickly assemble and prototype new applications. The OpenSocial gadget client provides users a convenient way to dynamically connect to any pureXML Universal Services through the UserPrefs support. With POST makeRequest, gadget developers can simply create queries connecting to the services to perform their database transactions. Gadget consumers can add the gadget to any OpenSocial container regardless where it is physically deployed and hosted keeping the consumers free of content and infrastructure management.
| Description | Name | Size | Download method |
|---|---|---|---|
| JavaScript POST request functions | PureJSON.js.zip | 1KB | HTTP |
| OpenSocial gadget definition XML | JSONclient.xml.zip | 2KB | HTTP |
Information about download methods
Learn
- Build a pureXML and JSON application, Part 1: Store and query JSON with DB2 pureXML (Nuno Job, Susan Malaika, and Michael Schenke; developerWorks, October 2009): See the first article in this series and begin to benefit from persisting JSON objects that maintain state across sessions. Store, manage, and query JSON with DB2 pureXML and a simple JSON-to-XML mapping. (Part 1 of three-part series.)
- Build a pureXML and JSON application, Part 2: Create Universal Services for pureXML that expose JSON (Faton (Tony) Avdiu, Susan Malaika, and Michael Schenke; developerWorks, October 2009): Following the steps in this article, you will expose the JSON data described in the first article in the series, through JSON Universal Services. (Part 2 of three-part series.)
- OpenSocial Community : Find links to articles, tutorials, and the technical specification and learn to embed OpenSocial APIs within a social network, to access or share social data on the Web.
- See the iGoogle Sandbox Development Guide : See details on OpenSocial support and application development and deployment in this environment.
- Apache Shindig: Explore this OpenSocial container to quickly host OpenSocial apps with code to render gadgets, proxy requests, and handle REST and RPC requests. This open source community is developing a reference implementation for the OpenSocial specification and deployment in this environment.
- IBM XML certification: Find out how you can become an IBM-Certified Developer in XML and related technologies.
- XML technical library: See the developerWorks XML Zone for a wide range of technical articles and tips, tutorials, standards, and IBM Redbooks.
- developerWorks technical events and webcasts: Stay current with technology in these sessions.
- developerWorks
podcasts: Listen to interesting interviews and discussions for software developers.
Get products and technologies
- DB2 Express-C: Download this no-charge community edition of the DB2 data server.
- IBM product evaluation versions: Download or explore the online trials in the IBM SOA Sandbox and get your hands on application development tools and middleware products from DB2®, Lotus®, Rational®, Tivoli®, and WebSphere®.
Discuss
- Participate in the discussion forum.
- XML zone discussion forums: Participate in any of several XML-related discussions.
- developerWorks blogs: Check out these blogs and get involved in the developerWorks community.

Han Nguyen is a software engineer working on emerging standards with a focus on Social Computing across various industry verticals and products. She has previously worked on several technologies both in the services and software enablement.

Andy Smith is a software engineer working on emerging standards with a focus on the application of Social Networking related technologies across various industry verticals and products. He has previously worked on various Web and portal technologies both in the services and software enablement.

Mark Weitzel is a Senior Technical Staff Member in IBM Software Group Emerging Standards and Open Source team focusing on social networking. Prior to this, Mr. Weitzel, as part of Tivoli Autonomic Computing team, was responsible for several open source systems management initiatives at Eclipse and Apache.
Comments (Undergoing maintenance)





