Friday, October 28, 2016

Problem with GWT RPC and Enhanced classes that are not.

I have recently run into a problem with GWT RPC.  I use Hibernate and I send my entities over the wire using GWT-RPC.  Object graphs are transformed before they are sent to the client to snip unwanted references and replace lazy loading collections, similar to Gilead if my understanding is correct.  At any rate, the object graph being sent over RPC is intended to be a graph of POJO's, and this has seemingly worked well for several months until I unexpectedly received a deserialization error on the server.  I won't post the specifics of this error here or why it suddenly occurred; I have debugged it and the cause of the problem appears to be:

1.  My POJO's are also Hibernate Entities and are annotated with @Entity
2.  This annotation triggers the GWT-RPC SerializableTypeOracleBuilder to determine my class as "Maybe Enhanced"
3.  Being "maybe enhanced" triggers the GWT serialization framework to look for set() methods for setting fields and, where found, to use these in preference to direct field access when deserializing a graph.
4.  My classes are not enhanced (and if they were, I would not want them treated the way GWT RPC currently does; I find the implemented solution to enhanced classes makes me queasy).
5.  The implementation, as it stands, can call methods on partially deserialized objects.  I believe this has been a long standing issue with GWT-RPC which has been noted before with respect to Object.hashCode and Object.equals being called on partially deserialized objects while populating collections.  I wonder if RPC deserialization should proceed in two passes; one to construct all objects and silently set all fields on those objects and a second pass to allow collections and perhaps this bizarre Enhanced mechanism to call methods on these objects to finalize the graph.  However, this question is not the nature of my post.

My issue with this is that I am unable to find a satisfactory way to disable this "enhanced" class detection and subsequent serialization behaviour that it triggers.  What I want is field based serialization and deserialization.  My options for disabling this "feature" seem to be:
1.  Remove the @Entity annotation from by entity beans and declare them as entities in xml.  Not appealing to me; I like the simplicity and cleanliness of using annotations.
2.  Modify the set() methods on my Entity beans so that they avoid generating exceptions by accessing fields which may not have been deserialized yet.  This is one workaround, but it's not appealing either: I really don't want methods being called on my objects until they are fully deserialized, and I don't want to litter my code with checks which otherwise would not be there.  I already have a specific HashMap implementation I use for GWT serialization which avoids calling hashCode() or equals() during deserialization, but at least this is self-contained.
3.  Hammer the GWT ServiceInterfaceProxyGenerator to stop it declaring my classes enhanced.  I did this with some success - I use a custom SIPG which inherits from the GWT standard SIPG, and I forcibly unset the enhanced setting on all JClassType instances in an overridden generateTypeHandlers() method.  This works well - at least the .gwt.rpc files do not have @ClientFields entries in them, and RPC works fine.  However it is obviously horrible and not a permanent solution, but it is better to me than the alternatives.  Unfortunately, and more critically, it does not seem to work in SuperDev mode, which I use extensively.  Does anyone have any suggestions why this might be or how I can fix it?  Happy to post in detail about the errors experienced here if someone feels they might be able to shed light on it.

What I would really like is a way of turning off this enhanced class detection feature which works throughout the GWT toolchain...

Any help most gratefully received

- Will


--
You received this message because you are subscribed to the Google Groups "GWT Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-web-toolkit+unsubscribe@googlegroups.com.
To post to this group, send email to google-web-toolkit@googlegroups.com.
Visit this group at https://groups.google.com/group/google-web-toolkit.
For more options, visit https://groups.google.com/d/optout.

No comments:

Post a Comment