Developing widgets for IBM Mashup Center 1.0

This article introduces the widget programming model in IBM® Mashup Center: the IBM iWidget specification, widget basics, and the eventing service. To give you a better idea of how to build a widget from scratch, this article guides you as you develop a widget that can monitor the memory usage of the back-end server.

Qian Jie (Jove) Zhong (zhongqj@cn.ibm.com), Software Developer, Systems Documentation, Inc. (SDI)

Jove Zhong is the team leader of the IBM Lotus Mashups UI development team in Shanghai. He's been working for IBM for four years, mainly focusing on Flash- or AJAX-based rich Internet application development. You can reach Jove at zhongqj@cn.ibm.com.



Wei (Marshall) Shi (shiwcsdl@cn.ibm.com), Software Developer, Systems Documentation, Inc. (SDI)

Wei Shi (Marshall) is a Software Engineer on the IBM Lotus Mashups UI development team at China Lab. He is interested in Web 2.0 technology and has been working on related projects for more than two years. You can reach him at shiwcsdl@cn.ibm.com.



Zheng (Erik) Bi (bizheng@cn.ibm.com), Software Developer, Systems Documentation, Inc. (SDI)

Zheng Bi (Erik) is a Software Engineer on the IBM Lotus Mashups UI development team at the China lab, specializing in Java and Web technology. He has been involved in Web application development for more than two years. You can reach him at bizheng@cn.ibm.com.



Peng Yu (Joard) Zhang (zhangpy@cn.ibm.com), Software Developer, Systems Documentation, Inc. (SDI)

Peng Yu (Joard) Zhang is a Software Engineer on the IBM Lotus Mashups UI development team at the China lab. You can reach him at zhangpy@cn.ibm.com.



19 August 2008

Also available in Chinese

IBM Mashup Center, as the first integrated enterprise Web 2.0 mashup software platform in the industry, is a complete end-to-end mashup platform, supporting line-of-business assembly of simple, flexible, and dynamic Web applications, with the management, security, and governance capabilities that IT requires. IBM has created a lightweight widget model and defined a standard for widgets. As part of this effort, IBM is leading a new widget specification workgroup in OpenAJAX.

First, this article presents a simple Hello World widget with static text. Then, we show you how to upload the widget in IBM InfoSphere™ MashupHub and add it to the user palette. We next demonstrate how to add back-end Java™ code to the widget application and leverage AJAX technology to communicate with the server without a page refresh. Finally, this article covers a few advanced topics of widget development, such as communication among widgets, globalization support, and more.

Widget programming model

To develop new widgets for IBM Mashup Center, first you need to know the basics of the IBM iWidget specification and some key concepts.

IBM iWidget Specification V1.0

The widget development in IBM Mashup Center has adopted the evolving IBM iWidget specification and is based on V1.0 of this specification. This specification defines a simple, extensible browser-based component model. These components are called iWidgets. Different software vendors can provide different names for these components. Because of the lack of open standards, these shared concepts are all executed in different manners, eliminating interoperability of the components between different frameworks. This specification seeks to remedy this situation by defining an open standard that implements these shared concepts, and an extensibility model for surfacing other, more advanced concepts.

Widget basics

Let's first clarify several concepts, some of them from the IBM iWidget specification.

  • iWidget. A browser-oriented component, potentially extending a server-side component, that provides either a logical service to a page or a visualization for users (normally related to a server-side component or a configured data source).
  • Page. The larger entity being composed for presentation to a user. This entity can include both display and non-display iWidgets, each of which can come from a different source. The composition can change while it is being presented (for example, new iWidgets can be added to the composition) such that the exact definition of when a transition to a new page occurs is a policy decision left to the implementation that is managing the composition.
  • iContext. A context of the iWidget runtime that provides the overall management of the iWidget. This context includes any user interface (UI) controls, coordination between iWidgets, and interaction with the back-end service.
  • Markup fragment. A view that the iWidget produces for users. An iWidget can present multiple fragments simultaneously to users.
  • ItemSet. The attributes of an iWidget that typically control both its look and feel and its data sources. One example of data in ItemSet is an attribute named bgColor that controls the background color of the iWidget. Another example is an attribute named feedURL that controls the Atom feed that the iWidget connects to or renders.
  • Mode. An iWidget piece of the iContext managed state that tells the iWidget what type of markup to generate for the user. Examples of the types of markup include view for normal user markup and edit for markup for editing the iWidget's attributes.
  • Events. A mechanism that provides a transitory means of sharing information. iWidgets can share data through the publish event, which contains the event data. There are two types of events: a published event, which means the iWidget publishes some data by this event, and the handled event, which means the iWidget receives some data from other iWidgets.

Creating a real-world widget step-by-step

We introduce several new terms and concepts here. After you develop a widget with the following instructions, these new concepts become clear.

HelloWorld, your first iWidget

To create your first HelloWorld iWidget, follow these steps:

  1. Open your favorite text editor and create a widget.xml file using the code snippet shown in listing 1.

    Listing 1. A simple widget.xml file
    <?xml version="1.0" encoding="UTF-8"?>
    <iw:iwidget name="myWidget" xmlns:iw="http://www.ibm.com/xmlns/prod/iWidget" 
    supportedModes="view edit" mode="view">
        <iw:content mode="view">Hello World!</iw:content>
        <iw:content mode="edit">Configure me.</iw:content>
    </iw:iwidget>

    As you can see in the XML file, this widget has two modes. It shows "Hello World!" text in the default view mode, and it shows "Configure me." in the widget edit mode.
  2. To test your first widget, enter this XML file in any public Web site. Get a public URL, such as http://www.mycompany.com/widgets/widget.xml, and then register it in InfoSphere MashupHub.

    To do this step, log in to https://<host>:9443/mashuphub/, and then click Upload Widget as shown in figure 1.

    Figure 1. Click the Upload Widget link in InfoSphere MashupHub
    Click the Upload Widget link in InfoSphere MashupHub
  3. Select widget- iWidget, and then click Next.
  4. Select the option Register a Widget URL in the window that displays, as shown in figure 2. Enter the URL for the widget.

    Figure 2. Register a Widget URL in InfoSphere MashupHub
    Register a Widget URL in InfoSphere MashupHub
  5. Click Next, and then specify all the required information, such as widget title, description, and version.
  6. Click Finish to register the widget in InfoSphere MashupHub.
  7. To add this widget to your Lotus® Mashups toolbox, go back to the main UI of InfoSphere Mashup Hub, click List Widgets, move the mouse over the new registered widget, and then click Add to Lotus Mashups as shown in figure 3.

    Figure 3. Add the widget to Lotus Mashups
    Add the widget to Lotus Mashups
  8. Specify all required information, such as Lotus Mashups user name, passwords, and widget catalog. Then return to Lotus Mashups, and this new widget displays in your selected toolbox drawer. After dragging it on the page, you can check the widget UI in view and edit mode as shown in figure 4.

    Figure 4. Widget user interface in view and edit modes
    Widget user interface in view and edit modes

Package it as a WAR file and upload to Mashup Catalog

If you don't have a public Web site on which you can host the widget files, then you can package the widget as a Java Platform, Enterprise Edition WAR file. InfoSphere MashupHub also supports uploading a widget WAR file and adding all widgets inside the WAR file to your Lotus Mashups toolbox. The other benefit of developing a widget as a WAR file is that you can leverage JavaServer™ Pages (JSP) and servlet technology to serve as the backend for the widget, such as database operation or transaction management.

You can use IBM Rational® Application Developer or Eclipse IDE for Java EE Developers (Ganymede Package) to create a dynamic Web project. Then, add the widget.xml to the WebContent folder. You also need to add two special files in the WebContent/WEB-INF folder, catalog.xml and mashup.properties, as indicated in figure 5.

Figure 5. Widget artifacts in the Eclipse project
Widget artifacts in the Eclipse project

Let’s check mashup.properties, shown in listing 2, first.

Listing 2. Content of mashup.properties
contextRoot=MonitorWidget
componentName=dw.widget.monitor

The mashup.properties file in the lib folder is required to tell the IBM Mashup Center server how to deploy the WAR file. If the parameter contentRoot is not specified in this file, then the deployer service automatically generates a unique context root for the Web application. Explicitly specify a unique name for this parameter so that inside the widget you can use /%contentRoot%/abc to refer to any servlet or resource that the widget might use. The parameter componentName is another required property for the mashup.properties file. The IBM Mashup Center deployer service uses this name to determine whether a full deployment or an update is needed. To avoid collision, use a Java-style package-naming convention for this property value, such as componentName=com.foo.MyWidget

Then, let’s check the content of catalog.xml as shown in listing 3.

Listing 3. Content of catalog.xml
<?xml version="1.0" encoding="UTF-8"?>
<catalog>
  <category name="Test">
    <entry id="myWidget" unique-name="myWidget">
      <title>
        <nls-string lang="en">Memory Monitor</nls-string>
      </title>
      <description>
        <nls-string lang="en">Track the J2EE server memory status</nls-string>
      </description>
      <definition>widget.xml</definition>
      <icon>widget_icon.png</icon>
    </entry>
  </category>
</catalog>

This sample catalog.xml listing contains metadata for the widget (ID, title, description, definition, and icon). More than one widget can be declared in this catalog.xml file. In other words, there could be multiple <entry> tags under <catalog>.

Because it's a Java Platform, Enterprise Edition Web project, you could add any number of servlets. Let's create one to get server-side Java Virtual Machine (JVM) memory usage information and pass it to the widget. See figure 6.

Figure 6. Creating a Java servlet in the Eclipse IDE
Creating a Java servlet in the Eclipse IDE

As shown in figure 6, enter the following information in the Create Servlet window:

  • In the Java package field, enter dw.widget.monitor.
  • In the Class name field, enter WidgetServlet.
  • In the Superclass field, enter javax.servlet.http.HttpServlet.

The fields Web project and Source folder are automatically filled by the Eclipse IDE.

The servlet Java code is fairly simple. It calls the Runtime.totalMemory() and freeMemory() methods to get data, then it returns a JSON-style response. See listing 4.

Listing 4. Java source code of dw.widget.monitor.WidgetServlet
package dw.widget.monitor;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class WidgetServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    public WidgetServlet() {
    }

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        long total=Runtime.getRuntime().totalMemory();
        long current=total-Runtime.getRuntime().freeMemory();
        response.getWriter().print("["+total+","+current+"]");
    }
}

Next, you need to modify the widget definition XML by removing the hard-coded "HelloWorld!" text and adding the real user interface. See listing 5.

Listing 5. Content of the updated widget definition XML (widget.xml)
<?xml version="1.0" encoding="UTF-8"?>
<iw:iwidget name="myWidget" xmlns:iw="http://www.ibm.com/xmlns/prod/iWidget"
supportedModes="view edit" mode="view" iScope="dw.MonitorWidget">
    <iw:resource uri="widget.js" />
    <iw:content mode="view">
    <![CDATA[
    <div style="margin:5px">
        <h3>Memory usage:</h3>
        <p>Total:<span id="totalMemory">loading..</span> MB ,
        Current: <span id="currentMemory">loading..</span> MB </p>
        <span id="percentage" style="float:right">loading..</span>
        <div style="width:300px;background-color:#f1f1f1;">
            <span id="bar" style="height:10px;background-color:#E7AB6D;
            border-style:solid;border-width:1px;display:block;width:19%;">
            </span>
        </div>   
    </div>
    ]]>
    </iw:content>
    <iw:content mode="edit">Configure me.</iw:content>
</iw:iwidget>

Note that you add more HTML elements in the <iw:content mode="view">. Some of them provide a static view, such as <h3>Memory usage:</h3>. Others are updated dynamically based on the data from the server side. You specify IDs for those elements so that you can use JavaScript™ to manipulate them.

You might also notice that you added a <iw:resource> element and specified an iScope attribute. By doing so, you can use JavaScript to control the widget. The path to the JavaScript file is specified in the <iw:resource> tag. See listing 6 for the content. The name of the class defined in this file is same as the value of the iScope attribute in the <iw:widget> tag.

Listing 6 shows the source code of widget.js.

Listing 6. Content of the widget JavaScript class (widget.js)
dojo.declare("dw.MonitorWidget",null,{   
   
    spanTotalMemory:null,
    spanCurrentMemory:null,
    spanBar:null,
    spanPercentage:null,
    onLoad:function(){
        this.spanTotalMemory=this.iContext.getElementById("totalMemory")
        this.spanCurrentMemory=this.iContext.getElementById("currentMemory")
        this.spanBar=this.iContext.getElementById("bar")
        this.spanPercentage=this.iContext.getElementById("percentage")
       
        this.getDataAndUpdateUI()
        var _this=this
        setInterval(function(){
            _this.getDataAndUpdateUI()
        },20*1000)
    },
   
    getDataAndUpdateUI:function(){
        var _this=this
        dojo.xhrGet({
            url:"/MonitorWidget/WidgetServlet",
            handle:function(data,ioArgs){
                var numbers=eval(data)
                _this.updateUI(numbers[0],numbers[1])
            }
        })   
    },

    updateUI:function(total,current){
        this.spanTotalMemory.innerHTML=parseInt(total/1024/1024)
        this.spanCurrentMemory.innerHTML=parseInt(current/1024/1024)
        var percentage=""+parseInt(current/total*100)+"%"
        this.spanBar.style.width=percentage
        this.spanPercentage.innerHTML=percentage
    }
   
})

First, you leverage the dojo.declare() method to create a new JavaScript class, dw.MonitorWidget. Lotus Mashups calls the onLoad method automatically when the widget is loaded. In this method, you create a JavaScript timer to query the server-side memory status every 20 seconds and to update the UI.

To test the new widget in IBM Mashup Center, first right-click the Web Project in Eclipse, select Export - WAR file, and then generate a WAR file. Log in to IBM InfoSphere MashupHub, and upload this widget WAR file. The user interface is very close to the one shown in figure 2, except that you need to select the option Upload a Widget Package. Finally, you need to add this widget to the Lotus Mashup toolbox as shown in figure 3.

Figure 7 shows the window that displays when you add the widget on a mashup page. The widget sends an AJAX request to the server to get the latest memory information and update the UI without refreshing the whole page.

Figure 7. The updated user interface of the sample widget
The updated user interface of the sample widget

Advanced topics

Most of the basic concepts of iWidget development are covered in preceding example. Before we wrap up, though, let's quickly go through some advanced topics.

Use the ItemSet

The ItemSet API is provided to store and retrieve iWidget attributes, which are usually used to customize the look and feel of an iWidget or to configure an iWidget. iWidget attributes can be defined in iWidget definition XML and can updated through the ItemSet API.

Let’s take XML syntax as an example. See listing 7.

Listing 7. Attributes can be defined as an item within itemset-"attributes"
<iw:itemSet name="attributes" > 
<iw:item name="username" value="IBM" readOnly="false"/> 
</iw:itemSet>

To get the ItemSet value, you can call iContext.getiWidgetAttributes().getItemValue(“username”). It returns a string value of IBM.

To save an ItemSet value, you need to call the setItemValue() method. See listing 8.

Listing 8. Sample code to save the widget preference
this.iContext.getiWidgetAttributes().setItemValue(attributeName,attributeValue, 
isReadOnly); 
this.iContext.getiWidgetAttributes().save();

Add events to iWidget

Widgets use events to communicate with each other. There are two kinds of events: the publish event and the handle event.

Let's take the event definition from the Feed Reader iWidget, which is a production widget shipped with IBM Mashup Center V1, as a example. See listing 9.

Listing 9. Sample code for a publish event
<iw:event id="feedURLChanged" published="true" eventDescName=
"desc_feedURLChanged" onNewWire="publishURLOnNewWire"/> 
<iw:eventDescription id="desc_feedURLChanged" payloadType="string" 
description="Publish URL when feed URL setting is changed" lang="en"> 
       <iw:alt discription="" lang="de"/> 
       <iw:alt discription="" lang="cn"/> 
</iw:eventDescription>

This publishable event is called feedURLChanged. It sends out the string payload, as shown in listing 10.

Listing 10. A handle event sample code
<iw:event id="getFeedFromURL" handled="true" 
onEvent="handleGetFeedFromURL" eventDescName="desc_getFeedFromURL"/> 
<iw:eventDescription id="desc_getFeedFromURL" 
payloadType="string" description="get feed content from the url" lang="en"> 
       <iw:alt discription="" lang="de"/> 
       <iw:alt discription="get feed content from the url" lang="cn"/> 
</iw:eventDescription>

This sample is a handle event called getFeedFromURL, which can receive a string as payload and invoke the function handleGetFeedFromURL when it is triggered.

Source iWidget could publish the source event, which triggers the target event in the target iWidget using the iEvents API. See listing 11.

List 11. Sample code to fire an event
this.iContext.iEvents.publishEvent("feedURLChanged", newFeedURL);

A convenient wiring UI is provided to wire two iWidgets together while editing the page. Figure 8 shows the wiring UI.

Figure 8. Lotus Mashups widget wiring interface
Lotus Mashups widget wiring interface

A wire is stored in the span format shown in listing 12 in the target iWidget instance. You can wire two events together in a static page by explicitly defining a ReceivedEvent in the target widget's micro format.

Listing 12. Sample micro format code of a widget wire definition
<span class="mm_ReceivedEvent" > 
<a class="mm_SourceEvent"href="#1" 
style="visibility:hidden" > nameOfPublishEvent</a> 
<span class="mm_TargetEvent" 
style="visibility:hidden" > displayEventData </span> 
</span>

NOTE: Inside the anchor <a class=""mm_SourceEvent">, the href attribute points to the ID of the source widget. Content is the publish event name. Content inside the <span class="mm_TargetEvent"></span> tag is the handle event name.

National language support

If you want add national language support (NLS) to your widget, you can follow these steps:

  1. Add dojo.require("dojo.i18n"); to your script.
  2. Organize all your language-dependent strings in the following fashion. The <lang> should be replaced by the language code:

    js\nls\<lang>\helloWorldStrings.js
  3. Then, in the widget onLoad method(), register the resources shown in listing 13 so that the widget JavaScript can reference them.

    Listing 13. Register the NLS resources
    dojo.registerModulePath("helloWorldWidgetModule",this.iContext.io.rewriteURI("js"));
    dojo.requireLocalization("helloWorldWidgetModule","hwStrings");
    this.resourceBundle = 
    dojo.i18n.getLocalization("helloWorldWidgetModule","hwStrings");
  4. Now you can reference any string defined in the helloWorldStrings.js file as needed. If you have a string defined like this:

    helloWidgetStr_AskName = What is your name? You can reference it like this:

    this.resourceBundle.helloWidgetStr_AskName

Conclusion

In this article, we demonstrated how to create a simple widget that can be registered in IBM Mashup Center. Then we added more features in the widget, such as Java servlet backend and Dojo XmlHttpRequest. In the last part of this article, we covered a few advanced widget programming topics.


Downloads

DescriptionNameSize
Code samplewidget.monitor.zip11KB
Code samplewidget.monitor.war6KB

Resources

Learn

Get products and technologies

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Select information in your profile (name, country/region, and company) is displayed to the public and will accompany any content you post. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into IBM collaboration and social software on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Lotus, Sample IT projects
ArticleID=330718
ArticleTitle=Developing widgets for IBM Mashup Center 1.0
publish-date=08192008