Friday, March 30, 2007

Reverse Ajax with Direct Web Remoting (DWR)

Direct Web Remoting (DWR), is an open source Java library that can be used to implement Ajax in Java web applications with minimal Javascript coding. Using DWR, we can invoke server-side Java methods from Javascript in the browser. DWR 2.0 introduces a new feature, dubbed "Reverse Ajax", using which server-side Java can "push" updates to the browser. In this post, I tried to use a simplistic web application that will demonstrate the use of DWR for "Reverse Ajax".
In this example, I use a servlet that will be pushing information to the browser clients. Here is how to implement the example.
  1. Download DWR 2.0 from here, dwr.jar file has to be included in the classpath.
  2. Create the Service: This service generates messages which will be written to the browser. Here is the code for the Service.
    package utils;

    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.List;

    import org.directwebremoting.ServerContext;
    import org.directwebremoting.proxy.dwr.Util;

    public class Service {

    private int count = 0;

    public void update(ServerContext wctx) {
    List<Data> messages = new ArrayList<Data>();
    messages.add(new Data("testing" + count++));

    // Collection sessions = wctx.getAllScriptSessions();
    Collection sessions = wctx.getScriptSessionsByPage("/ReverseAjax/index.html");
    Util utilAll = new Util(sessions);
    utilAll.addOptions("updates", messages, "value");
    }
    }
    Service.java
  3. Create the Message Container: The message container is a simple Java bean that holds the message.
    package utils;

    public class Data {
    private String value;

    public Data() {
    }

    public Data(String value) {
    this.value = value;
    }

    public String getValue() {
    return value;
    }

    public void setValue(String value) {
    this.value = value;
    }
    }
    Data.java
  4. Create the Servlet: Here is the code for the Servlet.
    package servlets;

    import java.io.IOException;
    import java.io.PrintWriter;

    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;

    import org.directwebremoting.ServerContext;
    import org.directwebremoting.ServerContextFactory;

    import utils.Service;

    public class TestServlet extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    Service service = new Service();
    ServerContext wctx = ServerContextFactory.get(this.getServletContext());
    for (int i = 0; i < 10; i++) {
    service.update(wctx);
    try {
    Thread.sleep(1000);
    }
    catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    PrintWriter writer = response.getWriter();
    writer.println("Done");
    writer.close();

    }}
    TestServlet.java
    • The ServerContext is used by DWR to get information of the clients that have open sessions on the server.
  5. The Web Page: This is the code for the Web Page (index.html).
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <title>index</title>
    <script type='text/javascript' src='dwr/engine.js'></script>
    <script type='text/javascript' src='dwr/interface/Service.js'></script>
    <script type='text/javascript' src='dwr/util.js'></script>
    </head>
    <body onload="dwr.engine.setActiveReverseAjax(true);">
    <ul id="updates">
    </ul>

    </body>
    </html>
    index.html
    • engine.js handles all server communications.
    • util.js helps you alter web pages with the data you got from the server.
    • The path to the scripts is relative to the root of the web content. The DWR servlet (defined in the web.xml file) will provide these scripts.
    • dwr.engine.setActiveReverseAjax(true); is used to activate Reverse Ajax
    • The id of the list is the same as the parameter set in the Service.
  6. The Web Deployment Descriptor:
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    <display-name>ReverseAjax</display-name>

    <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>
    <init-param>
    <param-name>activeReverseAjaxEnabled</param-name>
    <param-value>true</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet>
    <servlet-name>TestServlet</servlet-name>
    <servlet-class>servlets.TestServlet</servlet-class>
    </servlet>

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

    <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    </welcome-file-list>
    </web-app>
    WEB-INF/web.xml
    • The DWR Servlet has to be loaded on startup
    • Setting activeReverseAjaxEnabled to true sets Reverse Ajax to be active. In this case Reverse Ajax used will be through polling or comet requests (extended http requests). If this is false, then inactive Reverse Ajax (piggybacking) will be used. In this case, the server waits for requests from the client and piggybacks the updates with the response.
  7. The DWR Configuration: The DWR configuration is defined in the dwr.xml file
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 2.0//EN" "http://getahead.org/dwr/dwr20.dtd">
    <dwr>
    <allow>
    <create creator="new" javascript="Service" scope="application">
    <param name="class" value="utils.Service" />
    </create>
    <convert converter="bean" match="utils.Data" />
    </allow>
    </dwr>
    WEB-INF/dwr.xml
    • "create" is used to define a Java object as being available to Javascript code.
    • The "javascript" attribute is the one that will be used in case of invoking the server-side methods from Javascript.
    • The converter definition allows utils.Data to be used as a parameter.

  8. Environment: This example was tested using DWR 2.0 RC 3, on Tomcat 5.5

12 comments:

  1. How to get Multiple axis chat ?

    ReplyDelete
  2. This comment has been removed by the author.

    ReplyDelete
  3. Hi

    I am using dwr with struts framework and new to it.

    I have a problem in accessing the latest data from form bean which is in session scope.
    When ever i access the included methods of form bean in jsp i am getting initialized values instead of latest values.

    Is there any thing extra i have to add in dwr.xml ?

    ReplyDelete
  4. I did something similar with JPublish and DWR. Readers who want a simpler example of reverse AJAX can download and run the following demo: simpledwr.war.zip

    Have fun!

    ReplyDelete
  5. Can we have unit Testing frame work available for DWR. like JUNIT ?

    ReplyDelete
  6. is this example complete? I could not get it to work at all. how do you post to the servlet? the index.html is just the initialization, but you have not included the chat part.

    best regards,
    -C.B.

    ReplyDelete
  7. Hi Everybody... Don't work!

    ReplyDelete
  8. Abhi,
    Nice tutorial, although as given it is incomplete. I've posted a complete working version (with slight modifications) at:
    http://amazingstacktrace.blogspot.com/

    Thanks for the original post,

    Eduardo

    ReplyDelete
  9. Thanks for this wonderful post. I have a query..now what's happening we are executing the testServlet and it is posting to the page.

    But I want to execute server code itself on session inactivity what should i do for that?

    ReplyDelete
  10. You may also want to take a look at using StreamHub for Reverse Ajax. It integrates well with either Java or .NET and is cross-browser compatible.

    ReplyDelete
  11. Hi i m newer to DWR i tried lot DWR with Database for reverse AJAX but still i cant implement,
    so is there any example any one have to implement Reverse Ajax using DWR for Database value can get on browser with push technology.

    ReplyDelete

Popular Posts