PDA

View Full Version : RpcMap not-serializable problem



yafmbl
6 May 2009, 5:29 AM
Hi,

For some debugging purposes, we decided to keep some of our classes in serialized form, in a BLOB field of the DB.

The classes extend BaseModel class. BaseModel class contains a field of type RpcMap, which is not serializable itself. So, the actual JAVA serialization gives an error.

Here is a sample code snippet which produces the same exception:


BaseModel model = new BaseModel( ) ;

model.set( "somefield", "somevalue" ) ;
model.set( "anotherfield", "another value" ) ;

ByteArrayOutputStream baos = new ByteArrayOutputStream( ) ;
ObjectOutput oos = new ObjectOutputStream( baos ) ;
oos.writeObject( model ) ;
byte[ ] data = baos.toByteArray( ) ;

System.err.println( "size:" + data.length ) ;


The exception is:


Exception in thread "main" java.io.NotSerializableException: com.extjs.gxt.ui.client.data.RpcMap
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1156)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1509)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1474)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1392)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:326)


What we want to do in short is to be able to run the above code with minimum change.

Thanks in advance...

Colin Alworth
6 May 2009, 10:31 AM
Well, RpcMap at it's core is just a HashMap<String, Object>, so why not grab that map using RpcMap.getTransientMap(), and serialize that? Then to rehydrate the object, use the RpcMap.putAll() method.

Can you write a custom serializer to handle this to do it this way? If not, it is possible to modify RpcMap to make it serializable, as all of it's members are serializable.

yafmbl
7 May 2009, 1:50 AM
Thanks for the reply.

The problem with the first approach is, the actual class hierarchy and object graph is much deeper. So doign it manually is practically out of question.

The next option of changing it ourselves is smt that we do not want to do, because once we start doing modifications on the code, then we will need to maintain that part of the code as well. And in a newer release, we will need to remember those changes etc. In short we just want to use GXT as an external library.

And one other thing is, they did left the RpcMap not-serializable on purpose it seems and I wonder why is it this way? Will it break any innerworkings of GWT serialization mechanism? or any other side effects? IMHO the dev team can shed some light on this?

Thanks in advance...

per.abixh
16 Feb 2010, 4:09 AM
I saw in the code that the RpcMap is declared as being serializable - but I still do get this error.

Any Idea why? The only thing I can guess is that it has something to do with the transient field declared there. But RpcMap is implementing Serializable.

Any ideas?

chiappone
23 Feb 2010, 1:26 PM
I am also noticing this problem. Have you guys figured out a fix for this. I am trying to store a Model in google MemCache and it will not retrieve it due to the serializable issue.

thanks.

The_Jackal
10 Aug 2010, 5:59 PM
Why not just store the model properties new HashMap(model.getProperties()) or use a BeanModelMarker or BeanModelTag to wrap POJOs and store the POJOs instead.

yafmbl
11 Aug 2010, 12:05 AM
Our problem was not solved, even after marking the RpcMap serializable. It just removed the error, but the underlying map was empty. It was using a custom serializer for GWT. And for server side it is not working.
Simply wrapping a HashMap will not work because there are deep object hierarchies. You have to wrap all, and you have to un-wrap all. So we wrote a RpcMapWrapper class, which does implement readObject and writeObject methods. And we wrote another helper class to traverse the object hierarchy and replace all the RpcMaps with the wrapper objects, then we serialize. It is kind of a slow process, because all the objects in the hierarchy is traversed. But in our case, we did not need to do too frequently so it worked well for us.

Colin Alworth
11 Aug 2010, 6:09 AM
The RpcMap has its own serializer to keep it from trying to leave space in the rpc stream for all of those blank fields used for whitelisting. If you are seeing errors serializing, there are a couple of possibilities for what is going wrong. If it is an intermittent problem, it could be simply that the server doesn't have the same classes loaded the the client does. But if it always happens, you probably either have your own subclasses of the ModelData typed defined in GXT, or you are putting some of your own objects (including enums!) into these maps, but are not telling the GWT compiler that they need to be allowed to be serialized. Easiest way to do this is to subclass BaseModelData (or whatever) and add a private unused member for each data type you want to send over the wire within it.

Additionally, you can (as of GWT 2.0) add whitelist entries in the .gxt.xml file (either refer to each type by name or use a wild card):
<extend-configuration-property name="rpc.whitelist" value="my.namespace.client.model.*"/>