Translations of this page:

Java Enterprise Edition, AJAX with Direct Web Remoting

Ajax is a programming method that has taken the web development community by storm over the last couple of years. You will come across it in applications such as Google's GMail. It enables desktop like interaction with Web based applications. The term was coined by Jesse James Garrett in February 2005 and stands for Asynchronous Javascript and XML. The technique overcomes limitations in the Web's HTML/HTTP request/response paradigm. In the traditional web programming model a web browser connects to a server and requests a resource, the server performs whatever tasks are necessary to retrieve the page's data and returns this as a new HTML page. Even small updates to a page's data require a new page to be prepared and transmitted. This waists network bandwidth as well as CPU cycles on the server and client and makes the user interface seem clunky and sluggish. It would be better if just the data that needed to be updated could be asked for and returned.

Enter Ajax. To give a concrete example a user could be filling in a registration form. In the traditional web model on completing his postal code a piece of Javascript could detect this event, send the partially completed form off to the server and retrieve a new form with the town and state (and even road in Canada or the UK) corresponding to the zipcode. With Ajax the same event is detected but just the user's postal code is transmitted and server returns the corresponding address information, wrapped in XML, leaving the browser to update the appropriate fields without resending and rendering the entire web page

Ajax is asynchronous because the data exchange with the server does not interfere with normal page loading. Ajax functionality is implemented in the Javascript programming language and data retrieved using the technique is usually formatted using XML (eXtensible Markup Language). Ajax is multi-platform and based on open standards. Ajax has its roots in Microsoft's Remote Scripting (MSRS) which was introduced in the late 1990s for Internet Explorer (IE) and later Netscape Navigator versions 4.0. Microsoft introduced the key XMLHttpRequest object with IE 5.0.

The zipcode example is just a single area where Ajax could be used but one that interested me. In short Ajax can be used where ever part or all of the variable data needs to be updated in a page without changing the overall page layout. Tree views, menus, forms are all potential applications.

A couple of the disadvantages of Ajax is the learning curve and cross browser support. It relies on Javascript and there are oftendiscrepancies as to how this is implemented on different web browsers. Ajax applications require testing across different web browsers and you will often encounter browser specific code to cope with the differences. A framework can abstract these differences as well as bootstrapping all the Javascript infrastructure required to get an application running. I initially looked at Google's Ajax toolkit but settled on the lighter weight Direct Web Remoting (DWR). DWR supports the core theme of Ajax - communication between web page components and a server. It makes invoking methods on a Server-side Java object transparent through a local Javascript object. The aim of this example application is to call an EJB 3.0 entity bean to retrieve town and state values given a zipcode and to update those values in a web form.

Configuration

DWR exports Java object to the Ajax layer through the DwrServlet which is contained in the dwr.jar directory. We need to configure this servlet in the WEB-INF/web.xml directory. Here we say any url pattern that begins with /dwr/ is mapped to the DwrServlet class.

<servlet>
  <servlet-name>dwr-invoker</servlet-name>
  <display-name>DWR Servlet</display-name>
  <servlet-class>org.directwebremoting.servlet.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>

Entity Beans

We now need an Entity bean to access our zip data. This contains properties for zipcode, city and state representing columns in a database table called ziplocation.

....
@Entity
@Table(name="ziplocation")
public class Zip implements Serializable {
    private int zipcode;
    private String city, state;
 
    public Zip() {
    }
 
    public Zip(int zipcode, String city, String state) {
        this.zipcode = zipcode;
        this.city = city;
        this.state = state;
    }
 
    public String getCity() { return city; }
 
    public void setCity(String city) { this.city = city; }
....
}

We use the Zip Data Access Object to interface with this bean. The findAddress() method takes the zipcode as a string. It looks up a reference to the Entity Manager, which handles the relationship with the ORM (Object Relational Mapper). It then looks up the Zip Entity that corresponds to the zipcode and returns this.

....
public class ZipDAO {
    public Zip findAddress(String code) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("MyPu");
        EntityManager manager = emf.createEntityManager();
 
        int id = Integer.parseInt(code);
        Zip z = manager.find(Zip.class, id);
        return z;
    }
}

Ajaxified HTML Page

The HTML file implements the client side of the DWR Ajax model. When the postcode field is filled the fillAddress() method is called. This calls the client AddressLookup.findAddress() method, a client side version of the remote Java method. The DWR layer is responsible for marshalling the data over the XMLHttpRequest object.

<HTML>
<HEAD>
<TITLE>zipcode</TITLE>
  <script type='text/javascript' src='/mvc/dwr/interface/AddressLookup.js'></script>
  <script type='text/javascript' src='/mvc/dwr/engine.js'></script>
  <script type='text/javascript' src='/mvc/dwr/util.js'></script>
 
  <script type='text/javascript'>
    function fillAddress() {
      var postcode = dwr.util.getValue("postcode");
      AddressLookup.findAddress(postcode, function(address) {
        dwr.util.setValues(address);
      });
    }
</script>
</HEAD>
<BODY>
<table>
  <tr>
    <td>Zipcode/Postcode:</td>
    <td><input id="postcode" type="text" onchange="fillAddress()"/></td>
  </tr>
  <tr>
    <td>House name/number:</td>
    <td><input id="house" type="text"/></td>
  </tr>
  <tr>
    <td>Line 2:</td>
    <td><input id="line2" type="text"/></td>
  </tr>
  <tr>
    <td>City:</td>
    <td><input id="city" type="text"/></td>
  </tr>
  <tr>
    <td>State:</td>
    <td><input id="state" type="text"/></td>
  </tr>
</table>
<BODY>
</HTML>

You will notice the Javascript include AddressLookup.js; this is not something we've written but is generated by the DWR engine based on the signature of the remote methods. We need to tell DWR the name of teh remote class and method as well as the type of return object. In this case a bean with getters and setters. Here is the excerpt of the WEB-INF-dwr.xml file

<dwr>
  <allow>
    <create creator="new" javascript="AddressLookup" class="com.abcseo.ZipDAO">
    <include method="findAddress"/>
    </create>
    <convert match="com.abcseo.Zip" converter="bean"/>
  </allow>
</dwr>

That's it. Package all the files up into a WAR or EAR and deploy to your favourite Web Application Server, in our case JBoss 4.2.1.

To do We'll need to set up our Zip database.

Ajax - What's going on under the covers?

Performance Testing Ajax Applications

Resources

tech/java/java-ee-ajax-with-dwr.txt · Last modified: 2007/10/04 21:20 by davidof
Recent changes RSS feed