Playing with Workshop and the Dojo Ajax Framework

This was originally posted on my dev2dev blog March 23rd, 2008.  After posting it, I discovered and it was also reported by others that IE had trouble with the code-as-is.  I have not revisited this yet.

I have been Inspired by the recent article by Gary Horen called "Ajax programming with BEA Workshop" and the numerous blogs from Skip Sauls that have touched on JSON and Firefox plug-ins like Firebug and YSlow.  I decided to try using what I perceive to be the most popular javascript framework, Dojo, to solve a relatively simple requirement from one of my customers to populate the options of a select drop-down based on the selection of another drop-down without refreshing the page.  For example, the options in the City drop-down will be populated based on the user's selection of an option in the State drop-down.  Here's a look at the finished example.

state

The State drop-down is the only one available, the City and the Submit button are disabled.

stateSelect

This is not a normal html select, it is a Dijit FilteringSelect that has enhanced capabilities, such as type-ahead, and the user selects a state.

selectCity [2]

Once a state is selected, the list of cities is populated and is now enabled.

submit

Once a user selects a city, the submit button is now enabled.  This has all happened without a screen refresh and provides a better user experience.

The Tools

  1. BEA Workshop 10.2
  2. Aptana Studio - Set of javascript plug-ins for Eclipse that among other things help with Javascript debugging
  3. Firefox 2
  4. Firebug - Great Firefox plug-in for debugging client side issues
  5. Dojo 1.0.2

Getting Started

The Workshop 10.2 projects used for this example (minus Dojo) are available here.  Import the projects, extract Dojo 1.0.2 to the WebContent folder of the DynamicSelectWEB project and deploy the DynamicSelectEAR project to a server to get it up and running.  This includes a city / state web service in the CitiesStatesWEB project that returns the city and state information.  The ServiceControl in the DyanmicSelectWEB project is assuming that web service is deployed to localhost and port 7001, so make sure to adjust that if your server settings are different.

I could have tried using IceFaces, an Ajax-enabled JSF framework, but I think it's important to get the fundamentals down before adding additional layers of complexity.  So my first recommendation is to start simple with plain HTML and JSON files.  Once you get the basics going, then add in the dynamic pieces (JSPs, etc).

The Dojo documentation has some excellent basic examples in the "Book of Dojo 1.0".  After reading the of the form basics, particularly the FilteringSelect example, I figured out the basic framework.  Each FilteringSelect object has an attribute called a "store" that is responsible for holding data for the options.  You can populate the store programmaticly in javascript, by invoking a URL that returns JSON, etc.  The example uses a static states.txt file that shows what the JSON looks like and I use that as a basis for my purposes.  It is easy to take the JSON response and create a new dojo.data.ItemFileReadStore and set the "store" value of the FilteringSelect to that new value without any complex parsing.  I use the same json.jsp for populating both the cities and the states; and the action code in the pageflow just populates some lists for that jsp that can be reused to populate any select-based Dojo element.

Here's a look at how easy Dojo makes it to wire up events to javascript functions.  This onLoad function gets called when the page loads via some javascript on the body tag.  The "states", "cities", and "myButton" references are the id's of the DOM objects.  "onChange" and "onClick" are the names of the events to register.   "onchange_states", "onchange_cities", and "button_click" are the names of javascript functions to call respectively when those events occur.

function onLoad() {
var states = dijit.byId("states");
dojo.connect(states, "onChange", "onchange_states");

var cities = dijit.byId("cities");
dojo.connect(cities, "onChange", "onchange_cities");

var button = dijit.byId("myButton");
dojo.connect(button, "onClick", "button_click");
}

Since Workshop has very nice Apache Beehive pageflow tooling, I just prototyped using that framework.  Below is a look at my site-map.  You can see how I started with a test.html file.  Once I got that working, then I migrated the code over to the index.jsp and added in the dynamic elements.  Each drop-down onChange calls a different pageflow action, that return dynamic JSON.  You can see that in the getCities action, I'm passing the entire form.  This way I can pull out the value of the selected state and only return the cities for that state.

pageflow [2]

Gotchas

Take note of this css code that the FilteringSelect requires to display properly.  I had to use this approach instead of the @import example used on the Dojo site due to an issue in one of the Eclipse plug-ins that caused a hang consistently.


<link rel="stylesheet" type="text/css" href=""dojo-release-1.0.2/dijit/themes/tundra/tundra.css" />

I decided to submit the form with a post when the state is selected since that is most likely how you would do more complex forms.  Here's what that function looks like.


function populate_cities()
{
var ajaxReq = {
form: dojo.byId("myForm"),
url: "getCities.do",
handleAs:"json-comment-filtered",
load: function(response){
dijit.byId('cities').store = new dojo.data.ItemFileReadStore({data:response});
},
error: function(data){
alert("Holy Bomb Box, Batman! An error occurred: " + data);
},
timeout: 2000
};
//dojo.xhrGet(ajaxReq); //Servlet get argement with doGet
dojo.xhrPost(ajaxReq); //Servlet get argement with doPost
}

I found that Dojo does this with a multi-part submission by default, so an extra annotation is necessary on the Pageflow to allow multi-part.


@Jpf.Controller(simpleActions = { @Jpf.SimpleAction(name = "begin", path = "index.jsp") }, multipartHandler=Jpf.MultipartHandler.memory )
public class Controller extends PageFlowController {

Conclusion

The Firebug plug-in is invaluable for debugging purposes.  I found the Javascript debugging and the ability to look at the XHR request/response values to be particularly helpful.  My example still has debugging turned on and to use this on a high-traffic site I would recommend turning that off and using some javascript compression.  Check out Skip's recent post for more detail on that.  If you have had a better experience using a different javascript framework like prototype, DWR, IceFaces, etc please leave a comment.  Overall Ajax programming is made easier with these frameworks and tools, but they are not quite as mature as what server-side java developers are used to, but they are getting there fast.

I had some ambitious plans to create a Workshop facet to add Dojo support to Dynamic Web projects, however that's going to be for another time.  Check out Konstantin's presentation if you have curiosity about how to do that.

Comments:

The ItemFileReadStore data is not binding with the xhrPost response. So no data is getting displayed in the second drop down.

Posted by Somnath Manna on August 24, 2008 at 08:57 PM PDT #

Post a Comment:
Comments are closed for this entry.
About

James Bayer Image
I was formerly a Product Manager on the WebLogic Server team based out of Oracle HQ. You can find my new blog at http://iamjambay.com.
Follow Me on Twitter
Oracle WebLogic

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today