On Apr 7, 2008, at 7:06 AM, Rick McGuire wrote:
Dain Sundstrom wrote:
I've been sucked into another project and haven't been paying much
attention to the lists...
The problem is we flush before returning the created object to the
caller. The reason we do this is because database generated fields
are not filled in until the flush statement which means the primary
key is not guaranteed to be available until flush. The current
code requires the primary key to create the cmp proxy we return to
the caller. The code will have to be changed to allow for late
primary key resolution either when the code calls getPrimaryKey or
at the end of the transaction.
I don't have the time to look at this, but I can help you if you
want to work on it.
I've started poking around in the code trying to understand what
needs to change. Is the JpaCmpEngine.createBean() method where the
flushing takes place? It appears at that point in time that the
primaryKey is used for 1) creating the ThreadContext instance, 2)
ror storing the bean in the transaction cache, and 3) for creating
the ProxyInfo instance. Am I looking in the correct location for
this?
Yes.
The ThreadContext primary key bit looks easily changed to a lazy
resolution, and probably the ProxyInfo as well, but the transcaction
cache does not appear to be as easily changed, since the primary key
is the main lookup method for the transaction cache. I guess the
transaction cache step could be bypassed until the primary key is
actually generated, but I'm concerned that this could result in some
resolution failures where an object would be expected to be located
in the cache.
The transaction cache was introduced as a work around to the new-
delete-new bug in OpenJPA (see JpaTestObject.newDeleteNew()). If you
create, remove and recreated a bean with the same pk, OpenJPA
internally leave the pk as "deleted" so calls find(Class,Object)
result in a null. We work around this by using a private cache to
track the objects created during the transaction.
To implement delayed flush, you will have to add another way to track
the JPA instance object (since we won't have the pk to "find" the
object in the entity manager). When the pk is not available, you use
the new, alternate, method to find the object, and when the pk is
finally resolved, you would add it to the transaction cache.
Off the top of my head, it may be possible to use a stand-in pk object
which wraps the JPA object itself (using identity based hashcode and
equals) until the real pk is resolved. This pk object would then be
the alternate tx cache.
Any pointers on where the end of transaction processing would need
to be performed?
CmpContainer.ejbLoad(EntityBean) uses
TransactionSynchronizationRegistry.registerInterposedSynchronization
to store entities at the end of the transaction. You'll want to
expand that logic to handle pk resolution in addition to ejbStore
callbacks. The registerInterposedSynchronization doesn't really
handle ordering well so I suggest you use a single Synchronization
object to handle processing of the pks and the ejb store callbacks.
One other think to keep in mind is that before a CMP is passed to a
remote vm, you'll need to make sure the pk has been resolved.
-dain