Getting started with DWR is easy but there are a few important concepts you need to be aware of:

Remote calls with DWR - handling the asynchronous nature of AJAX with callbacks

DWR generates JavaScript proxy functions that are similar to the Java methods exposed using the <create ... > element, in your dwr.xml file.

The biggest challenge in creating a remote interface to match Java code across AJAX is the (usually) asynchronous nature of AJAX, compared to the synchronous nature of a normal Java call.

DWR solves this problem by introducing a callback function that is called when the data is returned from the server.

There are 2 recommended ways to make a call using DWR. Either by appending a call options object or a callback function to the parameter list.

  1. Call Options Object

    The recommended syntax is to make use of a call options object that specifies the callback function and other options.

    Suppose we have a Java method that looks like this:

    public class Remote {
        public String getData(int index) { ... }
    }
    

    We can use this from Javascript as follows:

    <script type="text/javascript"
        src="[WEBAPP]/dwr/interface/Remote.js"> </script>
    <script type="text/javascript"
        src="[WEBAPP]/dwr/engine.js"> </script>
    ...
    
    Remote.getData(42, {
      callback:function(str) { 
        alert(str); 
      }
    });
    

    '42' is just the parameter to the getData() Java function - see above.

    DWR will always pass a JavaScript version (serialized using DWR's converters) of the object returned from the remoted Java method as the first parameter of the callback. In this case str will contain the String that getData returns.

    This method has some advantages: Depending on your style it may be easier to read, but more importantly it allows you to specify extra call options.

    Timeouts and Handling Errors

    In addition to the callback function you can also specify a timeout, errorHandler, and several other call options. For example:

    Remote.getData(42, {
      callback:function(str) { alert(str); },
      timeout:5000,
      errorHandler:function(message) { alert("Oops: " + message); }
    });
    
  2. Simple Callback Functions

    An alternative approach is to simply append a callback function to your parameter list:

    function handleGetData(str) {
      alert(str);
    }
    Remote.getData(42, handleGetData);
    

    Alternatively you can use the all-in-one-line version:

    Remote.getData(42, function(str) { alert(str); });
    

Creating JavaScript objects to match Java objects

Suppose you have exposed the following Java method, with a Person Java Bean as a parameter:

public class Remote {
  public void doSomethingWithPerson(Person p) {
    // Some Java code that does something with Person p.
  }
}

And Person looks like this:

public Person {
  private String name;
  private int age;
  private Date[] appointments;
  // getters and setters ...
}

Then you can call this from Javascript like this:

var myJSPerson = {
  name:"Fred Bloggs",
  age:42,
  appointments:[ new Date(), new Date("1 Jan 2008") ]
};
Remote.doSomethingWithPerson(myJSPerson);

Any fields missing from the JavaScript representation will be left unset in the Java version.

Since the doSomethingWithPerson method returns 'void' we do not need to use a callback and can just leave it out. If you want to be notified of the completion of a server-side method that returns void then you can include a callback method. Obviously DWR will not pass any data to it.