LiveCycle Data Services are a very powerful tool. This period we're working on 3 different projects that use these services and I discovering many "under the hood" capabilities.
But these days we don't sleep to trying to solve a problem and to understand if there's a solution for that.
The problem is with the use of lazy EJB3 with the RemoteObject class.
When working with EJB3 in order to avoid the possibility of loading your entire database you have to use any lazy fetching strategy. (We tried with Graniteds Data Services and it works well.)
This is the scenario : a business logic that uses an EJB3 (lazy) application and Flex Data Services to manage data for a Flex application.
The problem we're facing is the following :
Is it possible to use RemoteObject (without using the Data Management Services) to load Java objects that are persisted by EJB3 and have some of their properties lazily initialized?
I try to explain more in detail with the following information :
The environment in use is a JBoss application server and a MySQL 5 DBMS; the deployed applications in JBoss are an EJB3 application, containing domain classes and business beans, and a Flex Data Services .war application, with configuration for remoting services; the FDS war application has a library of delegate classes that perform the EJB lookup and use the EJB beans; these classes act as destinations of flex RemoteObjects and are called from the Flex client.
For example there is a Person class that has a List of Address objects, which is annotated with lazy fetch:
// Person.java
@OneToMany (fetch = FetchType.LAZY, mappedBy = "person")
public List<Address> getAddresses() {
return addresses;
}
A stateless bean, PersonBean, fetches a Person from the underlying database:
// PersonBean.java
public Person getPerson(long id) throws Exception {
Person p = this.em.find(Person.class, id);
return p;
}
The stateless bean implements a @Local interface.
These classes are deployed inside an EJB3 jar file, configured to connect to the local MySQL database.
A Java class performs the EJB lookup and calls the PersonBean; the class is placed in a jar file inside the lib folder of the FSD war application:
// PersonDelegate.java:
public Person getPerson(long id) throws Exception {
return bean.getPerson(id);
}
PersonDelegate is configured as remote object destination, in remoting.config.xml:
<destination id="personDelegate">
<properties>
<source>com.delegate.PersonDelegate</source>
<scope>application</scope>
</properties>
<adapter ref="java-object" />
</destination>
The flex client has a RemoteObject that uses the defined destination and calls the getPerson() method to fetch a Person object but when the call is made the following error comes out:
faultCode:Server.Processing faultString:'failed to lazily initialize a collection of role: com.Person.addresses, no session or session was closed' faultDetail:'null'
and in the JBoss log a org.hibernate.LazyInitializationException appears, related to the addresses field of Person.
If Person.java is modified to use FetchType.EAGER everything works fine, the addresses are loaded; but in a more general case, where the graph of java objects can grow very large, the use of eager fetch may cause unnecessary data to be loaded and the application is slowed down.
So the question we're trying to solve are :
Is there a way to avoid being thrown the LazyInitializationException when making RemoteObject calls?
The Person object may arrive without the lazily fetched addresses Collection, which could be loaded in a later request?
The HibernateAssembler seems to handle lazy fetching, so the solution might be to reconfigure the application to use data management services instead of RemoteObject calls?
And in that case what should be used instead of the HibernateAssembler, as the application uses EJB3 to handle persistence and not Hibernate?
Stay tuned and we'll shortly be able to give you the solution :)