| Close Window |
Putting AJAX functionality into your Web application can be a daunting task when you're first learning AJAX. After all you're a Java programmer not a JavaScript programmer. It can also be very frustrating having to learn how the different browsers handle XMLHttpRequests. It's been reported, however, that Internet Explorer 7 will support native XMLHttpRequests rather than requiring the developer to make ActiveX requests. This will make a Web developer's life a lot easier.
For Java Developers there are a number of different frameworks/libraries that hide most of the complexity of developing AJAX-enabled Web applications. For this purposes of this article I'll be using one of those libraries called DWR or Direct Web Remoting (http://getahead.itd.uk/dwr/). I chose DWR because I haven't found another framework/library that's easier to use or as flexible.
DWR is an Open Source Java library, distributed under the Apache License version 2, that lets JavaScript call Java methods as if they were running in the browser, when in fact they're running on the server. DWR isn't tied to any one framework so it should work with any standard servlet container.
There are a number of different ways that you can use DWR, and the extensive documentation shows most of them. I've found that having Java methods return the HTML code that I want displayed is the easiest way to learn DWR. Using it this way also allows for the most flexibility in your AJAX designs.
For this article I'll show you how to use DWR to develop two simple AJAX-enabled Web applications. The first Web application will be an old "Hello World" application. This will show just how easy it is to write an AJAX-enabled Web application with DWR. The second application will display the stats of the players on a baseball team. As you select a position, the names of players that can play that position appear in a dropdown select box. Then you can select the player to see their stats.
You'll need to start by downloading the DWR jar file from http://getahead.itd.uk/dwr/ and copy it to the lib directory of your Web application. The location of the lib directory will vary depending on what servlet container you're using. DWR is designed to work with any standard servlet container so feel free to use the one you're most comfortable with.
Once the DWR jar file is in the lib directory, you'll need to configure the Web application to use it. Add the following lines to the Web.xml file, located in the WEB-INF directory:
<servlet>
<servlet-name>dwr-invoker</servlet-name>
<servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>true</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>dwr-invoker</servlet-name>
<url-pattern>/dwr/*</url-pattern>
</servlet-mapping>
The <param-name> and <parm-value> tags between the <init-param> tag is optional but I've found the debug page to be extremely useful, however, you'll want to make sure it's turned off when you deploy the application. The debug page will be discussed in greater detail later in this article.
Now you'll need to create a dwr.xml file in the WEB-INF directory. This is the DWR configuration file and for the "Hello World" application you'll only need to put the following lines in it.
<!DOCTYPE dwr PUBLIC
"-//GetAhead Limited//DTD Direct Web Remoting 1.0//EN"
"http://www.getahead.ltd.uk/dwr/dwr10.dtd">
<dwr>
<allow>
<create creator="new" javascript="ajaxFunctions">
<param name="class" value="ajaxDemoHello.model.ajaxFunctions"/>
</create>
</allow>
</dwr>
The DWR configuration file defines what classes DWR can create for remote use by JavaScript. In the example above, I defined "ajaxFunctions" to be used by JavaScript to call a Java class named ajaxFunctions in the ajaxDemoHello.model package. The name of the class doesn't have to be the same name that you defined for JavaScript's use; I just find it convenient to keep the names the same.
There are a couple of restrictions to the names that can be used for classes and methods. You can't use any JavaScript reserve words. Most of the words that are reserved in JavaScript are also reserve words in Java so this is normally not an issue but something to keep in mind.
You'll also want to avoid overloaded methods because it's hit or miss on which method gets called. This is because JavaScript doesn't typecast its variables so DWR has to guess which overloaded method to call based on what the variable contains for data.
As an example, let's say there are two methods that are overloaded, one accepting an int as the argument and the other accepting a String as the argument. You then try to call the method that accepts the String as the argument but the String contains "42." DWR may interpret the 42 as the number 42 and call the method that accepts the int.
The "Hello World" application will have two files, an index.html file that contains the static Web page of the Web application and the ajaxFunctions class that contains the methods that DWR will use to implement the AJAX functionality of the Web page shown in Listing 1.
Once the "Hello World" Web application is deployed, you can test the AJAX functionality by using the DWR's debug page shown in Listing 2. To access the debug page you'll want to point your Web browser to http://{your Web server}:{port}/{your Web app}/dwr/, this will bring up a page that will look like Figure 1.
All classes that are configured in the dwr.xml file will be listed here. To test a class, click on the class name. In this case, there's only one class so click on the ajaxFunctions link and you should see a page that looks like the page in Figure 2.
One of the things that makes DWR so easy is this debug page. Not only does it let you test the AJAX functionality of each method but it also tells you what JavaScript files to include in the Web page to access this class with DWR.
About halfway down the page, you'll see the sayHello() method listed with an Execute button next to it. If you click the button, and everything is configured correctly, you'll see the "Hello from AJAX and DWR" message appear next to the Execute button.
The top of the debug page lists three scripts; two are listed as required and one is listed as optional for the ajaxFunctions class. The examples in this article need a function from the optional utility script, so you'll have to put all three scripts in the index.html page. These scripts should go in the head of the HTML page. You can simply cut each script line from the debug page and paste them into your code.
To display the string returned from the sayHello method, we have to write a JavaScript function to act as the callback function for the sayHello method, but DWR makes this easy too. Listing 3 contains this JavaScript function.
This creates a JavaScript function called displayHello that accepts one argument (remember JavaScript doesn't typecast its variables). The only line in the displayHello function uses the setValue function of the DWR utility script. This function takes the value of the second argument (displaystring) and alters the contents of the element with the id of the first argument (message). This will work with almost all HTML elements that use an id tag.
In the index.html page, change the line that displays "Click me" to the following line:
<a onClick='ajaxFunctions.sayHello(displayHello)'>Click Me:</a> <div id="messages">
Clicking on the "Click Me:" will trigger the sayHello method of the ajaxFunctions class. You may remember that the sayHello method doesn't accept an argument, but the line above passes one. The first argument in a method that's called with DWR is the JavaScript callback function that the output of the method is passed to. In this case the output of the sayHello method is passed to the displayHello javaScript function that we created above. The sayHello method doesn't accept any arguments but if it did the arguments would be added after the callback function.
The <div id="messages"> at the end of the line is where the DWRUtil.setValue will put the hello message. The new index.html file is in Listing 4. If the JavaScript files to include (those listed on the debug page) are different than the ones in Listing 4, change them to match the ones on the debug page.
With this new index.html deployed you'll be able to click on the "Click Me:" and the hello message will appear.
Congratulations, you've created your first AJAX-enabled Web application.
Here's a checklist of what's needed to integrate DWR with a Web application:
I. Copy the dwr.jar file to the lib directory of the Web application.
II. Edit the web.xml file so the Web application will recognize DWR.
III. Create the dwr.xml file to configure DWR.
IV. Write the Java class that DWR will use for the AJAX functionality.
V. Add the AJAX functionality to your Web application.
That's really all that's needed to develop an AJAX-enabled Web application with DWR.
Now that you've seen how easy it is to add AJAX functionality to your Web application with DWR, let's create the baseball statistics Web application.
When the application is first started, a list of available positions appears to the left of the screen that can be clicked on. The page should look like Figure 3.
After you click on a position, a list of players that are available for that position will appear in a dropdown selector. Figure 4 shows what it looks like if you selected center fielder.
Once a player is selected, his statistics will appear. Figure 5 shows what this looks like.
Now that we have a basic idea of how the Web application is supposed to function, it's time to start the development. Steps one and two will be the same for almost all applications. Before you go live with the Web application, just remember to disable the debug page.
For the baseball statistics Web application, step three will also be the same as the "Hello World" application. I usually name the Java class that handles the AJAX functionality ajaxFunctions.java just to keep it consistent between applications. Below is the dwr.xml file for the baseball statistics Web application:
<!DOCTYPE dwr PUBLIC
"-//GetAhead Limited//DTD Direct Web Remoting 1.0//EN"
"http://www.getahead.ltd.uk/dwr/dwr10.dtd">
<dwr>
<allow>
<create creator="new" javascript="ajaxFunctions">
<param name="class" value="com.thelinuxdog.model.ajaxFunctions"/>
</create>
</allow>
</dwr>
Step four is to develop the Java class that DWR will use for the AJAX functionality. Before this class can be developed, the class that will handle all the data access functions needs to be written. Normally this class would use a database to store the data, but for simplicity's sake this class will store the data in an array of Strings. Listing 5 contains the dataFunctions class.
The dataFunctions class contains two methods. The first method, returnNames, returns a list of names and the number of the players for a given position. The position is passed to the method through its only argument.
The second method, returnStats, returns an array of Strings that contains the statistics for the player with a given number. The player's number is passed to the method through its only argument.
Listing 6 contains the ajaxFunctions class.
The ajaxFunctions class also contains two methods. The first method, displayNames, displays the dropdown box that contains the players for a given position. The method accepts a String that contains the position that you want to obtain the list of players as its only argument.
The displayNames method begins by getting a list of players who can play the given position from the returnNames method of the dataFunctions. It then begins to build the HTML code for the dropdown box by defining a form with a name of playerform.
The next line defines the select box. The onChange function of the select box calls the displayStats method of the ajaxFunctions class with DWR. This is very similar to the onClick method in the "Hello World" Web application except we're passing two arguments this time because the displayStats method will accept one argument. Keep in mind the first argument passed to a method with DWR is the JavaScript callback function that will accept the output of the Java method. The second argument of the function uses this.options[this.selectedIndex].value to get the number of the selected player and that number is what's passed to the displayStats method.
The options for the select box are then added using the list of names and numbers of the players that were returned from the returnNames method. The value of the option is the player's number and the element is the player's name. The String that represents the HTML code for the select box is then returned, which DWR will then pass to the JavaScript callback function to display on the Web page.
The second method in the ajaxFunctions class is called displayStats. This method returns the HTML code to display the statistics for the player with the number that's passed to the displayStats method in its only argument. This function is similar to the returnNames method. It begins by getting the data needed from the returnsStats method of the dataFunctions class and then builds the HTML code to display the statistics. The method then returns the String that contains the HTML code to display the statistics.
The Web application can be deployed at this point to test the ajaxFunctions class with the DWR debug page. After the application is deployed, point the Web browser to http://{your Web server}:{port}/{your Web app}/dwr/ and you should see the debug page if everything is configured correctly. If you click on the ajaxFunctions link, you'll be taken to the ajaxFunctions debug page, which will also list the JavaScript files needed by the Web application to use the ajaxFunctions class with DWR. Listing 7 contains the index.jsp file for the baseball statistics Web application. Remember to substitute the links to the JavaScript files with the ones from your ajaxFunctions debug page.
You may have noticed that in the ajaxFunctions class the displayStats method was called by the displayNames method. Calling an AJAX method from another AJAX method is perfectly fine under one condition, the JavaScript functions needed by the AJAX method has to be on the static HTML page and not created by the AJAX method. For example, when the displayStats method is called it sends the output to the JavaScript callback function called displayStatsJS. Therefore, the displayStatsJS function needs to be in the static HTML page, or in this case the static jsp page called index.jsp.
That is all there is to developing an AJAX-enabled Web application with DWR. The next question is "what do you do if the AJAX functionality doesn't function properly?" The debug page created by DWR is the first tool that I use for debugging my AJAX-enabled applications. It's good for testing if DWR is configured properly and if the functions called through DWR are working properly.
If everything appears to work properly through the debug page but the AJAX part of your Web application still isn't working, you'll need to know a little bit of JavaScript to debug your application. The most useful JavaScript command for debugging is the alert command that pops up an alert window. For example, the command alert("Hello"); pops up an alert box with the word "Hello" in it. This can be useful to see if you're getting to your callback functions and to test what's in the variables.
If I were to change the displayNameJS javaScript function to:
function displayNamesJS(data)
{
alert(data);
DWRUtil.setValue("names",data);
}
everytime the displayNamesJS function is called, an alert pop-up box that contains the HTML code that's going to be displayed on the page would appear
As you can see it's pretty easy to develop AJAX-enabled Web applications with DWR. DWR handles all of the compatibility issues with the different browsers and the asynchronous calls to the server so all you have to do is write the Java classes that DWR will use.
I've been using DWR version 1.x for a while now in my development environment and found it to be very stable. They are in the process of developing a version 2 that will introduce "Reverse Ajax," which will allow Java on the server to send JavaScript to the client.
In this article I showed how to develop AJAX-enabled Web applications by having DWR pass HTML code back to the browser. To me this is the easiest and most flexible way of using DWR, but not the only way. The DWR Web site has very good documentation and examples (http://getahead.itd.uk/dwr/). I'd really recommend that if you plan on using DWR in your production environment that you spend a little time reading the full documentation to find the best way of using DWR for your project.
© 2008 SYS-CON Media Inc.