This is probably the biggest release we've ever done in terms of new features.
The biggest new feature is what we call Reverse Ajax. DWR 1.x allowed you to asynchronously call Java code from Javascript. DWR 2.0 builds on this to allow you to asynchronously call Javascript code from Java. Reverse Ajax makes writing interactive applications much easier. It can use polling or Comet (long-lived HTTP) queries.
Our 'chat' example contains Java code like this:
WebContext wctx = WebContextFactory.get(); String currentPage = wctx.getCurrentPage(); // 'messages' is a List of recent chat messages to display // Java objects converted to Javascript have a declaration and a declared variable name. OutboundVariable ov = wctx.toJavascript(messages); // Loop over all the users on the current page for (ScriptSession otherSession : wctx.getScriptSessionsByPage(currentPage)) { otherSession.addScript(ov.getInitCode() ); otherSession.addScript("receiveMessages(" + ov.getAssignCode() + ");" ); // receiveMessages is a Javascript function that displays the current list of messages }
In essence we are looping over all the users on the current page and sending them some Javascript to update their display. The Javascript is even simpler. You just turn polling on:
DWREngine.setPolling(true);
Chat example (included in the war download) includes the Javascript source to receiveMessages() which is a 4-liner that uses DWRUtil to put the messages on the screen.
Other uses for this technology include progress bars, online games, stock tickers and any system where server state changes and we need to push updates to a browser or browsers.
Should you need to access servers in a different domain we've enabled a new remoting scheme. From DWR 2.0 you can use manipulation of <script> tags in addition to XMLHttpRequest or iframes. To use is you just need to do the following:
DWREngine.setMethod(DWREngine.ScriptTag);
DWR 1.x sometimes needs a <signatures> element to help it get the type conversion right. If you are using DWR 2.0 with JDK5 generic types then you probably don't need <signatures> any more. DWR will automagically get the right type conversion.
We've updated DWRUtils. There is a new DWRUtil.cloneNode(elementId) method that enables you to use HTML fragments as templates that are repeated. For example:
// Loop over all the beans for (var i = 0; i < beanArray.length; i++) { // Fill in the blanks in the template. You will have several lines like this. DWRUtil.setValue("someid", beanArray[i].property); // Clone the node so we don't overwrite it next time DWRUtil.cloneNode("template"); } // Finally hide the template $("template").style.display = "none";
We're also trying an experimental update to getValues to make it work more like a form. A Checkbox will return its value if checked and false if not. This might break backwards compatibility, it is slight non-obvious depending on your perspective so we need feedback on this one.
There is a new scope. Servlet/JSP developers are familiar with setting attributes at a request, page, session or application level. DWR 2.0 allows you to use "script" scope. With script scope you can persist variables for long-lived pages like single-page Ajax applications. Script scope is a bit like session scope in its longevity, however it does not require cookies. Script scope attributes are available to any Ajax operations within a single page. It is available to creators dwr.xml:
<create creator="new" javascript="Test" scope="script"> <param name="class" value="com.example.Test"/> </create>
Script scope is also available programatically:
WebContextFactory.get().getScriptSession().setAttribute("key", value);
Starting with DWR 2.0m1 the downloadable war file is quite a bit bigger than before because we are including some examples. We are working on simple Struts and Spring integration demos.
Refactoring is often a feature in the eyes of developers because the code feels cleaner, but it can just cause backwards compatibility issues for users. We've done some refactoring for DWR 2.0, but here is what users get out of it: We now use the org.directwebremoting.* package rather than the more obscure uk.ltd.getahead.dwr.*, but we've left stubs behind for backwards compatibility. Please shout if we've missed anything out. We've also tried to make DWR more embeddable, and it should now be possible to create alternative wire protocols like SOAP or JSON-RPC if desired.
You can now pass request attributes from DWR using call meta-data like this:
Remote.getData(42, { callback:function(str) { alert(str); }, customKey:"Fred", });
The extra meta-data will then be available to Java in the HttpServletRequest. The following code will return the string "Fred":
WebContextFactory.get().getHttpServletRequest().getAttribute("customKey");
I very much doubt that anyone will notice, but we've removed deprecated.js. It's been deprecated since around DWR version 0.9.
We take security very seriously. DWR 1.x has proved to be very secure so far, but that does not mean we rest on our laurels. DWR 2.0 introduces a lot of new code. Reverse ajax and script based session management are places where we could easily slip up.
In addition in milestone 1, Reverse Ajax will create a much heavier load on your webserver than older stable releases. We've got 2 answers - the design allows server load-monitoring and dynamic back-off. More excitingly we're working with Mortbay to allow DWR to use Jetty6 continuations if available to allow long lived HTTP requests without risking resource starvation.
So please do not use DWR 2.0 in a production system until we've had more testing and inspections.
This is just the first in an exciting set of milestones that we will be pushing out over the next few weeks. We've got more stuff coming!
You can download DWR 2.0 M1 from the usual download page.