Skip to main content

Developing Applications Using Reverse Ajax

March 22, 2007

{cs.r.title}



Ajax has long
been known for providing an enhanced user experience, allowing a
web page to be updated using data from a web server without the
need for a full page refresh. Now, however, web developers are
increasingly requiring Ajax applications to update page data, not
only when the user sends a request, but also when the server
decides an update is required. Examples of this include a
multi-user application, where all users need to be aware of the
changes other users make, or a monitoring application, with the
server needing to let the browser know that its state has
changed.

In such situations, developers of Ajax applications can employ
various techniques to ensure this "push" from the server to the
browser occurs. But which technique is best for which situation?
Answering this question and then implementing it can be a lengthy
process. This article will investigate one answer to this
problem.

DWR, hosted on
java.net, is a Java open source library that helps developers to
write websites that include Ajax technology. When DWR broke onto
the Ajax scene with release 1.0, its announced mantra was
"Easy Ajax
for Java
." It aids the developer in many ways, not least by
allowing code in the web browser to use Java functions running on
the web server as if they were in the browser.

With release 2.0, DWR continues on the same theme, removing from
the developers shoulders the pesky problem of "pushing"
information. It introduces the term reverse Ajax to describe
this asynchronous transfer of messages from server to browser or
browsers. While, as mentioned above, techniques for doing this
already exist, the beauty of "reverse Ajax" is that it wraps them
all up neatly and then automatically selects the best method to use
transparently to the user.

The three techniques DWR supports are:

Polling
At regular and frequent intervals, the browser sends requests to
the server to see if the page has been updated.
Comet
After a request has been received from the browser, the server
keeps the reply open so that it can pass down information when it
arrives. This is also known as a long-lived HTTP
connection
.
Piggyback
When the server has an update to send, it waits for the browser
to make a request and then sends the update in addition to the
requested information.

When comparing the three techniques above, it is easy to see
that when using the polling or comet techniques, updates from the
server to the browser would occur quicker than when using
piggyback. However, polling and comet have the disadvantage of
producing extra network traffic, while piggyback does not.

DWR recognizes that speed of updates and amount of network
traffic will be something the developer wants to have a hand in
controlling. Therefore, it separates the three techniques into two
categories: comet and polling are classed as active, and
piggyback is classed as inactive. If the developer requires
a faster "push" of information from the server to the browser, and
is willing to take the hit of extra network traffic, she can enable
active reverse Ajax. This allows comet and polling to be
brought into the equation when DWR is deciding which technique to
use. If active reverse Ajax is not enabled, then piggyback is used.
In this way, reverse Ajax is always available even when active
reverse Ajax is turned off.

So how does DWR's reverse Ajax make things easy for the
developer?

The example below aims to demonstrate how easily we can add a
chat web page using reverse Ajax to an existing web application.
The web page is a simple multi-user chat demo, allowing a number of
users to see the messages that each submits. Reverse Ajax is used
to collect the messages, and server-side browser manipulation
updates the pages with the results. The emphasis is not on fancy
graphics, but on demonstrating how simply the chat functionality
can be added and how easily we can implement reverse Ajax. The
source to the chat example is included with the DWR 2
distribution.

First, we will look at how the JavaChat web page and the server-side Java are constructed. Then we will add the reverse Ajax code
to show how easily it can be implemented.

The JavaChat Web Page

The web page consists of two parts: the first is an input field
where you can type a message; the second is the area where you can
see the messages that you have typed. This is also the area where
messages will appear from other users. Figure 1 shows what it looks
like.

The chat web page />
Figure 1. The JavaChat web page

The HTML is very simple:

[prettify]
<h1>Java Chat</h1>

<p>This is a very simple chat demo that uses reverse ajax
to collect messages and server-side browser manipulation to
update the pages with the results.</p>

<p>
  Your Message:
 <input id="text" onkeypress="dwr.util.onReturn(event, sendMessage)"/>
 <input type="button" value="Send" onclick="sendMessage()"/>
</p>
<hr/>

<ul id="chatlog" style="list-style-type:none;">
</ul>

[/prettify]

A few lines of JavaScript are also included. The JavaScript
calls the Java code that will do the work.

[prettify]
<script type='text/javascript' src='../dwr/engine.js'> </script>
<script type='text/javascript' src='../dwr/interface/JavaChat.js'> </script>
<script type='text/javascript' src='../dwr/util.js'> </script>

[/prettify]

Here engine.js contains the core of DWR; util.js
contains some optional utility functions for use with DWR; and
JavaChat.js is the JavaScript dynamically generated by DWR
as the remote version of JavaChat.java, the Java class
we shall view in more detail below. "http://www.getahead.ltd.uk/dwr/documentation.html">Full
documentation
for engine.js and util.js can be
seen at the DWR website.

A JavaScript function is also included to be fired off by the
browser whenever the Send button is pressed.

[prettify]
<script type="text/javascript">
    function sendMessage() {
      JavaChat.addMessage(dwr.util.getValue("text"));
    }
</script>

[/prettify]

This calls the addMessage() method in the
JavaChat class, as we shall below.

Server-Side Java

We have two classes to do the server-side work. The first is the
Message class. This holds a single string entered by
the user. The Message also maintains a unique ID as a
property. For now, we are going to cheat by using the current time
in milliseconds as the ID.

[prettify]
import org.directwebremoting.Security;

public class Message
{
   public Message(String newtext)
   {
     text = newtext;
     if (text.length() > 256)
     {
        text = text.substring(0, 256);
     }
     text = Security.replaceXmlCharacters(text);
    }

    public long getId()
    {
        return id;
    }

    public String getText()
    {
        return text;
    }

    private long id = System.currentTimeMillis();

    private String text;
}
[/prettify]

The constructor does a few simple things: it shortens the
messages to 256 characters and uses the DWR Security
class to ensure that the characters are valid.

The other class on the server is the JavaChat
class. It keeps track of the messages sent to the server.

[prettify]
public class JavaChat
{
    public void addMessage(String text)
    {
  if (text != null && text.trim().length() > 0)
        {
            messages.addFirst(new Message(text));
            while (messages.size() > 10)
            {
                messages.removeLast();
            }
        }
        //Reverse Ajax code to be added here shortly
    }

    private LinkedList messages = new LinkedList();

    protected static final Logger log = Logger.getLogger(JavaChat.class);
}
[/prettify]

As mentioned earlier, addMessage() is called in
response to a user typing in the input area, the text
parameter being the new text to add to the list. The code ensures
that only the last ten messages are held in the list.

Now we have the basic code written; where should the reverse
Ajax code be added to ensure that the information can flow from the
server to the browser?

Implementing Active Reverse Ajax

Reverse Ajax is implemented in three places. The
JavaChat web page, the JavaChat class and the
web.xml file.

In the JavaChat web page, the following line should
be included, allowing active reverse Ajax (ARA) to occur.

[prettify]
<body onload="dwr.engine.setActiveReverseAjax(true);">
[/prettify]

The main code change occurs in the JavaChat class.
The following lines should be included in the
addMessage() method. You may have noticed the comment
above that indicates where it should be inserted.

[prettify]
WebContext wctx = WebContextFactory.get();
String currentPage = wctx.getCurrentPage();

   // Clear the input box in the browser that kicked off this page only     
   Util utilThis = new Util(wctx.getScriptSession());
   utilThis.setValue("text", "");

   // For all the browsers on the current page:
   Collection sessions = wctx.getScriptSessionsByPage(currentPage);
   Util utilAll = new Util(sessions);

   // Clear the list and add in the new set of messages
   utilAll.removeAllOptions("chatlog");
   utilAll.addOptions("chatlog", messages, "text");
[/prettify]

As part of configuring your app server's web.xml to
understand DWR, the following lines of code need to be added to the
web.xml file. You will notice a parameter called
pollAndCometEnabled with its value set to
true. By setting the value to true we ensure that
active reverse Ajax is turned on and polling or comet techniques
can be used.

[prettify]
<servlet>
    <servlet-name>dwr-invoker</servlet-name>
    <display-name>DWR Servlet</display-name>
    <description>Direct Web Remoter Servlet</description>
    <servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>
    <init-param>
      <param-name>debug</param-name>
      <param-value>true</param-value>
    </init-param>
    <init-param>
      <param-name>pollAndCometEnabled</param-name>
      <param-value>true</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>dwr-invoker</servlet-name>
    <url-pattern>/dwr/*</url-pattern>
</servlet-mapping>

[/prettify]

Configuring DWR

The first step in configuring DWR is to copy dwr.jar into
your web app. You can download dwr.jar from its "https://dwr.dev.java.net/">java.net project. Next, you need to
tell DWR about the chat server you have just created. The DWR
configuration file dwr.xml file should be placed alongside
web.xml in your WEB-INF folder. For your chat application,
dwr.xml should look like this:

[prettify]
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 2.0//EN"
"http://getahead.ltd.uk/dwr/dwr20.dtd">

<dwr>
  <allow>
<create creator="new" javascript="JavaChat">
        <param name="class" value="[your.package].JavaChat"/>
        </create>
        <convert converter="bean" match="[your.package].Message"/>
</allow>
</dwr>
[/prettify]

In the code above, [your.package] should be
replaced with the package that you used.

We are telling DWR it is OK to create JavaChat
classes for remoting to the browser, and that in JavaScript they
will be called JavaChat. It also says that
Message is safe to be used as a parameter.

And that's it! We have a basic multi-user, web-based chat system
that uses reverse Ajax with active reverse Ajax turned on, in under
200 lines of code.

Conclusion

Using DWR version 2.0 can make it very easy to add chat
functionality to an application, allowing updates to be pushed from
the server to the browser or browsers so that all users are aware
of changes made. DWR's reverse Ajax introduces a very neat way to
manage this transfer of information. It takes responsibility for
deciding which techniques (polling, comet or piggyback) are best to
use in each situation. It is easy to implement, thereby leaving the
programmer free to concentrate on developing other areas of her
application.

Resources

width="1" height="1" border="0" alt=" " />
Katherine Martin works as a J2EE developer and consultant in the UK for Xansa Ltd.
Related Topics >> Programming   |   Web Development Tools   |   

Comments

thanks. this is perfect for

thanks. this is perfect for me.

from downloaded dwr.jar file, I didn't get ...

from downloaded dwr.jar file, I didn't get dwr/interface/JavaChat.js. I want to develop a chat application with reverse ajax. Please help me for the same

@SelviSibi You wont find JavaChat.js in the dwr.jar. This ...

@SelviSibi
You wont find JavaChat.js in the dwr.jar. This is a virtual JS file. Its name should match with the 'javascript' attribute value in the dwr.xmls create tag.