« 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
    28476 Views
    Average (2 Votes)
    The average rating is 5.0 stars out of 5.
    Comments
    Threaded Replies Author Date
    Hi, I tested this and the Spring, DWR Liferay... Eugene Ramirez August 19, 2009 8:13 PM
    Hi, I have tested with liferay 5.0.2. And it is... krunal b soni July 7, 2010 2:26 AM
    To access ThemeDisplay in DWR, put this in your... Francisco Aranda September 9, 2010 12:26 PM
    Hello 3 years later. Unfortunatelly it does not... Michal Sima June 20, 2013 9:36 AM
    Works great on 6.0.5. If you need html to be... Vishal Bhanderi December 1, 2010 10:43 AM
    Hi Bhanderi, Can you pls tell me how DWR makes... Mani kandan January 28, 2011 3:03 AM

    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
    Posted on 8/19/09 8:13 PM.
    Hi, I have tested with liferay 5.0.2. And it is working fine.

    Thanks
    Posted on 7/7/10 2:26 AM.
    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...
    Posted on 9/9/10 12:26 PM.
    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 });
    });
    Posted on 12/1/10 10:43 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...
    Posted on 1/28/11 3:03 AM in reply to Vishal Bhanderi.
    Hello 3 years later. Unfortunatelly it does not work. I did exactly how you explained, but the following code does not work:

    WebContext webContext = WebContextFactory.get();
    HttpSession sesion = webContext.getSession();
    ThemeDisplay themeDisplay = (ThemeDisplay) sesion.getAttribute("themeDisplay");
    themeDisplay.getUser().getExpandoBridge()­.setAttribute("foo", "bar");

    I have the following exception:
    com.liferay.portal.security.auth.PrincipalException: PermissionChecker not initialized
    Posted on 6/20/13 9:36 AM in reply to Francisco Aranda.