The "Plants by WebSphere" application is among a number of samples that are provided with the IBM WebSphere Application Server Feature Pack for Web 2.0. The application exemplifies a typical J2EE application and how it can be enhanced with an Ajax-style architecture without rewriting the entire application. The sample application represents a fictitious online plant store where customers can order and purchase flowers, trees, vegetables, and accessories. Take a look at Figure 1, which shows the front page of the Web application:
Figure 1: The Plants by WebSphere Web application
Figure 2 illustrates the architecture of the application in its original form before attempting to add Ajax-style features. The architecture is intended to be fairly typical for a J2EE application running on WebSphere Application Server. At a high level, the application adheres to a Model-View-Controller (MVC) design pattern, which most Web applications follow on some level. A browser accesses the URL for the application, which returns a JSP-rendered HTML page. The browser issues additional requests to the Web application, and servlets are used to control the flow as users move through the purchase request. Enterprise JavaBeans (EJBs) are used to serve model data available on the database.
Figure 2: A typical Web architecture
Figure 3, below, shows how the architecture of the application has been augmented using Ajax. The intention is not to rewrite the application, but rather to take advantage of technologies in the IBM Feature Pack that would improve and create a more interactive and rich experience for the user.
On the browser side, the application uses widgets provided with the JavaScript Dojo Toolkit. Additionally, customized user interface widgets were created to improve the interactive nature of Plants by WebSphere while not rewriting it. The customized user interface widgets are asynchronous, meaning they communicate using the browser's XHR mechanism supported by the Dojo Toolkit. The widgets use an XML interchange format to exchange data with the server. On the server, the RPCAdapter provided with the Feature Pack is used to convert EJB data into an XML interchange format that can easily be consumed by your newly created widgets on the browser.
A characteristic of Ajax applications is an improved response on the user interface.
Plants by WebSphere uses the Dojo Toolkit within the Web browser to improve the user
interface (UI) of the application. The Dojo Toolkit is pure JavaScript, and the JavaScript
files can be hosted directly in the Web-Content directory of
the Web Archive File (WAR),
or exist as static Web content on a performance-optimized content delivery network.
As a sample, the Dojo Toolkit JavaScript files are hosted as part of the WAR.
The Dojo Toolkit supports being used declaratively or procedurally. In a declarative role, you embed the JavaScript you plan to use directly within the HTML content. The Dojo Toolkit contains a wealth of widgets that can be used declaratively within HTML, reducing the need for you to hand code the function. In the case of Plants by WebSphere, Dojo Toolkit widgets are directly embedded into the JSP pages.
Figure 3: An Ajax-enhanced architecture
A common scenario in Web applications is form handling, where the user enters data into a Web page, data such as his or her name, address, preferences, and so on. The information is then sent back to the server for processing, and the result is returned to the user. A common action on the form is validation to ensure the content the user is entering is in an accepted format. Was a number entered in place of a letter? Did the user enter a valid zip code? The Dojo Toolkit provides a rich set of form-handling validation capabilities that can be added to Web pages. Listing 1, below, is an example that is used within the Plants by WebSphere application. It represents a typical example of how to declaratively use the Dojo Toolkit within a Web application.
We'll begin by declaring the usage of Dojo within your HTML page. Looking at Listing 1, the
first script tag declares usage of dojo.js. Dojo.js is the core Dojo Toolkit kernel and is
required when using the Dojo Toolkit. The second <script> tag declares the Dojo widgets
that the page uses. The dojo.declare clause compares to the Java import or the C++ includes clause. The statement tells the dojo.parser where to locate the appropriate Dojo Toolkit
JavaScript file the page uses. For the example in Listing 1, the page uses the dijit.form.ValidationTextBox
widget. Additionally, the JavaScript dojo.parser needs to be included as well. The parser is
used to scan the page for widgets to declare. Listing 2, later, will explain why.
Listing 1: Sample code listing at maximum width
<script type="text/javascript"
src="/PlantsByWebSphereAjax//dojo/dojo.js"
djConfig="isDebug: false, parseOnLoad: true,
extraLocale: ['de-de', 'en-us']">
</script>
<script type="text/javascript">
dojo.require("dijit.form.ValidationTextBox");
dojo.require("dojo.parser");// scan page for widgets and
// instantiate them
</script>
|
Listing 1 showed how the Dojo Toolkit is declared within your JavaScript and the type of
widgets the page will use. Listing 2 shows how the widget is declared within the page.
The dojo.parser
that was declared in Listing 1 will be used to parse the HTML page. When a
widget is found by the parse, a call is made to the widget constructor code. The result is the
validation widget code is created in the page's Document Object Model (DOM).
Listing 2: Declaring the use of Dojo's
ValidationTextBox widget
<TD width="100%">
<P>
<input type="text" id="sname" name="_sname" class="medium"
dojoType="dijit.form.ValidationTextBox"
propercase="true"
required="true"
promptMessage="Enter Name" />
</P>
</TD>
|
Figure 4 shows the result. When the user fails to enter a value for a required field, the browser will dynamically inform the user.
Figure 4: Billing address using Dojo's validation widget
Form validation is a simple example of how to begin to use Ajax within an existing J2EE application. At the same time, it represents a powerful example of how seamlessly a user interface can be improved without having to rewrite a ton of existing code.
There are numerous other examples of how declarative forms of programming using the Dojo Toolkit can be used within a J2EE application. Dojo ships a wide array of sample applications within the test directories of the Dojo Toolkit. These applications will run within a browser by opening the HTML page.
Creating your own custom widgets
Another interesting example is creating your own customized JavaScript widgets. Dojo provides a powerful framework to create innovative widgets that can be embedded directly within your HTML pages.
Figure 5 shows the catalog browsing page for the Plants by WebSphere application. When the user clicks one of the images, the catalog page shows pictures of items across the top and detailed information of each item at the bottom.
Figure 5: Catalog page for Plants by WebSphere
While this page consists of a number of different widgets, we'll look at the itemDetails widget shown at
the bottom in Figure 6. The itemDetails widget fetches information from the server and displays it in
the details window. The user can add the item to the cart or drag it to the cart using the left mouse
button. The widget fetches information from the server when the user clicks on one of the catalog items
at the top. Now we'll look at how the itemDetails widget was created.
Figure 6: The
itemDetails widget
When creating widgets using the Dojo Toolkit, there are several files you must consider. The first two are the HTML and
CSS template files. These will be used to define the skeleton of what the page will look like when the
widget is rendered within the browser. The HTML page will contain declared attachment points where the
DOM elements will be inserted by your widget. The attachment points are called DojoAttachPoint.
Listing 3 shows a portion of the itemDetail widget's HTML template and the DojoAttachPoint for the
table rows. As the JavaScript in the customized widget processes content, it will dynamically create elements
and insert them into your attachment points for the DOM.
Listing 3:
DojoAttachPoint in the itemDetail.html Dojo template
<div>
<table cellpadding="2" cellspacing="2" border="0" width="100%"
height="100%">
<tr width="100%" height="100%">
<td valign="top" align="left" width="75%">
<span class="itemNameText"
dojoAttachPoint="nameElement"></span>
<span dojoAttachPoint="descElement"
class="itemDescText"></span><br><br>
<table cellspacing="0" cellpadding="0" width="100%"
height="100%">
<tr style="width: 80%">
<td valign="top" align="left">
<span style="font-family:verdana,arial,
sans-serif;
font-size:11px;">Price:</span>
</td>
<td valign="top">
<span class="itemNameText" >$
<span dojoAttachPoint="priceElement">
</span></span>
</td>
<td valign="top" align="right">
<button dojoType="dijit.form.Button"
dojoAttachEvent="onclick: addToCart">
Add to cart</button>
</td>
</tr>
</table>
. . . . .
. . . . .
// Additional content
. . . . .
. . . . .
</table>
</div>
|
The widget's template and CSS define the appearance of the widget and identify where in the DOM updates will occur. The next step is to add the JavaScript code to the widget that does the work.
Listing 4 shows the beginning section of the customized itemDetail widget. The code begins by
declaring the widget to be created: dojo.provide("ibm.widget.ItemDetails");.
The name is used to reference the newly created widget.
Below the dojo.provide is the dojo.declare. The dojo.declare defines the widget and any inheritance that
this widget might have. In this case, the code declares inheritance from
base dijit._Widget and dijit._Templated. Because this is a templated widget, the code declares the
templatePath. The template path defines the location of the template that was defined above. The
dojo.moduleUrl is a utility function that is used to resolve the location of the template.
Further down in the code, the DojoAttachPoint declarations defined in Listing 3 are declared. These
will be the root nodes of the DOM references that will be updated. In this case, nameElement and descElement
are declared, among a number of other variables. The next section will look at how these
elements are modified.
Listing 4: Declaring the
itemDetails widget
dojo.provide("ibm.widget.ItemDetails");
dojo.declare(
"ibm.widget.ItemDetails",
[dijit._Widget, dijit._Templated],
{
initializer: function(){ },
templatePath:
dojo.moduleUrl("ibm","widget/templates/ItemDetails.html"),
isContainer: false,
// your DOM nodes declared as DojoAttachPoint in the
// Template:
nameElement: null,
descElement: null,
imageElement: null,
priceElement: null,
// Additional Code
. . . .
. . . .
|
To really make the widget interesting, data is needed to populate it. The data for the details widget is located on the server. At this point, you might wonder how to get the description data to render in the page.
The Dojo Toolkit offers a powerful I/O transport mechanism that can be used to issue XMLHttpRequests (XHR) requests to the server and process the result. The XHR API opens an independent communication channel within the browser. XHR is at the heart of what gives Ajax its interactive feel.
Listing 5 shows the use of the dojo.xhrGet function to
retrieve data from the server. The Dojo Toolkit wraps the XHR API with its own API, which makes dealing with the XHR API easier. The
url: parameter defines the address of the server. The ?p0="+item.id is a URL parameter that is passed to the
server. The timeout defines how long to wait before giving up on the connection to the server. The
headers define additional HTTP headers that should be applied to the request sent to the server. The
handleAs parameter tells the Dojo Toolkit how to handle the response. In this case, the expected response
is XML code.
The deferred.addCallback(function(response) is the callback function that will be invoked by the
Dojo Toolkit when the response is returned from the server. The previous section defined the
DojoAttachPoint as being the location of the DOM node to be modified. The descElement is one of the DOM
nodes modified here. The self.descElement.innerHTML value is set to the description text that was
returned in the XML. The descElement is the DOM node that was declared previously in the Template file
of the widget (see Listing 3).
Listing 5:
XHR GET request to the server
var deferred = dojo.xhrGet( {
url: self.url+"?p0="+item.id,
timeout: 5000,
headers: { "Content-Type":"text/html" },
handleAs: "xml"
} );
deferred.addCallback(function(response){
var itemElement =
response.getElementsByTagName( "entry" )[0];
self.descElement.innerHTML =
itemElement.getElementsByTagName( "description" )[0].firstChild.nodeValue;
self.hiddenData.setAttribute("itemname", item.name);
self.hiddenData.setAttribute("itemprice", item.price);
self.hiddenData.setAttribute("itemid", item.id);
. . . . .
return response;
});
|
When your customized Dojo widget is created, it needs to be inserted into your HTML page so it can be
used. Figure 6 shows what the page looks like. The listing is from the flowers.html file. Listing 6
shows a fragment of the HTML behind the page. The DIV tag is used to embed the widget and contains the
keyword dojoType, which declares the itemDetails widget. There are additional parameters passed to the widget
in the form of url
—the URL request to the Remote Procedure Call Adapter (RPCAdapter) on the server. If you recall, the itemDetails
widget makes an XHR request to the server to retrieve its data to display. The server-side code will be
covered in the next section, which looks at the RPC adapter usage.
Listing 6: Declaring
itemDetails in the HTML page
<body style="background: #FFF;">
. . . .
. . . . //additional HTML
. . . .
<div dojoType="ibm.widget.ItemDetails"
url="/PlantsByWebSphereAjax/servlet/RPCAdapter/httprpc/Sample/detailRequest"
style="width: 100%;"
itemTopic="itemdetails_flowers"></div>
</body>
|
At this point, you have seen how a customized widget is created in Dojo and how that widget would go about issuing XHR requests to the server. Now look at how the server might handle those requests.
In the case of the Plants by WebSphere application, the widget issues an XHR request to the server for some data. The servlet reads the request and looks up the correct Enterprise JavaBean (EJB). The EJB is called, and the EJB container issues a request to the database, which returns the result. The result needs to be encoded into XML and returned back to the JavaScript widget on the browser.
For this scenario, the RPC adapter (RPCAdapter) that is provided with the IBM Feature Pack for WebSphere Application Server will be used to connect to the Plants by WebSphere EJBs.
The RPCAdapter runtime JAR is included with the Plants by WebSphere application and is configured using an XML file located in the WEB-INF directory of the WAR file. Listing 7 shows an example configuration.
Listing 7: RpcAdapterConfig.xml
<?xml version="1.0" encoding="UTF-8"?>
<rpcAdapter>
<default-format>xml</default-format>
<services>
<pojo>
<name>Sample</name>
<implementation>
com.ibm.websphere.samples.plantsbywebspherewar.RpcConnecter
</implementation>
<methods filter="whitelisting">
<method>
<name>detailRequest</name>
<description>
returns back detail information for an item
</description>
<http-method>GET</http-method>
<parameters>
<parameter>
<name source="request">message</name>
<description>
Contains the message to be returned
</description>
</parameter>
</parameters>
</method>
</methods>
</pojo>
</services>
</rpcAdapter>
|
Take a closer look at the RpcAdapterConfig.xml file. The <default-format> returned by the
RPCAdapter is declared as XML. The adapter also supports returning data in JavaScript Object Notation (JSON)
as well. The <implementation> element contains the user-defined class definition the RPCAdapter will
instantiate to invoke the method. The method name in the class to call is defined in the <name> element
and is called detailRequest. The <http-method> that the RPCAdapter is expecting is GET. The parameter
that is expected on the URL request is message.
Putting it all together, the itemDetails widget from Listing 8 would invoke the RPCAdapter using the following
format, where F0001 is the identifier of the item:
/PlantsByWebSphereAjax/servlet/RPCAdapter/httprpc/Sample/detailRequest?message=F0001
|
The result returned by the RPCAdapter would be XML data. Listing 8 shows the XML output:
Listing 8: XML output returned to the itemDetails widget from the RPCAdapter
<results>
<entry>
<description>
African orchids are some of the most endangered and rare kinds of orchids grown today.
This variety is medium yellow with variegated salmon and pink insides. Height: 18 to 28
inches.
</description>
<image>
/PlantsByWebSphereAjax/servlet/ImageServlet?getimagebyid=F0001
</image>
<id>F0001</id>
<name>African Orchid</name>
<price>$250.00</price>
<thumb>
/PlantsByWebSphereAjax/servlet/ImageServlet?getimagebyid=F0001
</thumb>
<dept>0</dept>
<heading>Rare Delicate Beauty</heading>
</entry>
</results>
|
Now take a closer look at the implementation class. This was defined in the RpcAdapterConfig.xml
file and contains the detailRequest method. Listing 9 shows the implementation
class com.ibm.websphere.samples.plantsbywebspherewar.RpcConnecter defined in the RpcAdapterConfig.xml
configuration file in the previous listing.
Listing 9: Implementation class com.ibm.websphere.samples.plantsbywebspherewar.RpcConnecter
public Collection detailRequest( String itemId ) {
ItemDetailPojo itemDetailPojo = new ItemDetailPojo();
Vector itemCollection = new Vector();
if (itemId != null) {
try
{
Catalog catalog = catalogHome.create();
StoreItem item = (StoreItem)
catalog.getItem(itemId);
if ( item != null ) {
itemDetailPojo.name = item.getName();
itemDetailPojo.id = item.getID();
itemDetailPojo.price =
java.text.NumberFormat.getCurrencyInstance(java.util.Locale.US)
.format(new Float(item.getPrice()));
itemDetailPojo.heading = item.getHeading();
itemDetailPojo.description = item.getDescription();
itemDetailPojo.dept = new
Integer(item.getCategory()).toString();
itemDetailPojo.thumb =
"/PlantsByWebSphereAjax/servlet/ImageServlet?getimagebyid="+item.getID();
itemDetailPojo.image =
"/PlantsByWebSphereAjax/servlet/ImageServlet?getimagebyid="+item.getID();
itemCollection.add(itemDetailPojo);
}
}
catch (javax.ejb.CreateException e)
{
Util.debug("RpcConnecter: EJB Create Exception in
detailRequest(...)");
}
catch (Exception e)
{
Util.debug("RpcConnecter: general Exception in
detailRequest(...)");
}
}
return itemCollection;
}
|
The method detailrequest( ) returns a collection of Plain Old Java Objects (POJO) elements. The collection class is part of the
java.util package. The POJO elements are derived from data returned by invoking the StoreItem EJB. The
StoreItem is retrieved from the Catalog EJB. The Catalog EJB is a collection of the items that are contained
within the Plants by WebSphere inventory located in the Derby database. Once a Java Collection is returned, the
RPCAdapter will transparently map the Collection to XML data. The Collection's key corresponds to the XML element
and the key's value to the XML value. The XML stream is returned to the itemDetails widget.
By using the RPCAdapter and having it return XML code, you have created a service that others can connect to as well. The service only returns data, and it is up to the caller to figure out how to render the data. A usage scenario might be a partner company of Plants by WebSphere that aggregates data from its own greenhouse with the catalog information maintained by Plants by WebSphere. This scenario is sometimes referred to as a mashup.
Other scenarios to think about
While the Plants by WebSphere application does not implement the specific scenarios listed below, they are helpful in understanding other ways to use the benefits of the IBM WebSphere Application Server Feature Pack for Web 2.0 in your J2EE applications.
You have just learned about creating a mashup application that combines content from multiple sites to create the appearance of one site. The classic mashup example is taking Google maps and customizing it with a user's unique location-based content. One of the challenges in creating mashups is dealing with cross-site scripting within the browser. As an example, if you go to mydomain.com to access the Plants by WebSphere application, but the widgets you created issue XML requests to mypartner.com using XHR, then the browser will prevent the request. Normally, this is a very good behavior because it prevents cross-site scripting security vulnerabilities from occurring when you access pages on the Web.
In the case of the Plants by WebSphere application, you want to allow your widgets to access other sites for content. How do you allow cross-site scripting responsibly within the browser?
One common way is to use a forward proxy. A forward proxy takes the request from the browser, looks at the URL, and forwards the request to the appropriate domain. From the browser's perspective, the information appears to come from the same domain, but in reality, the content request is made by the proxy on behalf of the client. The Ajax proxy that is shipped with the IBM WebSphere Application Server Feature Pack for Web 2.0 includes a customizable servlet proxy.
The proxy is servlet based, and can be embedded directly in an EAR file or run on your server as a WAR file. The proxy also includes a white-listing ability, which you can further use to restrict the kinds of requests that the proxy is allowed to service. It also includes the ability to filter on headers, mime types, and cookies, and it's customizable using an XML file.
Web feed syndication -- tell the world
Web syndication (or Web feeds) is the practice of making content available to other sites to use. Typically, a site makes available a Web feed that contains a title and a short description of the content. If a user is interested in the content, he or she clicks on the link and is taken to the site to read more detailed information. In the case of the Plants by WebSphere application, you can imagine a scenario where a Web feed would contain additional planting tips, sales, or blogs by horticulture specialists.
The IBM Feature Pack for Web 2.0 provides the Apache Abdera library which includes an implementation of the Atom Syndication Format and Atom Publishing protocol to help you develop your own feeds.
A syndication solution would not be complete without taking into account the client-side implementation. The IBM Feature Pack provides an Atom Feed viewer as part of the Dojo Toolkit extensions. The viewer can be embedded in your HTML as a widget to provide feed-viewing capabilities.
The Plants by WebSphere application is just one example of how you can apply the IBM Feature Pack for Web 2.0 to create Ajax-style architectures for existing J2EE applications. The Feature Pack ships with a variety of client-side and server-side technologies that you can deploy together or independently with your Web application. Additional information is available with the Feature Pack download (see the Resources section for information).
Learn
- Get an overview of the Feature Pack in Kevin
Haverlock's introductory piece, "A look at the WebSphere Application Server Feature Pack for Web 2.0" (developerWorks, February 2008).
- Learn more about the Open source-based
Dojo Toolkit.
- Get documentation for the
Dojo Toolkit.
- Explore
Apache Abdera, an open source library for creating and aggregating Web feeds.
-
The developerWorks article "Build enterprise SOA Ajax clients with the Dojo toolkit and JSON-RPC" is an
example of using JSON-RPC to invoke server-side Java objects (June 2006).
- Learn more about Comet,
which facilitates asynchronous communication from the server to client.
-
The IBM Information Center
contains detailed documentation about the IBM WebSphere Application Server Feature Pack for Web 2.0.
- Get a demo of the IBM WebSphere Application Server Feature Pack for Web 2.0.
Get products and technologies
-
Get additional information on the IBM WebSphere Application Server Feature Pack for Web 2.0, including
links to the download page and additional documentation.
- Download
IBM product evaluation versions
and get your hands on application development tools and middleware products from
DB2®, Lotus®, Rational®, Tivoli®, and
WebSphere®.
Discuss
- Participate in the discussion forum.
- Check out
developerWorks
blogs and
get involved in the
developerWorks community.

Kevin Haverlock is an architect and developer with IBM's WebSphere Application Server product and is currently part of the Feature Pack team for Web 2.0. Kevin can be reached at kbh@us.ibm.com.
Comments (Undergoing maintenance)





