Wednesday, 16 June 2010

Ajax with Direct Web Remoting (DWR)

This is my blog entry after a long time.

Recently i have used ajax with dwr (Direct Web Remoting) and it was very useful. I would like to discuss the same this time.

DWR allows the us to call server-side Java objects from javascript with a great ease.

- Using DWR you can call server-side Java objects from javascript directly, so you can eliminate entire request-response handling code.

- DWR is deployed as a servlet within your Web application. But there is no need for you to write the servlet code to call the back end object.

- We can introduce the classes we require to call objects from. For each exposed class, DWR dynamically generates JavaScript to include in your Web page. The generated JavaScript contains stub functions that represent the corresponding methods on the Java class and also performs XMLHttpRequests behind the scenes. These requests are sent to the DWR servlet, which, in its second role, translates the request into a method call on a server-side Java object and sends the method's return value back to the client side in its servlet response, encoded into JavaScript.

- There are some utility functions provided to perform common UI tasks.


How to use it?

Ensure you have dwr.jar in your classpath.

Main components include:

- jsp event handler to call javascript.

- javascript function to call the server-side class.

- Server-side class to make the actual database call.

- dwr.xml file to expose the server-side class to the client.


Now let us look at an example.

In our jsp file, if you select a stream type, all the streams with that stream type should be populated dynamically.


<select id="streamType" name="streamType" onchange="onStreamTypeChange();">
<!-- options holding the list of stream types--!>
</select>

<select id="streamDesc" name="streamDesc">
<option value="">&nbsp;</option>
</select>


This calls the below javascript function to populate the relevant streams, whenever the value of this select list is changed (stream type is changed).


function onStreamTypeChange()

{

l = document.findJobs.streamType;

sST = l.options[l.selectedIndex].value;

StreamAdapter.getStreamsForStreamType(sST, populateStreams);

/*
StreamAdapter - JavaScriptName - specified in dwr.xml(explained below)
getStreamsForStreamType - methodName
sST - methodParams ...
populateStreams - callBack function
*/


}


This function passes the selected streamType into a method called getStreamsForStreamType of the object StreamAdapter.

After the remote method is called, the results from that method are passed to the popStreams javascript callback function(populateStreams).

- NOTE : callback function should be the last parameter. You can have multiple method params before that.


function populateStreams(data)

{

DWRUtil.removeAllOptions("streamDesc"); // Utility functions provided by DWR

DWRUtil.addOptions("streamDesc", data); // Utility functions provided by DWR

/*
if you want to access the elements inside the list,
then incoming list can be accessed as an array and
elements can be accessed as below...

streamDesc_1 = data[0];
streamDesc_2 = data[1];

*/


var l = document.findJobs.streamDesc;



for(i=0; i < l.options.length; i++)

{

if(l.options[i].value == "<c:out value="${sessionScope.findJobs.streamDesc}" />")

{

l.selectedIndex = i;

}

}

}


This method contains the logic to adjust the DOM to reflect the data coming back from the server-side. You will see there are a couple of DWR util functions in there to remove the current options from the select list and then add new options, which have come back from the server. The function then selects a value from the new select list based on a session attribute.

StreamAdapter is a server-side class that actually makes a database call. This class takes in the parameters sent from the JS function, calls down to a DAO class to get some results and returns a List back to the client side as below.


public class StreamAdapter
{

public List<String> getStreamsForStreamType(String streamType) throws Exception
{

CommonJobDAO dao = new CommonJobDAO();

List<String> result = dao.getStreamsForStreamType(streamType);

return result;
}

public List<StreamBean> "getStreamDetails(int stream_id){
....
}
}


In order to expose the StreamAdapter class to the client, there is a config file called dwr.xml. This file tells DWR to create a new instance of the StreamAdapter class whenever it is called and gives the location of the class as below.


<!DOCTYPE dwr PUBLIC
"-//GetAhead Limited//DTD Direct Web Remoting 2.0//EN"
"http://getahead.org/dwr/dwr20.dtd">


<dwr>
<allow>
<create creator="new" javascript="StreamAdapter">
<param name="class" value="com.myproject.adapters.StreamAdapter"/>
<include method= "getStreamsForStreamType"/> <!OPTIONAL>
<include method= "getStreamDetails"/> <!OPTIONAL>
</create>
</allow>
<allow>
<create creator="new" javascript="AnotherAdapter">
<param name="class" value="com.myproject.adapter.FieldAdapter"/>
</create>
</allow>
</dwr>



The above is the simpler version of dwr.xml file.

if you are retrieving List or Map then you can use convert element which specifies the members to include in the JavaScript serialization of StreamBean.

You can declare the dwr servlet as below in web.xml file.


<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>false</param-value>
</init-param>
</servlet>

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


Pros and cons of DWR:

- Very easy to use.
- very quick.
- DWR does a great job of hiding the Ajax machinery, but it's important to remember that the network is not transparent .

Hope it will be useful.


References :
http://www.ibm.com/developerworks/java/library/j-ajax3/

3 comments:

Ananth Chellathurai said...

I love using dwr. Thank you for your article. It is simple and quick

JasonBirk佳琪 said...

Thank you very much for such useful informaion ● 3●..................................................................

Kells said...

Thanks for sharing.Did you know that with Reverse Ajax Direct web remoting allows Java code running on a server to use client side APIs to publish updates to arbitrary groups of browsers?