Wednesday, November 12, 2008

Protobuf not Serializable ?!

I'm starting to use Google's protobuf for serialization and deserialization of objects. Its looks great, ought I'm still going to check out Facebook's Thrift, just to make sure I'm not missing something.
The code is very easy to use and much better then any of the XML to object mappings, or for that matter, XML as a data structure.
Still, there is one big cavity in protobuf. The generated objects do not implement Serializable. I hope there is a good reason for that though I didn't find one. Without knowing any better, its looks very simple to have the generated objects extend the interface.

With a large legacy codebase it is not feasible to change the bl transportation layer to use protobuf in one swift. Therefore you're stack if you have protobuf objects floating around and you need to java serialize them.

If you can embed the protobuf object in another one then its easy (though unpleasant) to solve the problem. I solved it by having a Externalizable class that wraps the protobuf object and deals with the java serialization for it.

For example, assuming NewsMediaContent is the protobuf object:

public class NewsMediaContentSerializer implements Externalizable{
private NewsMediaContent _media;
public NewsMediaContentSerializer(){}
public NewsMediaContentSerializer(NewsMediaContent media){_media = media;}
public NewsMediaContent getMedia (){return _media;}
public void readExternal (ObjectInput in) throws IOException, ClassNotFoundException{
int size = in.readInt();
if(0 == size) return;
byte[] array = new byte[size];
in.readFully(array);
_media = NewsMediaContent.parseFrom(array);
}
public void writeExternal (ObjectOutput out) throws IOException {
if(null == _media){out.writeInt(0); return;}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
_media.writeTo(baos);
baos.close();
byte[] array = baos.toByteArray();
out.writeInt(array.length);
out.write(array);
}
}


And use it like this:

  public NewsMediaContent getNewsMediaContent (){
return null == _mediaHolder ? null : _mediaHolder.getMedia();
}
public void setNewsMediaContent (NewsMediaContent media){
_mediaHolder = new NewsMediaContentSerializer(media);
}

0 comments:

Creative Commons License This work by Eishay Smith is licensed under a Creative Commons Attribution 3.0 Unported License.