
Using DWR for AJAX
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();