db-jdo-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Craig L Russell <Craig.Russ...@Sun.COM>
Subject Proposal for new method (long)
Date Mon, 09 Oct 2006 17:58:08 GMT
Javadogs,

I'd like to propose a solution to a problem that we have with  
usability in the web tier. When using a servlet, each method that  
needs access to a PersistenceManager needs to figure out where the  
current PersistenceManager is, and if it is even active. There are  
many ways around this issue, but they are not general. Among the  
workarounds are putting the active PersistenceManager into the  
servlet context as a request or session attribute, passing the  
PersistenceManager explicitly as a parameter, and putting the  
PersistenceManager into a ThreadLocal field.

Of these workarounds, the one with the most appeal is the ThreadLocal  
solution. So I'd like to propose that we formalize this by adding a  
method to return a thread-safe PersistenceManager proxy associated  
with a PersistenceManagerFactory that can be implemented as a  
singleton, stored in a component's static field, and that dynamically  
binds to the PersistenceManager that is currently active on the thread.

Multiple PersistenceManager proxies can be active, each with its own  
binding to a (possibly different) PersistenceManagerFactory.

The benefit of this proposal is ease of use for web and ejb  
components that currently have to manage their own PersistenceManager  
resources. Instead of having to look up and store a  
PersistenceManager in each method of each component that needs one,  
looking up the PersistenceManagerFactory can be done once during  
initialization of the component.

The limitations of the proposal is that in environments that do not  
support Java EE 5 TransactionSynchronizationRegistry (i.e. J2SE  
servers and Java SE), only one PersistenceManager per  
PersistenceManagerFactory can be used per thread (which maps to a  
single web request), and only one transaction can be used per  
PersistenceManager.

In environments that support Java EE 5  
TransactionSynchronizationRegistry, container-managed transactions  
can be used, including the ability to suspend transactions.

If used in an environment that does not support Java EE 5  
TransactionSynchronizationRegistry, the behavior is as follows:

The first component to use a PersistenceManager method on a thread  
would get a PersistenceManager from the factory. Subsequent callers  
would use the same PersistenceManager delegate until the transaction  
completed, at which time the PersistenceManager is cleared and the  
first subsequent request would create a new one.

Implementation: The proxy would delegate most methods to the current  
PersistenceManager, as determined by the ThreadLocal field being non- 
null. Calling close() would have no effect. If the ThreadLocal field  
is null, then getPersistenceManager() would be called on the  
PersistenceManagerFactory. A synchronization instance would be  
created and registered with the currentTransaction of the newly  
acquired PersistenceManager, the PersistenceManager would be set into  
the ThreadLocal, and then the request wold be delegated to the new  
PersistenceManager. At afterCompletion, the ThreadLocal would be  
nullified.

If used in an environment that supports Java EE 5  
TransactionSynchronizationRegistry, the behavior is as follows:

The first component to use a PersistenceManager method in a managed  
transaction would get a PersistenceManager from the factory.  
Subsequent callers in the same transaction would use the same  
PersistenceManager delegate until the transaction completed, at which  
time the PersistenceManager is cleared and the first request in a new  
transaction would create a new one.

Implementation: The proxy would delegate most methods to the current  
PersistenceManager, as determined by the  
TransactionSynchronizationRegistry entry for the  
PersistenceManagerFactory being non-null. Calling close() would have  
no effect. If the TransactionSynchronizationRegistry entry for the  
PersistenceManagerFactory is null, then getPersistenceManager() would  
be called on the PersistenceManagerFactory. An interposed  
synchronization instance would be created and registered with the  
TransactionSynchronizationRegistry, the PersistenceManager would be  
set into the TransactionSynchronizationRegistry entry for the  
PersistenceManagerFactory, and then the request wold be delegated to  
the new PersistenceManager. At afterCompletion, the  
TransactionSynchronizationRegistry entry for the  
PersistenceManagerFactory would be nullified.

If we agree on the semantics of this behavior, the method can be  
implemented as a helper method of JDOHelper, PersistenceManager  
getPersistenceManagerProxy or something like it (suggestions welcome).

To support container-managed transactions in J2EE servers (1.4 and  
earlier), we would have to put the method on  
PersistenceManagerFactory and allow the implementation to use its own  
secret sauce to provide the proper semantics. If the jdo  
implementation chose, it could simply delegate to the JDOHelper  
version of the method, with the limitations therein.

Craig

Craig Russell
Architect, Sun Java Enterprise System http://java.sun.com/products/jdo
408 276-5638 mailto:Craig.Russell@sun.com
P.S. A good JDO? O, Gasp!


Mime
View raw message