Skip to main content

Developing AJAX Applications the Easy Way

August 25, 2005

{cs.r.title}









Contents
The Chat Web Page
Server-Side Java
Configuring DWR
The Client-Side Scripting
Conclusion
Resources

AJAX is the
buzzword of the moment among web developers, so much so that you
could be sick of introductions to AJAX by now (if that's the case,
skip down to "The Chat Web Page"). AJAX is
a technology that is hotly debated from many angles, but it has
stuck because it encapsulates something that is new from a user's
perspective. The functionally that is newly available to all web
users is "in-page replacement": the ability for a web page to
change using data from a web server without totally redrawing
itself. This functionality has been around in Mozilla and Internet
Explorer for a while, but it is only recently that Safari and
Konqueror users have been able to join in.

It is this ability to have web pages that update dynamically
that is changing the way users interact with the web. For
example:

Activity Old Style AJAX Style
Scrolling in a mapping website Click on a right arrow to refresh whole page. Drag map area to the right--and watch the map scroll, like
Google Maps.
Looking up a word in a dictionary Enter the word, and click Submit to see a definition for that
word.
Begin typing the word, see possible matches as you type and the
definitions as soon as you finish typing, like "http://www.objectgraph.com/dictionary">ObjectGraph
Dictionary
.
Interacting in online forum Type message, click Submit, regularly click "check new
messages".
Type messages, and wait as new replies appear automatically
without needing your interaction. We will create a site like this
in this article.
Filling out form with a number of fields Visit a number of pages of a "wizard," getting error messages
about invalid fields.
Fill out a form that reports on errors as you type, and
can dynamically add data (like filling in full address details from
a zip code) without needing a slow page refresh.

AJAX isn't the best acronym in the world: it stands for
Asynchronous JavaScript and XML. This does nothing to
describe the benefits to a user: the technology behind it does not
have to be asynchronous, and the best implementations don't
necessarily use XML, either. However, the buzzword has stuck so we
are better off going with the flow now.

The problem for the web developer is that while this is a very
attractive way of creating websites, and one where you can get
started without a huge amount of effort, there are a number of
pitfalls that can make life harder. All browsers have
different quirks, so you can easily discover that, for example, you
have locked Mac users out of the party.

DWR, hosted on
java.net, is an Java open source library that helps developers
to write websites that include AJAX technology. Its mantra
is "Easy
Ajax for Java
." It allows code in a web browser to use Java
functions running on a web server as if they were in the browser.

This article demonstrates the use of DWR to create a multi-user
web-based chat site. It demonstrates how simple it is to integrate
JavaScript in the web browser with Java on the server. The aim is
to have a fully functional system in about 100 lines of code for
both the client and the server. The emphasis will not be on fancy
graphics or lots of chat features, because that would distract
us from the core business of how to write AJAX code without lots of
effort.

The Chat Web Page

The web page has two parts: one area where you can see the
messages that others type, and an input field where you can type
messages yourself. Figure 1 shows what it looks like.

The chat web page
Figure 1. The chat web page

The HTML is very simple:

Messages:




  Your Message:
 
        onclick="sendMessage()"/>

We'll come to the JavaScript code in a bit, but let's start with
the server side. Just how much code do you need for a multi-user
web-based chat system?

Server-Side Java

We have two classes to do the server-side work. The first is the
Message class that 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:

public class Message
{
    public Message(String newtext)
    {
        text = newtext;
        if (text.length() > 256)
        {
            text = text.substring(0, 256);
        }
        text = text.replace('<', '[');
        text = text.replace('&', '_');
    }

    public long getId()
    {
        return id;
    }

    public String getText()
    {
        return text;
    }

    long id = System.currentTimeMillis();
    String text;
}

The constructor does a few simple things: it shortens messages to
256 characters and replaces < with [
and & with _ to prevent abuse. All
fairly simple so far.

The other class in the server is the Chat class
that keeps track of the messages sent to the server--also very
simple:

public class Chat
{
    public List addMessage(String text)
    {
        if (text != null &&
            text.trim().length() > 0)
        {
            messages.addFirst(new Message(text));
            while (messages.size() > 10)
            {
                messages.removeLast();
            }
        }

        return messages;
    }

    public List getMessages()
    {
        return messages;
    }

    static LinkedList messages =new LinkedList();
}

And that's it for the server-side code!

Two of these methods are important from the web browser's point
of view: addMessage(), which is called in response to
a user typing in the input area, and getMessages(),
which is polled from time to time to see if anyone else has said
anything.

Configuring DWR

Now we need to remote these two methods to the web browser.
The first step 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
configure your app server's web.xml to understand DWR. The
standard bit of code looks like this:


  dwr-invoker
  DWR Servlet
  uk.ltd.getahead.dwr.DWRServlet
 
    debug
    true
 



  dwr-invoker
  /dwr/*

Finally, you need to tell DWR about the chat server you just
created. Specifically, you need to tell it two things:

  • That Chat is safe to be remoted to the
    browser.
  • That Message is allowed as a parameter.

DWR could do the second bit for you, but we'll do it this way to
make sure that you don't give away access to anything by mistake.
The DWR configuration file, dwr.xml, is placed alongside
web.xml in your WEB-INF folder. For your chat application,
dwr.xml should look like this (obviously, replace the
[your.package] bits with the package that you used
from the code above):


    "-//GetAhead Limited//DTD Direct Web Remoting 1.0//EN"
    "http://www.getahead.ltd.uk/dwr/dwr10.dtd">


 
   
     
   

   
 

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

The Client-Side Scripting

The final bit is the JavaScript that is fired off by the HTML to
call into the Java code. The good news is that DWR makes this bit
easy. Typically, the JavaScript code for this type of thing would
contain complex XMLHttpRequest code, DOM manipulation,
and parameter collation. With DWR, you don't worry about any of
that.

First we include the JavaScript that tells the browser about the
Chat code. There are there useful script lines:



The script engine.js contains the core of DWR. Generally, you just
include it as is, and then ignore it. There are a few methods in it
that are sometimes useful, but you can see the "http://www.getahead.ltd.uk/dwr/documentation.html">full
documentation
for them at the DWR website. The script util.js
contains some utility functions that are totally optional, but will
help you greatly in getting anything done with DWR. Chat.js
is dynamically generated by DWR as the remote version of
Chat.java. If you look at it, you'll see something
like this:

[prettify]
Chat.addMessage = function(callback, p0) { ... }
Chat.getMessages = function(callback) { ... }
[/prettify]

DWR does everything it can to make the JavaScript version of
your Java code as simple as possible, but there are some things you
need to be aware of. The most obvious is that the "A" in AJAX
stands for asynchronous; so by definition, the remote method is
not executed the instant your JavaScript code is executed. This
would not be an issue, except for the complexity of knowing what to do
with the values returned by Java to the browser. DWR solves the
problem by asking for a callback method, to which it will pass the
returned data. The first parameter to any DWR-generated method is
always the callback function.

Above, we created a web page with a JavaScript function that
we've not implemented, until now: the sendMessage()
event is fired off by the browser whenever the "send" button is
pressed. As you might guess, this is going to call
Chat.addMessage():

function sendMessage()
{
    var text = DWRUtil.getValue("text");
    DWRUtil.setValue("text", "");
    Chat.addMessage(gotMessages, text);
}

The first line gets the value from the input field.
DWRUtil.getValue() works with most HTML elements, so
long as they have an id attribute (in this case, the
input element has an id="text").

Next, we use the setValue() method to blank out the
input element; again, the setValue() is very smart at
working out what to do with your data and how it should update your
web page with the new data.

Then we call Chat.addMessage() and ask DWR to
return the list of messages typed by other web users to the
gotMessages() function. It looks like this:

function gotMessages(messages)
{
    var chatlog = "";
    for (var data in messages)
    {
        chatlog = "
" + messages[data].text +
            "
" + chatlog;
    }
    DWRUtil.setValue("chatlog", chatlog);
}

This is where DWR excels. The Java method
Chat.addMessage() returned a List of
Message objects. DWR has automatically converted this
into an array of JavaScript objects. All we need to do in
gotMessages() is to iterate over the messages array,
getting the text member from each object in the array, and build
some HTML from it. Finally, we push the string we have created into
the div using the ever-versatile
setValue() method.

And that's it! We have a basic multi-user, web-based chat system
in about 100 lines of code, for both the client and server code.

There are a number of things missing for this to be useful: a
polling method that uses setTimeout() to call
Chat.getMessages() would keep things flowing a bit
more. The downloaded code contains an extra six lines of JavaScript
to make this happen. We could also add code to only alter the
display if new messages have arrived; this would make for a
flicker-free display. Finally, having a back-off mechanism where
the browsers poll the server less often if nothing much is
happening would be a good idea to prevent swamping the server.

You can see the final version "http://www.getahead.ltd.uk/dwr/demo-chat.html">here. It adds
the features listed above, plus highlighting of new messages--all
of which takes an extra 50 or so lines of JavaScript.

It is also worth checking out
http://localhost:8080/[YOUR-WEB-APP]/dwr, which is a test
debug page that automatically shows you the classes you have
remoted, and allows you to test their functionality.

Conclusion

Using DWR can make creating cross-browser AJAX websites very
easy, and introduces a very neat way to interact between JavaScript
in the web browser and Java on the server. It is simple to get
started with and integrates well with your current website.

Resources

width="1" height="1" border="0" alt=" " />
Joe Walker is a developer and consultant working on advanced web development techniques like Ajax.
Related Topics >> Web Development Tools   |