0

Problem seems to be that not all Guava classes are serializable out-of-the-box.

I found a quite good solution to this and like to share it. (in this case for HashBiMap). (Maybe some Guava developers may apply this one day to ideally all of the classes)

If you copy the below class (and maybe adjust it to your to-be-serializable class) you will have further investigation details inside the Javadoc comment already.

package com.google.common.collect;

import java.util.LinkedHashMap;
import java.util.Map;

import com.google.gwt.user.client.rpc.SerializationException;
import com.google.gwt.user.client.rpc.SerializationStreamReader;
import com.google.gwt.user.client.rpc.SerializationStreamWriter;
import com.google.gwt.user.client.rpc.core.java.util.Map_CustomFieldSerializerBase;

/**
 * idea taken from some <a href=
 * "http://code.google.com/r/baggiogamp-guava/source/browse/gwt-src/com/google/common/collect/RegularImmutableBiMap_CustomFieldSerializer.java?r=a7aa10ddb815ce7996f3fae103bfd3823b1336ed&spec=svn6923b5fac0feb7005429d0b24be93b91685f9637"
 * >com/google/common/collect/RegularImmutableBiMap_CustomFieldSerializer.java</
 * a> <br/>
 * Problem was, that {@link HashBiMap} seems not to be serializable for GWT:
 * <ul>
 * <li>it nor its super classes do not implement com.google.gwt.user.client.rpc.IsSerializable (why?)</li>
 * <li>the following solution does not work if only applied to some super class, e.g. AbstractBiMap</li>
 * </ul>
 * <pre>
 * com.google.gwt.user.client.rpc.IncompatibleRemoteServiceException: The response could not be deserialized
    at com.google.gwt.user.client.rpc.impl.RequestCallbackAdapter.onResponseReceived(RequestCallbackAdapter.java:221)
    at com.google.gwt.http.client.Request.fireOnResponseReceived(Request.java:287)
    at com.google.gwt.http.client.RequestBuilder$1.onReadyStateChange(RequestBuilder.java:395)
    at sun.reflect.GeneratedMethodAccessor119.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at com.google.gwt.dev.shell.MethodAdaptor.invoke(MethodAdaptor.java:103)
    at com.google.gwt.dev.shell.MethodDispatch.invoke(MethodDispatch.java:71)
    at com.google.gwt.dev.shell.OophmSessionHandler.invoke(OophmSessionHandler.java:172)
    at com.google.gwt.dev.shell.BrowserChannelServer.reactToMessagesWhileWaitingForReturn(BrowserChannelServer.java:338)
    at com.google.gwt.dev.shell.BrowserChannelServer.invokeJavascript(BrowserChannelServer.java:219)
    at com.google.gwt.dev.shell.ModuleSpaceOOPHM.doInvoke(ModuleSpaceOOPHM.java:136)
    at com.google.gwt.dev.shell.ModuleSpace.invokeNative(ModuleSpace.java:571)
    at com.google.gwt.dev.shell.ModuleSpace.invokeNativeObject(ModuleSpace.java:279)
    at com.google.gwt.dev.shell.JavaScriptHost.invokeNativeObject(JavaScriptHost.java:91)
    at com.google.gwt.core.client.impl.Impl.apply(Impl.java)
    at com.google.gwt.core.client.impl.Impl.entry0(Impl.java:242)
    at sun.reflect.GeneratedMethodAccessor116.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at com.google.gwt.dev.shell.MethodAdaptor.invoke(MethodAdaptor.java:103)
    at com.google.gwt.dev.shell.MethodDispatch.invoke(MethodDispatch.java:71)
    at com.google.gwt.dev.shell.OophmSessionHandler.invoke(OophmSessionHandler.java:172)
    at com.google.gwt.dev.shell.BrowserChannelServer.reactToMessages(BrowserChannelServer.java:293)
    at com.google.gwt.dev.shell.BrowserChannelServer.processConnection(BrowserChannelServer.java:547)
    at com.google.gwt.dev.shell.BrowserChannelServer.run(BrowserChannelServer.java:364)
    at java.lang.Thread.run(Unknown Source)
Caused by: com.google.gwt.user.client.rpc.SerializationException: com.google.common.collect.HashBiMap/1352983899
    at com.google.gwt.user.client.rpc.impl.SerializerBase.getTypeHandler(SerializerBase.java:153)
    at com.google.gwt.user.client.rpc.impl.SerializerBase.instantiate(SerializerBase.java:114)
    at com.google.gwt.user.client.rpc.impl.ClientSerializationStreamReader.deserialize(ClientSerializationStreamReader.java:396)
    at com.google.gwt.user.client.rpc.impl.AbstractSerializationStreamReader.readObject(AbstractSerializationStreamReader.java:119)
    at mycomp.shared.conf.Config_FieldSerializer.deserialize(Config_FieldSerializer.java:12)
    at mycomp.shared.conf.Config_FieldSerializer.deserial(Config_FieldSerializer.java:35)
    at com.google.gwt.user.client.rpc.impl.SerializerBase.deserialize(SerializerBase.java:95)
    at com.google.gwt.user.client.rpc.impl.ClientSerializationStreamReader.deserialize(ClientSerializationStreamReader.java:398)
    at com.google.gwt.user.client.rpc.impl.AbstractSerializationStreamReader.readObject(AbstractSerializationStreamReader.java:119)
    at com.google.gwt.user.client.rpc.impl.RequestCallbackAdapter$ResponseReader$8.read(RequestCallbackAdapter.java:106)
    at com.google.gwt.user.client.rpc.impl.RequestCallbackAdapter.onResponseReceived(RequestCallbackAdapter.java:214)
    at com.google.gwt.http.client.Request.fireOnResponseReceived(Request.java:287)
    at com.google.gwt.http.client.RequestBuilder$1.onReadyStateChange(RequestBuilder.java:395)
    at sun.reflect.GeneratedMethodAccessor119.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at com.google.gwt.dev.shell.MethodAdaptor.invoke(MethodAdaptor.java:103)
    at com.google.gwt.dev.shell.MethodDispatch.invoke(MethodDispatch.java:71)
    at com.google.gwt.dev.shell.OophmSessionHandler.invoke(OophmSessionHandler.java:172)
    at com.google.gwt.dev.shell.BrowserChannelServer.reactToMessagesWhileWaitingForReturn(BrowserChannelServer.java:338)
    at com.google.gwt.dev.shell.BrowserChannelServer.invokeJavascript(BrowserChannelServer.java:219)
    at com.google.gwt.dev.shell.ModuleSpaceOOPHM.doInvoke(ModuleSpaceOOPHM.java:136)
    at com.google.gwt.dev.shell.ModuleSpace.invokeNative(ModuleSpace.java:571)
    at com.google.gwt.dev.shell.ModuleSpace.invokeNativeObject(ModuleSpace.java:279)
    at com.google.gwt.dev.shell.JavaScriptHost.invokeNativeObject(JavaScriptHost.java:91)
    at com.google.gwt.core.client.impl.Impl.apply(Impl.java)
    at com.google.gwt.core.client.impl.Impl.entry0(Impl.java:242)
    at sun.reflect.GeneratedMethodAccessor116.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at com.google.gwt.dev.shell.MethodAdaptor.invoke(MethodAdaptor.java:103)
    at com.google.gwt.dev.shell.MethodDispatch.invoke(MethodDispatch.java:71)
    at com.google.gwt.dev.shell.OophmSessionHandler.invoke(OophmSessionHandler.java:172)
    at com.google.gwt.dev.shell.BrowserChannelServer.reactToMessages(BrowserChannelServer.java:293)
    at com.google.gwt.dev.shell.BrowserChannelServer.processConnection(BrowserChannelServer.java:547)
    at com.google.gwt.dev.shell.BrowserChannelServer.run(BrowserChannelServer.java:364)
    at java.lang.Thread.run(Unknown Source)
 * </pre>
 * 
 * @author ADietrich
 * 
 */
public class HashBiMap_CustomFieldSerializer {

    public static void deserialize(SerializationStreamReader reader,
        HashBiMap<?, ?> instance) {
    }

    public static HashBiMap<Object, Object> instantiate(
            SerializationStreamReader reader) throws SerializationException {
        Map<Object, Object> entries = new LinkedHashMap<Object, Object>();
        Map_CustomFieldSerializerBase.deserialize(reader, entries);
        return HashBiMap.create(entries);
    }

    public static void serialize(SerializationStreamWriter writer,
        HashBiMap<?, ?> instance) throws SerializationException {
        Map_CustomFieldSerializerBase.serialize(writer, instance);
        }
}
Andreas Covidiot
  • 4,286
  • 5
  • 51
  • 96
  • 1
    [It's ok to ask and answer your own question](http://blog.stackoverflow.com/2011/07/its-ok-to-ask-and-answer-your-own-questions/), but you'll have to split it into a question and an answer post! – Chris Lercher Jan 03 '13 at 11:01
  • I wanted to do this, but new users can only answer their own questions after 8 hours :-/ – Andreas Covidiot Jan 03 '13 at 11:08
  • 2
    I don't get it. `HashBiMap` is `Serializable`, are you using some older version? – maaartinus Jan 03 '13 at 13:55
  • I don't know why it is not working then. You should be able to try it yourself with just some class containing an empty `HashBiMap` field. `java.io.Serializable` vs. `com.google.gwt.user.client.rpc.IsSerializable` ... this answer says that it should not matter too much which one to use: http://stackoverflow.com/a/3065519/1915920, but as I started with my first GWT project I found non-BiMap-related cases where I had to use the latter (but maybe it was only my interpretation after some fiddling with various possiblities :-) ) – Andreas Covidiot Jan 03 '13 at 14:35
  • The proper response to this is to file a bug report with Guava. – Louis Wasserman Jan 05 '13 at 19:32

1 Answers1

0

Implementing Serializable is sufficient only for specially designed classes. Guava's classes aren't designed that way (for various reasons). As a result, we need to add special support for each individual class. We've done this for some classes, and we can do it for others, though there are tradeoffs. We have a feature request for GWT serialization where you can read more detail and make requests. However, I'd first consider using ImmutableBiMap, rather than HashBiMap, in your RPC interface. ImmutableBiMap, like most of the immutable types, is already GWT serializable.

Chris Povirk
  • 3,738
  • 3
  • 29
  • 47
  • (Sorry - just saw the answer now. I did not get a reminder of your post.)Thanks a lot for your suggestion although it may be problematic if I want to manipulate the map on the client-side (which may be more or less likely)! – Andreas Covidiot Sep 27 '13 at 06:48