Posted by ljnelson
on June 15, 2006 at 8:15 AM PDT
I have a question about detached entities. Here is what I know so far.
I know that if you have an entity on your fat client and it crosses the wire to the server, you'd better call entityManager.merge(entity) to make sure that the persistence context (accessed via the EntityManager) "reattaches" the formerly detached entity back "into" itself. If you don't, you risk all sorts of Glassfish NullPointerExceptions the next time it tries to access a relationship field.
But what I don't know is if (on the server, obviously) my stateless session bean performs an operation that results in returning an entity over the wire to my fat client, what operations on this entity-now-being-used-on-the-client-as-more-or-less-a-data-structure are permissible on the client side?
I've found through trial and error, for example, that if, on the fat client, I attempt to access a Collection field that has been annotated as a OneToMany relationship, I get a NullPointerException from Glassfish (well, from Toplink). This is presumably because the object I'm calling is detached at that point (I'm on the client; no entity manager or persistence context in sight). Here is a short synopsis of the stack:
Caused by: java.lang.NullPointerException<br />
at oracle.toplink.essentials.internal.indirection.UnitOfWorkValueHolder.instantiate(UnitOfWorkValueHolder.java:217)<br />
at oracle.toplink.essentials.internal.indirection.DatabaseValueHolder.getValue(DatabaseValueHolder.java:82)<br />
at oracle.toplink.essentials.indirection.IndirectList.buildDelegate(IndirectList.java:193)<br />
at oracle.toplink.essentials.indirection.IndirectList.getDelegate(IndirectList.java:315)<br />
at oracle.toplink.essentials.indirection.IndirectList.isEmpty(IndirectList.java:393)<br />
at sapling.common.QueryEntity.getColumnNames(QueryEntity.java:82)<br />
There are ways in which this makes sense to me and ways in which this does not: on the one hand, I'm guessing that Toplink has somehow surgically altered the contents of my class such that the collection field is supplied by Toplink, and for better or for worse Toplink is assuming? maybe? that this entity is always on the server side, and is never going to be passed to the client as a detached object. That might be, for example, why the stack above is doing something with DatabaseValueHolder even though I'm on the client.
On the other hand, it's a NullPointerException, and an entity is supposed to be a POJO; I would like to be able to access any damn field I like anywhere I like. Any issues that crop up should occur when, back on the server side, I attempt to persist or merge the entity.
So: detached entities--bad idea? Do I really have to return to the old EJB 2.1 days of data transfer objects shipped back to the client? Is working with entities on both the client and the server a design smell, or a good way to go? I thought the whole point of entities was that they were fundamentally just Java objects.