Hibernate Serialization Exception in GWT but Eclip

2019-05-12 03:19发布

问题:

I am using eclipselink JPA implementation (Entity) with GWT 2.0 framework on presentation layer. Everything is working properly. But when i change my JPA implementation to Hibernate, I get Serialization/Deserialization Exception on GWT Layer when I pass entity beans but It is okay on eclipselink JPA. Whats really happens? Hibernate is an implementation of JPA and eclipselink too, why those act differently?

What should I do for solving this exception on Hibernate? using Hibernate4gwt?

Which JPA implementation is better for GWT?

Regards

回答1:

I recommend to read the whole Using GWT with Hibernate paper, it explains very nicely why enhanced classes (whether you're using proxies or weaving) are "problematic" for GWT:

Why Hibernate objects can't be understood when they reach the browser world

...

When you take an object and turn it into a Hibernate object, the object is now enhanced to be persistent. That persistence does not come without some type of instrumentation of the object. In the case of Hibernate, the Javassist library actually replaces and rewrites the bytecode for these objects by persistent entities to make the Hibernate magic work. What this means for GWT RPC is that by the time the object is ready to be transferred over the wire, it actually isn't the same object that the compiler thought was going to be transferred, so when trying to deserialize, the GWT RPC mechanism no longer knows what the type is and refuses to deserialize it.

In fact, if you were to look deeper to the earlier call to loadAccounts(), and step into the RPC.invokeAndEncodeResponse() method, you would see that the object we're trying to deserialize has now become an ArrayList of Account types with their java.util.Set of records replaced by the org.hibernate.collection.PersistentSet type.

Similar problems arise with other persistence frameworks, such as JDO or JPA, used on Google App Engine.

...

So my understanding it that this isn't an Hibernate specific problem and you might also run into troubles with alternative JPA implementations, including EclipseLink if you use static or dynamic weaving (you're not forced to use weaving but then you miss features like lazy loading or fetch groups).

The paper suggests several integration strategies allowing to workaround the issues:

  • Using Data Transfer Objects (argh!)
  • Using Dozer for Hibernate integration (an improved version of the previous approach)
  • Using Gilead (formerly known as Hibernate4Gwt) for Hibernate Integration

It also discusses their pros and cons, just check it out.

To sum up...

First, I don't think there is a "best" JPA implementation for GWT, they are all facing the same issue. If you can live without lazy loading, EclipseLink without weaving might be simpler. But you'd be somehow burying your head in the sand, the issue is there and you won't be able to use another implementation.

Second, while the two first "integration strategies" will work with any JPA provider, Hibernate is the only JPA implementation currently supported by Gilead (but OpenJPA and EclipseLink supports is planned).

Pick your poison :)

See also

  • Gilead Presentation
  • GWT Developer Forum


回答2:

Another thought: Custom Field Serializers.

Example: MyClass has a member mapped in a One To Many relationship with YourClass:

public class MyClass implements Serializable {

    private List<YourClass> yourClassList;

    @OneToMany(mappedBy="myClass")
    public List<YourClass> getYourClassList {
        return yourClassList;
    }
}

The precise implementation Hibernate will use is probably PersistentBag, which is not serializable, for the reasons Pascal mentioned. But GWT provides Custom Field Serializers to control the serialization. It would look something like this.

public class MyClass_CustomFieldSerializer {
   public serialize(SerializationStreamWriter writer, MyClass instance) throws SerializationException {
       writer.write(new ArrayList<YourClass>(instance.getYourClassList());
   }
}

Advantage here is not having to mess with Gilead/Dozer/more external libraries.