Thursday, May 17, 2007

Direct Web Remoting - A Tutorial


The DWR / Direct Web Remoting is an open source solution under the Apache license for the developer who wants to use AJAX and XMLHttpRequest in an easy way.



A Step by Step example:

1) Create the java service class :

package com.example.dwr;

public class DWRPersonService {

public Person[] getAllPersons() {

Person[] list = new Person[3];

/* .............................
Call your Ejb / DAO here
and populate values in the array
.............................
*/

Person info = null;
info = new Person();
info.setId(1L);
info.setName("sam");
info.setCity("bangalore");
info.setCountry("india");
list[0] = info;

return list;
}//end of getAllPersons

}//end of Class

2) Create the java bean class. (can be your Info or Transfer Object)

package com.example.dwr;

public class Person {

private Long id;
private String name;
private String city;
private String country;

/*
* Getters and Setters are defined here
*/

/**
* @return the id
*/
public Long getId() {
return id;
}

/**
* @param id the id to set
*/
public void setId(Long id) {
this.id = id;
}

/**
* @return the name
*/
public String getName() {
return name;
}

/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}

// ...............

}//end of Class

3) Configure DWR in WebXml

Start by specifying DWR's existence in the web.xml

<servlet>
<servlet-name>dwr-invoker</servlet-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>
</servlet>


Include dwr.jar in the WEB-INF/lib folder.

Place the scripts and css files in the respective folders.

You can download the latest jar from DWR Site

For support of autocomplete feature download the script.aculo.us-js-1.x.zip

4) Configure the dwr.xml

<!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="JDate">
<param name="class" value="java.util.Date"/>
</create>

<create creator="new" javascript="DWRPersonService">
<param name="class" value="com.example.dwr.DWRPersonService"/>
<include method="getAllPersons" />
</create>

<convert converter="bean" match="com.example.dwr.Person"></convert>
</allow>
</dwr>

We specify here to create a new js file for DWRPersonService.
The DWR engine will generate a file DWRPersonService.js at runtime
with the function getAllPersons.

The DWRPersonService.js created at run time by DWR Engine, looks as follows:

// Provide a default path to dwr.engine
if (dwr == null) var dwr = {};

if (dwr.engine == null) dwr.engine = {};

if (DWREngine == null) var DWREngine = dwr.engine;

if (DWRPersonService == null) var DWRPersonService = {};

DWRPersonService._path = '/dwr-sample/dwr';

DWRPersonService.getAllPersons = function(callback) {
dwr.engine._execute(DWRPersonService._path, 'DWRPersonService', 'getAllPersons', callback);
}

5) Create your Jsp.

Include the following js files from DWR.

<script type='text/javascript'
src='<%= request.getContextPath() %>/dwr/engine.js' />
<script type='text/javascript'
src='<%= request.getContextPath() %>/dwr/util.js' />

Also include the js file created for you, as defined in dwr.xml

<script type='text/javascript'
src='<%= request.getContextPath() %>/dwr/interface/DWRPersonService.js' />

Include the following js and css files for AutoComplete feature.

<link rel="stylesheet" type="text/css"
href="<%=request.getContextPath() %>/styles/autocomplete.css"/>
<script type="text/javascript" src="<%= request.getContextPath() %>/scripts/prototype/prototype.js"/>
<script type="text/javascript" src="<%= request.getContextPath() %>/scripts/script.aculo.us/effects.js"/>
<script type="text/javascript" src="<%= request.getContextPath() %>/scripts/script.aculo.us/controls.js"/>
<script type="text/javascript" src="<%= request.getContextPath() %>/scripts/autocomplete.js"/>

Create a text field with id personName. Create a div with the class auto_complete.
Instantiate the function AutoCompleter which takes the following arguments.
i)Id of the textField
ii)Id of the autocomplete Div for this textField
iii)function to populate the list – uses DWR
iv)Optional arguments like valueSelector – property to be listed from the Bean object, chioces – maximum number of choices to be displayed etc.
Finally, call the method DWRUtil.useLoadingMessage on body onLoad.

<script language="javascript">
function updatePersonList(autocompleter, token) {
DWRPersonService.getAllPersons(function(data) { autocompleter.setChoices (data); });
}
</script>

<body onload="DWRUtil.useLoadingMessage();">

Search Person: <input id="personName" type="text" style="width:250px;" / >

< div id="personListDiv" class="auto_complete" > </div>

<script type="text/javascript">
new Autocompleter.DWR('personName', 'personListDiv', updatePersonList,
{ valueSelector: function(obj){ return obj.name; }, partialChars: 1, choices: 10 });
</script>
</body>

In the above method the arguments are as follows :

new AutoCompleter.DWR(textFieldName, associatedDivName, methodForPopulatingList, optionalParams)

OptionalParams:
ValueSelector : the property of the bean that has to be shown in the autocomplete list. For example, 'name' property from 'Employee' bean.

PartialChars : Minimum number of characters to be entered in order to begin matching. Default value is 2.

Choices : Maximum number of items to be shown in the drop down.

Run your application and see DWR in action !!!