New features in DWR 0.8
DWR version 0.8 contains a big list of new features. You can download version 0.8 from java.net. The change log looks like this:
-
Batch sending of remote calls:
DWR will now send a group of remote calls together in a single batch to reduce network latency. SeeDWREngine.beginBatch()andDWREngine.endBatch()for more information. -
Provision of call ordering promises:
DWR can return results in the order in which they were sent usingDWREngine.setOrdered(). Warning: Setting this to true will slow down your application, and it expose you to timeouts if a message gets lost. In addition and it may well mean that you are being lazy and not thinking about the asynchronous model properly. -
Fine grained access control:
You can now specify exactly which methods are allowed and disallowed using the include and exclude elements in dwr.xml:<create creator="new" javascript="JDate" class="java.util.Date"> <include method="getSeconds"/> <include method="getMinutes"/> </create>
The alternative is to<exclude .../>. You can do one or the other but not both. -
J2EE role based authorization:
You can now specify that certain methods are only available to users with certain roles:<create creator="new" javascript="JDate" class="java.util.Date"> <auth method="toString" role="devel"/> </create>
This requires you to have added J2EE security turned on in your web.xml. -
Methods on java.lang.Object (like
wait()) are now disallowed. -
Enhanced debug pages:
The debug pages athttp://localhost:8080/[YOUR-WEB-APP]/dwrhave been enhanced to allow you to enter parameters other than strings, to show more detail on returned objects and to give more feedback on why methods are unavailable.
-
Auto-fill of Servlet Spec parameters:
If you have a DWR remoted method that has an HttpServletRequest parameter then DWR will automatically fill it in for you. This gives you a way of accessing HttpServletRequest like ExecutionContext except that you don't get the dependency on DWR. It also works for HttpServletResponse etc. -
Logging is now fine grained, and there is more of it:
If you were turning DWR debug on globally, you probably don't want to any more! -
You can specify detailed type information for collections:
List, Set etc don't have type info (and even under 1.5 it seems you can't get at it) so you can specify the types in dwr.xml:<create creator="new" javascript="Test" class="uk.ltd.getahead.testdwr.Test"> <parameter method="testBeanSetParam" number="0" type="uk.ltd.getahead.testdwr.TestBean"/> </create>
This solution is not perfect, and there is an update planned post 1.0
We are working on a smaller list for the next version so we are not that far from 1.0.
Update: Make that 0.8.1; there was an annoying Javascript error as a result of me fixing some issues brought up by a Javascript lint program. That'll teach me to use lint.
java.lang.String is NOT immutable
I found some code on a Java mailing list that challenges a lot of the assumptions about how strings work in Java.
There is a standard newbie question about immutable strings. It goes like this:
What gets printed out:
String lc = "lowercase"; lc.toUpperCase(); System.out.println(lc);
The standard answer is that you get "lowercase" because in Java, strings are immutable. The standard answer goes on to explain the benefits to security of having immutable strings, and how values can't be changed after they've been checked. I'm sure you've seen it all before.
So what about the following code:
String lc = "lowercase"; Mutant.toUpperCase(lc); System.out.println(lc);
You'd think that because Mutant wasn't even part of the String class that it couldn't alter lc, but Mutant.toUpperCase(lc); uses a simple reflection trick to edit the string:
public static void toUpperCase(String orig)
{
try
{
Field stringValue = String.class.getDeclaredField("value");
stringValue.setAccessible(true);
stringValue.set(orig, orig.toUpperCase().toCharArray());
}
catch (Exception ex)
{
}
}
The original article goes into a lot more depth, and a follow-up shows how to change the values of Integers too!.
The solution to the problem is to run your code with a Security manager turned on. That way you can be sure that people are not messing about with private variables.
Mutable Strings + Hungarian Notation + Security = ???
How to make Java Strings mutable, without breaking the Java security model, and in doing so how to look at the Hungarian / Apps Hungarian / Plain debate through the eyes of Niklaus Wirth...
Spolsky and Wirth
I'm sure that everyone knows about Joel Spolsky's recent argument for Apps Hungarian and how .NET has it wrong in demanding Plain Notation (i.e. no variable prefixes).
It occurred to me that Niklaus Wirth would probably be spinning in his retirement chair wondering if he should come out of retirement for one last blog entry: "Why all you programmers of C type languages have it all wrong".
Extra Strong Types
Niklaus Wirth invented Pascal, Modula(2) and Oberon (and other languages) and while I've never used them in anger, from the work I have done in Modula-2 it seems that Wirth really believed in having types based on real world concepts rather than functional ability.
By this I mean that if you have a variable that holds money then I think Wirth would argue that you should create a Money type to hold it, and if you also have some variables that store percentages then you need a Percent type also. Most Java programmers (including me) would probably just use a float or an int, most of the time.
Joel argued that Apps Hungarian allows you to see the difference between a web-safe string and a non-web-safe string. Wirth would argue that if you created the type WebUnsafeString then the compiler would do all the work for you. There would be no need for the code to "look right" because it would not compile if it was wrong.
And in this I am dead with Wirth and not with Spolsky. It is better to make the code "right by proof" than "right by inspection". Code that is "right by inspection" can only be right while the inspectors are perfect and the code is unchanged.
So maybe it would be good if we could have some types that represented web safe strings and have the compiler check that only these types were output to the web. Just how to do this might be the subject of another blog entry. But I'm going to gloss over it in a hand-waving "this is not the issue to debate" kind of way for now.
I did something similar in a recent project where we wanted to make sure that all user visible strings were internationalized, so we created a special type and wherever we could we used that type in our interfaces to force lazy programmers to do it the Right Way.
Finality and Immutability
BUT this is where we run into the problem of immutable strings. In Java, String is immutable, and that means it must be final, and that means that your WebSafeString can't inherit from String so it must contain String, which is a bit of a pain.
And this got me thinking; what if String was not final - Well that would blow the security model because you could pass a CrackedString to some security sensitive procedure which assumed strings were immutable and the CrackedString would change.
But what if we also made all of the methods of string final and kept all the members private? Then string would always function in the same way. Things that inherited from String would still not be able to alter strings after they were checked, and the actions of any String function would go unchanged, so String would still be immutable. But you would be allowed to create sub-classes of string (like WebSafeString or InternationalizedString) that helped with type safety.
I'm sure I must have missed something? Can we really make Strings non-final without losing immutability?
And remind me to blog about how Strings are not actually immutable anyway.
(Updated to tidy a heading)
DWR 0.6 Released. AJAX and XMLHttpRequest made easy
Loads of new features in this release including support for automatic marshalling of DOM trees, better Spring support, better browser support and optional commons-logging support. The full changelist includes:
- New ScriptedCreator so you can use Groovy (or any other language supported by BSF), etc to configure new interface objects.
- Wider support for browsers. DWR now works with Firefox, Safari, IE, Konqueror, Opera, and Mozilla.
- The SpringCreator will now read from bean files configured in web.xml
- Logging via commons-logging if it is avaiable, or the old Servlet.log method if not.
- New converters for DOM, JDOM, XOM and DOM4J so you can pass DOM trees between the client and server without thinking
- Fix to support Jetty
- URL tweak to provide more info to web log analysers
- New ContextCreator to allow remoted objects to be stored in the servlet application context
- 2 New utilities in DWRUtil: Range selection, and return event handling
- There is also better documentation, error messages that are easier to decipher, performance and other bug fixes
You can download the jar file and sources from java.net. Or see the main project page.
Ajax Validation with DWR
I've added a demo to the DWR site on how to do server-side validation that appears to be run on the client.
The demo form demonstrates 2 things; Firstly how to perform in-form validation using server-side checks. The checks here could mostly be done using JavaScript, however many validation tasks can only be done by using server side resources.
It also demonstrates how little boiler-plate DWR requires. The Java code from the examples below is taken from Jakarta commons-validator, without any changes. We simply told DWR to export pre-existing Java functions that were never designed for the web, and yet it all works just fine.
Check it out here: http://www.getahead.ltd.uk/dwr/demo-validate.html.
DWR explained in one GIF
I thought it ought to be possible to explain DWR in a single graphic, so I had a go. I think the result gives a simple overview of what is going on, without getting bogged down in how marshalling is done. What do you think?
On the subject of DWR, I've now had 3 requests for logging to use commons-logging so I've cut a 0.6.beta which makes commons-logging optional. If it's there DWR will use it, if not you get Servlet.log as before.
0.6.beta also makes some of the error messages better.
Download the new beta here.