Hi all.
I was the one at the back of the room at Rob's GWT RPC talk who had a
HibernateFilter that he wanted to integrate into GWT. It's a quick and
dirty solution, but it works for me. All it really requires is one
line in ServerSerializationStreamWriter in order to activate it, but
with the current methods there's no way to override this functionality
without replacing all the RPC classes with tweaked versions of my
own.
Here's the 1 line change I need in
ServerSerializationStreamWriter.java
private enum ValueWriter {
OBJECT {
@Override
void write(ServerSerializationStreamWriter1529 stream,
Object instance) throws SerializationException {
stream.writeObject(HibernateFilter.filter(instance));
}
}
}
And here's the HibernateFilter.
public class HibernateFilter {
public static Object filter(Object instance) {
if (instance == null) {
return instance;
}
if (instance instanceof Date) {
return new java.util.Date(((java.util.Date) instance).getTime());
}
if (instance instanceof PersistentSet) {
HashSet<Object> hashSet = new HashSet<Object>();
PersistentSet persSet = (PersistentSet) instance;
if (persSet.wasInitialized()) {
hashSet.addAll(persSet);
}
return hashSet;
}
//... similar code as above for PersistentList, Bag, Map, etc...
if (instance.getClass().getName().contains("CGLIB")) {
if (Hibernate.isInitialized(instance)) {
CGLIBLazyInitializer cg = (CGLIBLazyInitializer) instance;
log.warn("On The Fly initialization: "+ cg.getEntityName());
return cg.getImplementation();
} else {
log.debug("Uninitialized CGLIB");
return null;
}
}
return instance;
}
}
I'd prefer to be able to integrate this simple filter into the
serialization stream without copying the RPC and
ServerSerializationStreamWriter classes into my project.
Playing around with a solution to this I've come up with something
that will allow me to write code such as the following.
ServerSerializationStreamWriter writer = new
ServerSerializationStreamWriter(
rpcRequest.getSerializationPolicy());
writer.setValueWriter(Object.class, new ValueWriter() {
public void write(
ServerSerializationStreamWriter stream,
Object instance) throws SerializationException
{
stream.writeObject(HibernateFilter.filter(instance));
}
});
return RPC.invokeAndEncodeResponse(
this, rpcRequest.getMethod(), rpcRequest
.getParameters(), writer);
The major changes are:
1) RPC.invokeAndEncodeResponse() now takes a
ServerSerializationStreamWriter instead of a SerializationPolicy
2) ValueWriter is now a public interface instead of an enumeration
3) ServerSerializationStreamWriter has a setValueWriter(Class,
ValueWriter) method for overriding defaults.
I'd love to hear another idea for how to integrate this. An
alternative would be to make RPC not final and allow encodeResponse()
to be overriden so I can setup my own SerializationWriter there, but I
assumed that that would be less popular. I know Hibernate4GWT includes
an RPCCopy class as well, so it's definitely something people are
dealing with now.
Oh and to be clear, I'm not advocating that my HibernateFilter is
included, just that there's some sort of RPC filter extension point
that's easily accesible.
Cheers,
-Jeff
http://www.myhippocampus.com