Portlet development using REST services and the Dojo Toolkit

This article focuses on the creation of a reusable reference design for creating Web 2.0-enabled portlets using Representational State Transfer (REST) services and the Dojo Toolkit.

Thomas Lawless (tglawles@us.ibm.com), Advisory Software Engineer, IBM

Thomas Lawless is an Advisory Software Engineer working for IBM Software Group's Global eBusiness Transformation group. He specializes in portal development with a focus on Web 2.0 features, specifically Ajax and enhanced UI widgets. You can reach him at tglawles@us.ibm.com.



04 March 2008

Portlet development can benefit greatly from the adoption of Web 2.0 architectural styles, frameworks, and toolkits. The development of REST services and the adoption of open source UI toolkits, such the Dojo Toolkit, can transform mundane portlets into robust and interactive applications without your having to learn new technologies.

Reference design

As with any development effort, it is important to ensure the components of the system are well defined. A well thought out design allows for multiple dependent components to be developed in parallel, increasing both the productivity of the development team and the reusability of the components created. Using Web 2.0 development styles and functionality in portlet development is no exception. For this reason, a generalized, high-level reference design is needed to act as a template for development.

Using an adaptation of a Unified Modeling Language (UML) component diagram, the components of the portlet application can be easily visualized. Let's examine the component diagram in figure 1 as an example.

Figure 1. UML component diagram
UML component diagram

The terminology and explanation of the component stereotypes are as follows:

  • System. The system stereotyped component represents the overall portlet application and contains all the subcomponents provided.
  • REST service. The REST stereotyped component represents the functionality of the system through documenting the services it provides. In figure 1, the System Services component provides two services named Service1 and Service2. As noted in the diagram, the services themselves are also stereotyped, in this case with the stereotype of Servlet. The stereotype applied to the service is intended to convey details on the service's implementation and access method. In the case of Service1 and Service2, the Servlet stereotype implies access using Ajax. This notation can easily be extended to include additional stereotypes such as SOAP to denote a Web service, JSONP to denote an On-demand JavaScript service, and many others.
  • UI widget. The UI widget stereotyped component documents the Web 2.0-enabled UI components provided and/or used by the system as well as reference points used to enable client-side interportlet communication. In figure 1, the widget stereotype represents a widget used by the system. This notation can also be easily extended to include additional stereotypes representing custom developed widgets as well as widgets from Web 2.0 frameworks and toolkits. In figure 1, the System Widgets component contains elements named System.Value stereotyped with publish and subscribe. The stereotype on these elements is used to denote the data elements the system publishes and/or subscribes to when communicating with other portlet applications. This facet of the reference design is covered in detail in the following sections.
  • Portlet. The portlet stereotyped component documents the portlets provided by the system and acts as a container for the UI widgets.

It is easy to see how the representation of the system can be viewed as an implementation of the Model View Controller (MVC) design pattern with the REST service component acting as the Controller, the data provided by the REST service component acting as the Model, and the UI widget and portlet components acting as the View.


Implementing the reference design

In normal practice, the reference design defined previously is modified to represent the portlet application under development. After the application is complete, the components of the system are broken down further, and a full design is created for each element before development begins. For the sake of brevity, this article focuses on the modifications of the reference design and the implementation of an example system. Figure 2 shows the modified reference design reflecting the example system.

Figure 2. Modified reference design
Modified reference design

Based on the explanation in the previous section, figure 2 defines a system containing one REST service named SourceList, a Dojo Toolkit UI widget named FilteringSelect, and a JSR 168 portlet named DojoSourcePortlet.

The REST service in this example provides a list of sources using a specific JSON data format defined by the Dojo Toolkit's dojo.data API. The dojo.data JSON format can be used seamlessly with a number of the Dojo widgets, reducing the amount of code needed to create UI components. In listing 1, the output of the SourceList service is shown.

Listing 1. Output of the SourceList service
{
     identifier:"id",
     label:”name”,
     items: [
          {id:"src1", name:"First Source"},
          {id:"src2", name:"Second Source"},
          {id:"src3", name:"Third Source"}
]}

For additional information on the dojo.data API, refer to the Dojo Toolkit's Web site.

The UI widget component is made up of the Dojo FilteringSelect widget, which resembles an HTML select element. The Dojo Toolkit abstracts the code needed to access the REST service and to display the contents of the response using two lines of HTML code as shown in listing 2.

Listing 2. Accessing REST service and displaying the response
<div dojoType="dojo.data.ItemFileReadStore" jsId="sourceStore" 
url="/DojoSource/SourceList"></div>
        
<input dojoType="dijit.form.FilteringSelect“ store="sourceStore“ 
searchAttr="name" autocomplete="true" id="sourceSelect"/>

The <div> tag displayed in listing 2 defines the dojo.data JSON store. This line of code tells the Dojo parser to access the content residing at the URL provided by the url attribute and to create a JavaScript object, whose name is provided in the jsId attribute. The <input> tag defines the FilteringSelect widget. The dojoType attribute tells the Dojo parser to convert this element into the FilteringSelect widget and populates its selections with the JSON data stored in the dojo.data store identified by the store attribute. Figure 3 shows how the HTML code in listing 2 renders in a Web browser using the data provided by the SourceList service.

Figure 3. Browser rendition
Browser rendition

Additional HTML code and modifications to the HTML in listing 2 are needed to make it suitable for display within a portlet. Refer to the Dojo Toolkit Web site for a further explanation of the code snippets that follow.

First, the portlet must include the Dojo Toolkit style sheets and bootstrap loader. The code in listing 3 accomplishes this task.

Listing 3. Including the style sheets and bootstrap loader
<style type="text/css">
@import “http://o.aolcdn.com/dojo/1.0.0/dijit/themes/tundra/tundra.css";
@import "http://o.aolcdn.com/dojo/1.0.0/dojo/resources/dojo.css"
</style>
<script type="text/javascript"  src="http://o.aolcdn.com/dojo/1.0.0/dojo/dojo.xd.js"
djConfig="parseOnLoad: true, isDebug: true"></script>
<script type="text/javascript">
dojo.require("dojo.parser");
dojo.require("dijit.form.FilteringSelect");
dojo.require("dojo.data.ItemFileReadStore");
</script>

Second, the dojo.data store and widget elements must include the portlet namespace to ensure uniqueness. The resulting code is shown in listing 4.

Listing 4. Including the portlet namespace
<div dojoType="dojo.data.ItemFileReadStore" 
jsId="<portlet:namespace/>_sourceStore" 
url="<%= renderResponse.encodeURL(renderRequest.getContextPath() + 
"/SourceList") %>"></div>
        
<input dojoType="dijit.form.FilteringSelect“ 
store="<portlet:namespace/>_sourceStore“ searchAttr="name" 
autocomplete="true" id="<portlet:namespace/>_source" />

The <portlet:namespace/> JSP tag is used to generate a unique prefix to ensure that the JavaScript and HTML attributes are unique if multiple instances of the same portlet are displayed on the same page.


Interportlet communication

Using portlets that communicate with each other is an effective solution to displaying data from different sources, and it can easily be accomplished using the Dojo Toolkit. Building on the example in the previous section, you can make additional modifications to the component design diagram to include a second system. Figure 4 shows an updated diagram.

Figure 4. Component design diagrams of two systems
Component design diagrams of two systems

The widget components of both systems in figure 4 contain placeholders for interportlet communication. Both the DojoSourceWidgets and DojoTargetWidgets components contain an element named source.selectedSource stereotyped with publish and subscribe, respectively. This notation is used to illustrate the information the system provides and/or consumes from other systems. In figure 4, the association line drawn from the source.selectedSource element of the DojoTargetSystem to the source.selectedSource of the DojoSourceSystem stereotyped as subscribes denotes that the DojoTargetSystem consumes the value provided by the DojoSourceSystem when the source.selectedSource element is published.

To create a realization of this communication path, let's first examine the implementation of the DojoTargetSystem. Starting with the REST service component, the DojoTargetSystem defines a service named SourceContent whose responsibility is to provide the content associated with a source ID provided when the service is called to the system's UI widgets. The Java code of the service is irrelevant to this example so it is not included. The output of the service is an HTML fragment representing the content of the source ID provided and shown here:

<p><h3>Source 1 content</h3></p>

The ContentPane widget is defined in the DojoTargetWidgets component in another Dojo Toolkit widget. A single line of HTML code is needed to add the widget to the portal JSP page and to configure it to display the default source content shown in listing 5.

Listing 5. Adding and configuring the widget
<div preload="true" dojoType="dijit.layout.ContentPane" 
id="<portlet:namespace/>_sourceContent" href="<%= 
renderResponse.encodeURL(renderRequest.getContextPath() + 
"/SourceContent?srcID=src1")%>">

As with the DojoSourcePortlet, the attribute's values are prefixed with the portlet namespace to ensure uniqueness. The <div> tag in the example tells the Dojo parser to load the content residing at the URL provided by the href attribute, which points to the SourceContent service. Figure 5 shows the widget rendered in the Web browser.

Figure 5. Widget rendered in a Web browser
Figure 5. Widget rendered in a Web browser

Now that you have defined both the DojoSourceSystem and the DojoTargetSystem, you implement having the systems communicate with each other on the client by using the Dojo Toolkit's event infrastructure. The Dojo event infrastructure provides a publish API and a subscribe API allowing for the actions within one portlet to be published to one or more subscribing portlets contained within the portal page.

To implement interportlet communication, modifications to both the FilteringSelect widget of the DojoSourceWidgets component and the DojoSourcePortlet are required for the system to publish the value when a selection is made. An event handler must be added to the widget to capture the selection of a source. The resulting widget code is shown in listing 6.

Listing 6. Adding an event handler to the widget
<input dojoType="dijit.form.FilteringSelect" 
store="<portlet:namespace/>_sourceStore" searchAttr="name" 
autocomplete="true" id="<portlet:namespace/>_source"                    
 onChange="<portlet:namespace/>_sourceSelected" />

The change made in listing 6 is the addition of the onChange attribute. The onChange attribute contains the name of the JavaScript function executed when the value selected in the FilteringSelect widget is changed. The name of the function, in this case sourceSelected, is also prefixed with the portlet namespace to ensure uniqueness.

The sourceSelected JavaScript function needs to be added to the portlet and is responsible for capturing the value of the selected item and publishing it to the Dojo event infrastructure. The JavaScript code here does that:

function <portlet:namespace/>_sourceSelected(id){
dojo.publish("source.selectedSource", [id]);
}

The function in the preceding code uses the dojo.publish() method to publish a variable named source.selectedSource with a value of the ID chosen in the widget. The ID value is passed to the FilteringSelect widget when a selection is made. The code in listing 2 shows how the widget is populated with selections using the dojo.data JSON store notation. The id attribute associated with each data element is the value passed to this function. In the case of this example, the three options are:

  • src1
  • src2
  • src3

The DojoSourceSystem development is now done, and it is time to complete the DojoTargetSystem. The DojoTargetPortlet requires additional JavaScript code to listen for the value published by the DojoSourceSystem and to update its content accordingly. The JavaScript code shown in listing 7 provides this functionality.

Listing 7. The dojo.subscribe() method
dojo.subscribe("source.selectedSource", function(id){
var widgetRef = dijit.byId("<portlet:namespace/>_sourceContent");
	widgetRef.setHref("<%= renderResponse.encodeURL(renderRequest.getContextPath() +
	 			/SourceContent?srcID=")%>" + id);
});

The JavaScript code in listing 7 uses the dojo.subscribe() method to listen for source.selectedSource to be published. When the variable is published, the dojo.subscribe() method executes the anonymous JavaScript function provided. In this case, the anonymous function retrieves a reference to the ContentPane widget contained within the portlet and changes the value of the widget's href attribute to a value using the source ID published by the DojoSourceSystem. This demonstrates that the content within the widget can be updated to display contextual information relevant to the selection made.

Figure 6 displays the initial page load. Note that there is no value selected in the DojoSourcePortlet and that the DojoTargetPortlet displays the contents of Source 1 by default.

Figure 6. Initial page load
Initial page load

Making a selection in the DojoSourcePortlet updates the content displayed in the DojoTargetPortlet as illustrated in figure 7.

Figure 7. Updated page load
Updated page load

Conclusion

The use of Web 2.0 architectural styles, frameworks, and toolkits can greatly enhance a portlet application's presentation and functionality by creating well defined, highly reusable components leveraging open source technologies to reduce development effort. In addition, by implementing interportlet communication on the client, the overall perceived performance of the portal page is increased. When a value is selected in one portlet, it is no longer necessary to reload the entire portal page. Only those portlets affected by the selection are refreshed. This article demonstrated key concepts and best practices easily adapted to any portlet development effort.

Resources

Learn

Get products and technologies

Discuss

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. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. 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 WebSphere on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=WebSphere
ArticleID=292480
ArticleTitle= Portlet development using REST services and the Dojo Toolkit
publish-date=03042008