Escolar Documentos
Profissional Documentos
Cultura Documentos
DWR is a RPC library which makes it easy to call Java functions from JavaScript and to call JavaScript functions from Java (a.k.a Reverse Ajax). It has a large user-base, active mailing list and has been used in many projects. DWR has a number of features like call batching, marshalling of virtually any data-structure between Java and Javascript (including binary file uploading and downloading), exception handling, advanced CSRF protection and deep integration with several Java server-side technologies like Spring and Guice. The first diagram shows how DWR can alter the contents of a selection list as a result of some Javascript event.
Reverse Ajax (available since DWR version 2.0) allows Java code running on the server to find out what clients are viewing certain pages, and to send to them JavaScript, generated either manually or using a Java API. These JavaScript generating APIs generally match a client-side APIs.
A Java Servlet running on the server that processes requests and sends responses back to the browser. JavaScript running in the browser that sends requests and can dynamically update the webpage.
DWR works by dynamically generating Javascript based on Java classes. The code does some Ajax magic to make it feel like the execution is happening on the browser, but in reality the server is executing the code and DWR is marshalling the data back and forwards. This method of remoting functions from Java to JavaScript gives DWR users a feel much like conventional RPC mechanisms like RMI or SOAP, with the benefit that it runs over the web without requiring web-browser plug-ins.
Download the dwr.jar file. Place it into the WEB-INF/lib directory of your web application.
2. Install the Commons Logging JAR file
DWR depends on Commons Logging. Download the commons-logging.jar and place it into the WEB-INF/lib directory of your web application.
3. Add the DWR servlet definition and mapping to your application's web.xml
Add the following lines to your web application's deployment descriptor (WEB-INF/web.xml). The <servlet> section needs to go with any existing <servlet> sections, and likewise with the <servlet-mapping> section.
<servlet> <display-name>DWR Servlet</display-name> <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> </servlet> <servlet-mapping> <servlet-name>dwr-invoker</servlet-name> <url-pattern>/dwr/*</url-pattern> </servlet-mapping>
Create a new file in you web application's WEB-INF directory (alongside web.xml) named dwr.xml. A simple way to start is with something like this:
<!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 3.0//EN" "http://getahead.org/dwr/dwr30.dtd"> <dwr> <allow> <create creator="new" <param name="class" </create> <create creator="new" <param name="class" </create> </allow> </dwr>
The DWR config file defines what classes DWR can create and remote for use by Javascript. In the example above we are defining 2 classes that are remoted and giving the classes names in Javascript. The new creator that we used above uses the public no-args constructor that all Java Beans must have. It is also worth remembering that DWR has one restriction:
Avoid reserved JavaScript words; Methods named after reserved words are automatically excluded. Most JavaScript reserved words are also Java reserved words, so you won't be having a method called "try()" anyway. However the most common gotcha is "delete()", which has special meaning in JavaScript but not Java.
Visit the dwr.xml documentation for a detailed description of the dwr.xml file, creators and converters.
5. Take DWR for a test drive!
You should see a page showing you the classes you configured in Step 4. Having followed a link you should see an index of all the methods ready for calling - simply enter the required parameters (if parameters are required) and click the execute button. These pages are valuable debugging tools and dynamically generated by DWR when the debug init-param is set to true.
How to make use of this from your web application
We have a whole section on writing Javascript with DWR, and there are a number of examples in the sidebar that demonstrate how to dynamically alter the text in web pages, update lists, manipulate forms and perform live table editing. Each has a description of how it works. Another way to get started is to look at the source from the pages that you just viewed:
3
Go to http://localhost:8080/[YOUR-WEBAPP-CONTEXT]/dwr/ and click on your class View source and find the line that executes the method that you are interested in. Paste the text into an HTML or JSP page in your web-app. Include links to the DWR JavaScript files that make the magic happen:
You can omit the /[YOUR-WEBAPP-CONTEXT]/ section and use relative paths in your web pages if you wish. Next Step: Learn about writing Javascript that interacts with DWR.
Remoting Options
DWR provides two remoting options: 1) DWR native - By default DWR uses a superset of JSON that we like to call JavaScript. This was initially done to cope with recursive data, XML objects, etc., which the original JSON specifications had a difficult time dealing with. In this remoting mode DWR's client side engine (engine.js) handles preparing and executing the call to the server. Most of the documentation on this site deals with DWR native. 2) JSON/JSONP - In DWR 3 a JSON/JSONP RESTian API has been added that allows users to access Java services exposed to DWR via an URL: http://example.com/dwr/jsonp/ClassName/methodName/param1/param2 DWR will reply with a JSON structure containing the result of calling ClassName.methodName("param1", "param2"); This allows for seamless integration with JavaScript toolkits (DOJO, ExtJs, jQuery, etc.) while eliminating the need for the developer to convert the return types of their exposed Java methods into JSON manually - DWR's server engine handles this.
For an example of the JSON/JSONP functionality you can view this demo which uses JQuery. A similar example using DOJO is also avaiable. Both of these examples are available for download in our dwr.war.
Remote calls with DWR - handling the asynchronous nature of AJAX with callbacks
DWR generates JavaScript proxy functions that are similar to the Java methods exposed using the <create ... > element, in your dwr.xml file. The biggest challenge in creating a remote interface to match Java code across AJAX is the (usually) asynchronous nature of AJAX, compared to the synchronous nature of a normal Java call. DWR solves this problem by introducing a callback function that is called when the data is returned from the server. There are 2 recommended ways to make a call using DWR. Either by appending a call options object or a callback function to the parameter list.
'42' is just the parameter to the getData() Java function - see above. DWR will always pass a JavaScript version (serialized using DWR's converters) of the object returned from the remoted Java method as the first parameter of the callback. In this case str will contain the String that getData returns. This method has some advantages: Depending on your style it may be easier to read, but more importantly it allows you to specify extra call options.
In addition to the callback function you can also specify a timeout, errorHandler, and several other call options. For example:
Remote.getData(42, { callback:function(str) { alert(str); }, timeout:5000, errorHandler:function(message) { alert("Oops: " + message); } });
Any fields missing from the JavaScript representation will be left unset in the Java version.
6
Since the doSomethingWithPerson method returns 'void' we do not need to use a callback and can just leave it out. If you want to be notified of the completion of a server-side method that returns void then you can include a callback method. Obviously DWR will not pass any data to it.
Exemple 1 - Demonstration of how to dynamically update a web-page with text fetched from a web server
When you click on the "Send" button the browser calls the onclick event, which calls the update() function:
function update() { var name = dwr.util.getValue("demoName"); $.post("../../../dwr/jsonp/Demo/sayHello/" + name, {}, function(data) { dwr.util.setValue("demoReply", data.reply); }, "jsonp"); } } dwr.util.getValue()
is a utility to get the value of any element, in this case an input field, but it could be a
div or a select box. The next line is using the jQuery post function to make an asynchronous call to the server utilizing DWR's JSON capabilities. The first parameter is the URL for DWR's JSON service. The URL can be broken down as follows:
../../../dwr/ - The path to the DWR servlet. jsonp - Tells DWR to use JSONP. Demo - The name of the class you have exposed to DWR. sayHello - The name of the method you would like to call on the exposed class
The third parameter is the callback function and will be invoked when the remote call returns. The first parameter of the callback function (in this case "data") will contain the data returned from the remote call. The result of the $.post function is that DWR will call the Demo.sayHello() Java method:
public String sayHello(String name) { return "Hello, " + name; }
When the callback function is reached we call dwr.util.setValue() which is a utility that takes the data you pass in the second parameter and works out how to fit it to go into the HTML element specified by id in the first parameter. This function is one of several neat Javascript utilities that make working with DWR much easier.
HTML source:
<p> Name: <input type="text" id="demoName"/> <input value="Send" type="button" onclick="update()"/> <br/> Reply: <span id="demoReply"></span> </p>
Javascript source:
function update() { var name = dwr.util.getValue("demoName"); $.post("../../../dwr/jsonp/Demo/sayHello/" + name, { }, function(data) { dwr.util.setValue("demoReply", data.reply); }, "jsonp"); } }
Java source:
package org.getahead.dwrdemo.simpletext; public class Demo { public String sayHello(String name) { return "Hello, " + name; } }
web.xml
Note: In order to enable JSON/JSONP you must add the following init-param to your DWR servlet definition in your web.xml (This is a snippet and is not a complete web.xml).
... <servlet> <servlet-name>dwr-invoker</servlet-name> <display-name>DWR Servlet</display-name> <description>Direct Web Remoter Servlet</description> <servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class> <init-param> <param-name>jsonpEnabled</param-name> <param-value>true</param-value> </init-param> ...
dwr.xml
<?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="Demo"> <param name="class" value="org.getahead.dwrdemo.simpletext.Demo"/> </create> </allow> </dwr>
Exemple 2 - how to dynamically update a web-page with the contents of a page retrieved from the server
Normally the code called by DWR is a simple POJO that knows nothing about the web. In this demonstration we want to find out about the web server so we use the WebContext class to get access to the ServletContext. This example is similar to the dynamic text example, the big difference is that we are using this HTML page, and the WebContext class to allow us to get it. There are no iframes used in this example - just DWR and a humble div. The Java code looks like this:
public String getInclude() { WebContext wctx = WebContextFactory.get(); return wctx.forwardToString("/simpletext/forward.html"); }
There is one other difference. In the previous example we were working with plain text. Here we are working with HTML. To help protect you from XSS attacks DWR automatically escapes HTML characters, however sometimes (like in this case) we know that we have HTML, and that it is safe. So the Javascipt code looks like this:
function forward() { Demo.getInclude(function(data) { dwr.util.setValue("forward", data, { escapeHtml:false }); }); }
The third parameter is the options parameter which is present on a number of DWR functions. It allows you to customize how the function acts. In this case we are asking DWR to not escape and HTML in the passed string.
HTML source:
<p> <input value="Include Page" type="button" onclick="forward()"/><br/> Included Page: </p> <div id="forward"></div>
Javascript source:
function forward() { Demo.getInclude(function(data) { dwr.util.setValue("forward", data, { escapeHtml:false }); }); }
Java source:
package org.getahead.dwrdemo.simpletext; import import import import java.io.IOException; javax.servlet.ServletException; org.directwebremoting.WebContext; org.directwebremoting.WebContextFactory;
dwr.xml
<?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="Demo"> <param name="class" value="org.getahead.dwrdemo.simpletext.Demo"/> </create> </allow> </dwr>
10