This topic is for those considering migrating from EclipseLink JPA or TopLink to ObjectDB JPA.
This concerns a huge "gotcha" that other assessing migrating from and EclipseLink-based JavaEE web application to ObjectDB may encounter, and so far I am not sure what the best solution for my case is, only what the problem statement and options are. At first I was convinced that this involved either an ObjectDB bug or departure from the JPA spec by ObjectDB, but thanks to insistence and persistence from ObjectDB support I now concede the difference is due to an extending "feature" of EclipseLink (and TopLink before it). To explain this properly (and how it may impact on your ObjectDB project and on your EclipseLink to ObjectDB migration) I have to refer to some external EclipseLink/TopLink forum material.
On running a large existing web application on Glassfish3.0.1 for the first time successfully (i.e. it loaded) with ObjectDB, I was horrified to find that all of my collection relationships were null (not even just empty where appropriate), and on various pages I got NullPointerExceptions where non-null collection results (including non-null empty) were expected.
As explained to me by ObjectDB support, while the entities in a result set list from a JPQ query are initially managed (and so lazy loading would initially work), they become detached once the EntityManager under control of the container, and then in ObjectDB (but not in EclipseLink) lazy loading fails.
The 3 possible solutions in the ObjectDB case seem to be:
1. Use explicit FetchType.EAGER on all desired collections (which requires some re-coding and has performance consequences when large relationship hierarchies are involved) to ensure the desired collections are resolved already before detachment, losing all the benefits of lazy loading of course.
2. Perform the query within a @Stateful session bean with an extended EntityManager as described here:
blogs.oracle.com/enterprisetechtips/entry/extended_persistence_context_in_stateful
This however has the consequence of a long conversation until the stateful bean is released.
3. Use a FETCH JOIN as described here:
Detach JPA objects with lazy initialized properties
This has the big problem that one would need to tune queries for every preempted relationship, which for my application is impractical.
If you are previously an EclipseLink or TopLink user you may well be taking inadvertent advantage of feature that permits resolution of lazy loaded relationships outside a transaction, once detached, any you won't have needed any of the above required under ObjectDB operation !
The following quotes are from authoritative EclipseLink/TopLink gurus:
From Tom Ware at http://dev.eclipse.org/mhonarc/lists/eclipselink-users/msg05258.html:
Detached Objects get the connection need to traverse the LAZY relationship from the EntityManagerFactory and will able able to use it as long as the EntityManagerFactory is open. The connection used in not the transactional one and when you want to use the entity in a transaction it will have to be properly merged.
From chris_delahunt at http://www.java.net/node/706426:
In http://forums.oracle.com/forums/thread.jspa?messageID=1706796 it describes a feature of Toplink/EclipseLink that allows accessing untriggered lazy relationships after they are detached as long as the context is still avalable, which is what you are encountering. As long as the Entity is not serialized, and the connections are still available, you should still be able to get the referenced person entity.
From http://forums.oracle.com/forums/thread.jspa?messageID=1706796:
I am testing features of detached entities with a standalone application, and particularly with lazy loading association.
It seems that it is very difficult to "completely" detache an entity of a standalone application with TopLink. Even if I close the entity manager or the entity manager factory after having detached the entity, the detached entity finds how to load the entities of the lazy loading association from the database, when it needs it (without any merge call).
From doug clarke http://forums.oracle.com/forums/thread.jspa?messageID=1706796:
This is a special feature of TopLink's implementation where the detached instances created from non-tx reads still have access in their proxies to retrieve additional dettached instances. If the object was detached through serialization this would not be possible.
..
If you would like TopLink Essentials to not process lazy relationships after the EM has closed I would recommend filing an enhancement request in GlassFish.
The upshot for ObjectDB users is that you may have to undertake significant recoding of your web application and substantial additional entity management to use your application with ObjectDB (or in my case so far just to even try it out on my existing large web application). This is a non trivial matter to say the least.
Hoping this helps somebody,
Webel