Summary:
It would be nice if Hibernate supported three options for lazy proxy object serialization:
proxy - send the proxy (current behaviour)
initialize - initialize the proxy and send the target
nullify - uninitialized proxies get sent as null; if the proxy is initialised then the target is sent.
Background:
I am trying to open up a legacy system to heterogenous clients. We have wrapped the legacy system with a combination of EJBs and POJOs. Clients that want write-access to the legacy system use EJBs that persist using screen scraping. Practically all of the read-access is done using stateless session beans which return POJO's managed by Hibernate (i.e., the DAO pattern). We have put Apache Axis in front of the EJB container to make our lifes even more miserable.
At the moment we are trying to control the cut-points in the object graph returned by the stateless session beans. We need fairly fine grained control over whan objects are returned to the client for two reasons:
1) Populating the whole object graph from the top-level objects down would simply be too slow and
2) Apache Axis' BeanSerializer traverses the whole object graph returned by the stateless session bean. In doing so it hits a LazyInitialisationException because a) it is running in a different JVM, b) some of the components returned are lazy proxies and c) we have not reattached them. See the first point for the reason why we cannot automatically reattach them.
We have decided to cut the object graph in the session beans (i.e., leaf nodes are null, depending on the method called).
To prevent the LazyInitializationException in Axis we must explicitly nullify the individual properties that we don't want to return. For example:
Code:
Contract contract = (Contract)query.uniqueResult()
contract.setDeeplyNestedLazilyLoadedProperty(null);
return contract;
However in some methods we /do/ want to return the lazily loaded properties. We cannot easily reattach the objects when they have reached the Apache Axis' VM so we call Hibernate.initialize() before returning.
Code:
Contract contract = (Contract)query.uniqueResult()
Hibernate.initialize(getDeeplyNestedLazilyLoadedProperty());
return contract;
But -- we to remember to explicitly nullify or initialize any lazyily loaded properties of DeeplyNestedLazilyLoadedProperty.
Code:
Contract contract = (Contract)query.uniqueResult()
SomeProp prop = contract.getDeeplyNestedLazilyLoadedProperty();
Hibernate.initialize(prop);
prop.setPropertyA(null);
Hibernate.initialize(prop.getPropertyB());
prop.getPropertyB().setPropertyC(null);
return contract;
Having three options for lazy proxy serialization would allow us to set some sensible defaults in our mapping files instead of having this kind of messy code repeated in our session beans.
What do you think?