« Back to AJAX

Using DWR for AJAX

Tags: development

Table of Contents [-]

    DWR is an easy to use and powerful open source AJAX library. Here's how to use it in Liferay:

    - Download DWR jar from http://getahead.ltd.uk/dwr, copy jar to the global classpath (if using the extension environment copy them to ext\ext-lib\portal)

    - To install the DWR servlet, in the web.xml file add the following (if using the extension environment add following in ext\ext-web\docroot\WEB-INF\web.xml):

       <servlet>
          <servlet-name>DwrServlet</servlet-name>
          <servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class>
          <load-on-startup>12</load-on-startup>
       </servlet>
       <servlet-mapping>
          <servlet-name>DwrServlet</servlet-name>
          <url-pattern>/dwr/*</url-pattern>
       </servlet-mapping>

    - If you are using DWR 2.x then the servlet-class line should properly contain the following: org.directwebremoting.servlet.DwrServlet.

    During development, you will want to enable the debug page, which allows you to test the classes that have been remoted using the URL host/dwr:

       <servlet>
          <servlet-name>DwrServlet</servlet-name>
          <servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class>
          <load-on-startup>12</load-on-startup>
          <init-param>
             <param-name>debug</param-name>
             <param-value>true</param-value>
          </init-param>
       </servlet>

    - Add the dwr.xml (see DWR site for details) file inside the WEB-INF directory of Liferay's WAR (if using the extension environment add it to ext\ext-web\docroot\WEB-INF). For example:

       <dwr>
        <allow>
        <create creator="new" javascript="EchoService">
        <param name="class" value="com.example.EchoDwr"/>
        </create>
        </allow>
       </dwr>

    - Sample backend class, which creates an HTML fragment that decorates the passed in message:

       public class EchoDwr {
         public static String echo(String message) throws Exception {
          
          WebContext webContext = WebContextFactory.get();
          HttpSession session = webContext.getSession();
       
          String userId = PortalUtil.getUserId(session);
          if (userId == null) {
             throw new Exception("Must be logged in to run this.");
          }
          
          HttpServletRequest request = webContext.getHttpServletRequest();
          request.setAttribute("message", message);
          
          String html = webContext.forwardToString("/html/portlet/example/echo.jsp");
       
          return html; 
       }

    - the /html/portlet/example/echo.jsp referred to above can be any JSP that generates an HTML fragment. For example:

       <%
          String message = (String)request.getAttribute("message");
       %>
       <b><%= message %></b>

    - To invoke this from JSP:

       <%-- DWR AJAX setup --%>
       <script type='text/javascript' src='/dwr/interface/EchoService.js'></script>
       <script type='text/javascript' src='/dwr/engine.js'></script>
       <script type='text/javascript' src='/dwr/util.js'></script>
       
       <script type="text/javascript">
          <%-- invoke EchoDwr.echo() via AJAX --%>
          EchoService.echo("<%= someValue %>",
          { callback:function(dataFromServer) {
             <portlet:namespace />processResults("dataDivId", dataFromServer);
          }, errorHandler:function(errorString, exception) {
             <portlet:namespace />showError("errorDivId", errorString); }
          } );
          
          <%-- process AJAX response --%>
          function <portlet:namespace />processResults(divId, data)
          {
             if (data != null) {
           DWRUtil.setValue(divId, data);
             }
          }
       
          <%-- handle AJAX error, error callback is optional --%>
          function <portlet:namespace />showError(errorDiv, message) {
             DWRUtil.setValue(errorDiv, "Error: "+message+"");
          }
       </script>

    - At runtime, the caller JSP invokes the remote object asynchronously using the DWR generated javascript method "EchoService.echo()". This request is passed to the DWR servlet which maps this to the method EchoDwr.echo(). This method passes the parameters to a JSP which renders HTML output and returns it as a String. This is returned to the calling page. Upon receipt, the page calls processResults() to change the content of the given DIV to the returned HTML String.

    - In the remote object (e.g. EchoDwr), the HTTP request object does not contain the Liferay injected attributes such as Theme. If such information is required, it must be added to the method signature and passed in from the calling JSP (e.g. pass in the Theme ID, since Strings are easily serialized, where as the ThemeDisplay object is not)

    - The remote object can return various types of objects, or even an Array of objects. DWR will automatically serialize types like String & Integer. You can create a Converter object to serialize custom objects.

    - Each AJAX request uses an HTTP connection. To reduce the load on the server, multiple requests can be batched into one request. After all of the remote calls in the batch complete, a single response is sent and DWR passes the data to the callbacks.

       <%-- javascript --%>
       DWREngine.beginBatch();
       service.doSomething1();
       service.doSomething2();
       ...
       DWREngine.endBatch();
    0 Attachments
    17460 Views
    Average (2 Votes)
    Comments

    Showing 5 Comments

    Eugene Ramirez
    8/19/09 8:13 PM

    Hi, I tested this and the Spring, DWR Liferay sample for liferay 5.2.3, both throws NumberFormatException when initializing the DWR. Both work in 5.2.2. Anybody have the same issue? Thanks

    krunal b soni
    7/7/10 2:26 AM

    Hi, I have tested with liferay 5.0.2. And it is working fine.

    Thanks

    Francisco Aranda
    9/9/10 12:26 PM

    To access ThemeDisplay in DWR, put this in your portlet controller at doView() or HandleRenderRequest() if you are using Spring

    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(WebKeys.THEME_DISPLAY);
    request.getPortletSess­ion().setAttribute("themeDisplay", themeDisplay, PortletSession.APPLICATION_SCOPE);

    Then you can access themeDisplay in your DWR class

    WebContext webContext = WebContextFactory.get();
    HttpSession session = webContext.getSession();
    ThemeDisplay themeDisplay = (ThemeDisplay) session.getAttribute("themeDisplay");

    And there you are, you can access user information, PermissionChecker, etc...

    Vishal Bhanderi
    12/1/10 10:43 AM

    Works great on 6.0.5. If you need html to be shown make sure you disable DWR html escaping

    EchoService.echo(function(data) {
    dwr.util.setValue("dataDivId", data, { escapeHtml:false });
    });

    Mani kandan
    1/28/11 3:03 AM

    Hi Bhanderi,
    Can you pls tell me how DWR makes work in 6.0.5. I tried in 5.2.3 its working but its not working in 6.0.5...
    Its throwing exception current URL call...