The signatures section is used to enable resolution of the types stored in Collections. For example in the following example DWR has no way to know that it should cast the incoming data to be a list of numbers.
public class Check { public void setLotteryResults(List nos) { ... } }
The signatures section allows us to hint to DWR what types should be used. The format will be obvious to anyone that has an understanding of generic types under JDK5:
<signatures> <![CDATA[ import java.util.List; import com.example.Check; Check.setLotteryResults(List<Integer> nos); ]]> </signatures>
DWR contains a parser written just for the job so this will work under JDK 1.3 even though the syntax is derived from a JDK 5 feature.
The parser rules are as close to the rules you would expect as possible (with two exceptions) so all the java.lang
types are imported by default.
The first is down to a bug in the parser in DWR 1.0, which fails to take account of return types under some circumstances. So you may need to leave them out.
The second exception is that the parser is a "sunny day" parser; That is to say it is quite forgiving, unlike a complier which will insist on you getting it just right. So sometimes it will let you miss out imports too:
<signatures> <![CDATA[ import java.util.List; Check.setLotteryResults(List<Integer>); ]]> </signatures>
A future version of DWR might use a more formally defined parser which could be based on the official Java definition, so it might be best to avoid making too much use of this laxness.
The signatures element does not currently support nested generic defintions. So for example the following will not work:
<signatures> <![CDATA[ import java.util.List; import java.util.Map ; Check.setConditions(Map<String, Map<String, String>>); ]]> </signatures>
While the parser is updated to support nested generic definitions, you can use the following trick: In the absence of other type information, DWR assumes that a parameter will be a String. So the above example can be written:
<signatures> <![CDATA[ import java.util.List; import java.util.Map ; Check.setConditions(Map<String, Map>); ]]> </signatures>
The signatures section is only needed to resolve the type parameters in a generic parameter. DWR works out everything else for itself using reflection or run-time types, and assumes String as a parameter otherwise. So:
No entry required in signatures section - no generic type parameters:
public void method(String p); public void method(String[] p);
Entry required - DWR can't work it out from reflection:
public void method(List<Date> p); public void method(Map<String, WibbleBean> p);
No entry required - DWR guesses correctly:
public void method(List<String> p); public void method(Map<String, String> p);
No entry required - DWR works it out from runtime types:
public List<Date> method(String p);
It is worth noting that the keys of Objects in Javascript are all Strings - you can use other objects as keys, however they are converted into Strings before use. DWR 1.x uses this Javascript 'feature' to convert keys into Strings. It is likely that DWR 2.0 will do the conversion using on the server (having issued a warning) using the toString() method.
Sometimes DWR will be remoting classes that are wrapped in dynamic proxies. This causes a problem because DWR will be looking up the wrong type, and not find a match.
DWR allows you to specify the Javascript version of the class name in place of the full Java name. This allows you to specify a Creator that we should attach the signature to rather than a class.