Posts filed under ‘gwt’
GWT Serialization 2
GWT can serialize this class.
public MyClass implements IsSerializable {
public String myStr;
}
But if you change MyClass into the one below, GWT cannot serialize it and you’ll get the unhelpful error message: “Error: Type ‘foo.bar.MyClass’ was not serializable and has no concrete serializable subtypes”.
public MyClass implements IsSerializable {
public String myStr;
public MyClass(String str){myStr = str;}
}
Want to know why? Because MyClass now lacks a no argument constructor.
I learned this from a thread on issue 540 at the Google Code website. The first post, which came during the GWT 1.3 time frame, rightly asks for a better error message when GWT cannot serialize something. Further down the thread, post say this problem is fixed. It seems to have been fixed before GWT 1.4. Nevertheless, the problem of the unhelpful serialization error message persists, at least when using IntelliJ IDEA 7.0.1 with the GWT Studio plugin.
The work around mentioned in the thread’s 2nd post still holds: any classe you want GWT to serialize must have a no arg constructor. GWT can serialize the class below.
public MyClass implements IsSerializable {
public String myStr;
public MyClass(){}
public MyClass(String str){ myStr = str; }
}
GWT Custom Class Location
I created some of my own data transfer classes. I wanted to load them on the server and send them to the client. I tried putting them in the MyApp/server directory, which didn’t work. Turns out GWT couldn’t find them unless they were in the MyApp/client/remote directory. Who’d have thunk it?
GWT Serialization 1
GWT RPC requires a extra type info when a remote method returns a Java collection of your own classes. To help GWT you specificy the data type the colletion holds with a @argType annotation. Below are two examples.
In the first case I return a Map. I had to tell GWT it would hold: key=String and value=ArrayList<String>. (Looks a lot like Java 1.5 generics doesn’t it?). In the second case, I returned an ArrayList<Category>. Category is my own class, and it wouldn’t serialize right off the bat.
/** * NOTE: When there's no param name with the annotation, GWT assumes it's the return type. * @gwt.typeArgs < java.lang.String,java.util.ArrayList<samApp.client.remote.mypkg.Foo> > */ public Map getMapOfFooLists(); /** * @gwt.typeArgs <samApp.client.remote.mypkg.Foo > */ public ArrayList getFooList();
GWT didn’t like my Foo class. Here’s the original version:
public class Foo implements Serializable
{
public String name;
public ArrayList strList = new ArrayList();
}
Now, here’s the version GWT liked.
public class Foo implements IsSerializable
{
public String name;
/** @gwt.typeArgs <java.lang.String> */
public ArrayList strList = new ArrayList();
}
Change #1: I changed implements Serializable to IsSerializable, which is GWT’s limited version of Serializable. The docs claim GWT 1.4.x works in a limited way with Serializable, but my understanding is that you must list your Serializable classes in a serialization policy file. The docs say it’s generated, but not how or where it gets put.)
Change #2: Provide a @gwt.typeArgs annotation for the Java collection in my Foo class. This idea came from a Google groups post.
I was surprised I had to do this for my class’s member variables. In case it surprises you too, I hope this post helps.
GWT Questions/Issues
Question: Why does GWT say I can use ArrayList and then warn me about using it when I do?
- They say they support it.
- Error when using it: Caused by: com.google.gwt.user.client.rpc.SerializationException: Type ‘java.util.ArrayList’ was not included in the set of types which can be serialized by this SerializationPolicy. For security purposes, this type will not be serialized.
- GWT docs talk about a serialization policy file, whose extention is .gwt.rpc. They say it’s created by RPC and that without it serialization reverts to a JDK 1.3 level. However, the docs don’t say where this file is located.
Answer:
- First, it turns out it was my problem not GWT.
- Second, I was returning a Map of type <java.lang.String,javal.util.ArrayList>, but I mistakenly wrote Map<java.lang.String,java.lang.String> in my typeArgs annotation.
- Third, even after I fixed it to say ArrayList, I still got a warning asking me to specify what object type the ArrayList would hold. So the final annotation is Map<java.lang.String,java.util.ArrayList<java.lang.String>>.
Recent Comments