It seems that the issue of having a mechanism for generic GWT-RPC
object serialization comes up frequently. While the motivation by the
developer for being able to do this in their code varies, the end
result is generally the same: a reference explicitly or implicitly is
made for GWT to serialize java.io.Serializable which then triggers the
GWT compiler to "go crazy" and generate code for every serializable
object on the class path. In the best case, this merely results in
bloated code; in the worst case, it results in a project that fails on
the server with ClassNotFound exceptions during GWT-RPC (I can provide
the specifics if anyone is interested).

In the situations that I have encountered, the developer typically
wants to build a generic GWT-RPC service where all they know about the
type of the argument(s) or return value is that GWT can serialize
it...the type may be a type from the JRE that GWT emulates (String,
Long, Date, etc) and can serialize or an object of their own creation
which I will assume can be made to implement
com.google.gwt.user.client.rpc.IsSerializable. The other common case
is the desire to pass or return collections such as List<Object> or
Map<String, Object> where, again, the developer only knows that Object
will be of a type that GWT can serialize.

There is a thread from 2008 (http://groups.google.com/group/Google-Web-
Toolkit-Contributors/browse_thread/thread/25d151960b48b5c4#) that
proposes one possible workaround. Before finding that solution, I
invented one on my own and posted it in response to a forum post on
the StackOverflow list (http://stackoverflow.com/questions/2210226/how-
can-i-keep-gwt-from-trying-to-include-every-serializable-class-when-i-
use-arr/3385509#3385509); unfortunately, my post hasn't received any
feedback. I don't feel nearly as strongly about the specific
implementation of a solution as I do that developers shouldn't have to
invent workarounds like this on their own. To that end, I am posting
my implementation (see below) for a class called RpcObject, and I
would like feedback: is the implementation sound, or are there
suggestions for improvement? should a class of this sort be provided
by GWT? is there interest in having it be a project of GWT-contrib?

In the event that I am native in my understanding of GWT-RPC and there
is already a better way to accomplish this [or there is one on the
roadmap], please let me know.

-Jeff


import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.google.gwt.user.client.rpc.IsSerializable;

public class RpcObject implements IsSerializable {
        protected HashMap<String, IsSerializable> rpcObjectWrapper = new
HashMap<String, IsSerializable>();

        /*
         * NOTE: The following fields are here to
         * trick/fool/work-around/whatever-you-want-to-call-it GWT-RPC's
         * serialization policy. Having these types present, even though
their
         * corresponding fields are never used directly, enables GWT-RPC to
         * serialize/deserialize these primitive types if they are
encountered in
         * the rpcWrapperObject! Of course GWT-RPC already knows how to
serialize
         * all these primitive types, but since, for example, String doesn't
         * implement GWT's IsSerializable interface, GWT has no expectation
that it
         * should ever be allowed in the rpcWrapperObject instance (and thus
String,
         * as well as all the other Java primitives plus Arrays of such types
as
         * well as List, Set, and Map, won't be part of the serialization
policy of
         * the RpcObject type). This is unfortunate because thanks to java
type
         * erasure, we can easily stuff Strings, Integers, etc into the
wrapper
         * without any issues; however, GWT-RPC will cowardly refuse to
serialize
         * them. Thankfully, it appears that the serialization policy is for
the
         * RpcObject type as a whole rather than for the rpcObjectWrapper
field
         * specifically. So, if we just add some dummy fields with these
"primitive"
         * types they will get added to the serialization policy (they are
         * effectively white-listed) of the type as a whole, and alas, GWT-
RPC stops
         * cowardly refusing to serialize them.
         */
        protected Byte _byte;
        protected Short _short;
        protected Integer _integer;
        protected Long _long;
        protected Float _float;
        protected Double _double;
        protected Date _date;
        protected Boolean _boolean;

        protected Byte[] _bytes;
        protected Short[] _shorts;
        protected Integer[] _integers;
        protected Long[] _longs;
        protected Float[] _floats;
        protected Double[] _doubles;
        protected Date[] _dates;
        protected Boolean[] _booleans;

        protected List<String> _list;
        protected Set<String> _set;
        protected Map<String, String> _map;

        public RpcObject() {
                super();
        }

        public RpcObject(final Object value) {
                super();
                this.setValue(value);
        }

        @SuppressWarnings("unchecked")
        public <X> X getValue() {
                HashMap h = (HashMap) rpcObjectWrapper;
                X value = (X) h.get("value");
                return value;
        }

        @SuppressWarnings("unchecked")
        public void setValue(Object value) {
                HashMap h = (HashMap) rpcObjectWrapper;
                h.put("value", value);
        }
}

-- 
http://groups.google.com/group/Google-Web-Toolkit-Contributors

Reply via email to