Monday, September 15, 2014

Re: GWT 2.2.0 does not serialize/deserialize basic Java types if not referenced explicitly



On Monday, September 15, 2014 6:57:24 AM UTC+2, Justin Zhang wrote:
Hi GWT experts,
  I had a problem with the GWT-RPC on 2.2.0 and above.

  I have a generic service interface which serves as multiple RPC
requests depending on the value of event parameter:

    @RemoteServiceRelativePath("Service")
    public interface Service extends RemoteService {
        EventResult execute(String event, Map<String, Object> eventData)
                throws ServiceException;
    }

The details of request are passed as Map with String key and the value (the eventData)
can be String, Integer, Double and Date (java.util.Date precisely).
This works well on GWT 1.6.4. But when I try to upgrade to 2.2.0 (for
better dev mode tool),


You couldn't have chosen a worse moment to finally move from Hosted Mode to Dev Mode!
Just when Dev Mode is only still supported by Internet Explorer and everyone's switching to Super Dev Mode (which the GWT Team is working on all rage to get you a better dev experience in the upcoming GWT 2.7)

 
it complains that:

    Type 'java.util.Date' was not included in the set of types which can
be deserialized by this SerializationPolicy or its Class object could
not be loadded. For security purposes, this will not be deserialized.

I came across an SO post on a workaround to add the problematic type
explicitly to a dummy method. For instance to get past the java.util.Date
issue, you modify the above interface like:

    @RemoteServiceRelativePath("Service")
    public interface Service extends RemoteService {
        EventResult execute(String event, Map<String, Object> eventData)
                throws ServiceException;

This was a really bad idea. You should use the most specific types as possible in your RPC interfaces and transfer-objects (it's not news, it has always been that way, it's just become stricter over time).
So HashMap (or LinkedHashMap or TreeMap) rather than Map, and NOT Object.
In that specific case, create a value object that can transport any of your supported value types; either use one object with as many properties as the types you support (stringValue, intValue, doubleValue, dateValue) and use the one field that's not null, or create a base class and as many subclasses each wrapping a single value (e.g. new StringValue("foo"), new IntValue(42), etc.) and use instanceof on that wrapper class.
That way, by static analysis of your code and class hierarchy, GWT can know exactly which types you'll send over the wire, and it will generate the code to handle all of those types, and only those types (not too few –causing errors like you're seeing–, not too many –generating bloated code–).
…or better yet, create specific event objects (whether they all inherit from a base class so that you can use a single, polymorphic execute() service method is up to you; I, for one, would rather use specific methods, possibly using multiple arguments rather than event objects then).
 
        void dummy(Date date);
    }

Since the GWT 1.6.4 serialize/deserialize the basic Java types
correctly, I'm wondering if there is a better way to avoid messing up
the service interface. For instance, add some special configuration in
the module xml file to instruct the RPC policy generator always allow
serialization/deserialization of basic Java types.

There's a blacklist of types, but no whitelist, no.

--
You received this message because you are subscribed to the Google Groups "Google Web Toolkit" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-web-toolkit+unsubscribe@googlegroups.com.
To post to this group, send email to google-web-toolkit@googlegroups.com.
Visit this group at http://groups.google.com/group/google-web-toolkit.
For more options, visit https://groups.google.com/d/optout.

No comments:

Post a Comment