db-jdo-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Wes Biggs <...@tralfamadore.com>
Subject Re: Proposal for new method (long)
Date Wed, 11 Oct 2006 12:42:24 GMT
Craig,

I've used this approach myself, and found it to generally improve 
productivity in web application development.

However, I would question whether enshrining it in the API is really 
that valuable.  There are definite limitations to the usefulness of a 
ThreadLocal PM, from the obvious one of not being able to easily share 
it in threaded subtasks (producer-consumer, for example, or other 
scenarios where a web request initiates an asynchronous action), to the 
lack of ability to control PM lifecycle (from a user perspective) and 
the lack of ability to optimize PM reuse and caching (from a provider 
perspective).  ThreadLocals are also notoriously difficult to debug, 
particularly in the area of memory leaks.  Undoubtedly there are 
techniques to get around all of those, but let's just say it's not a 
silver bullet.

Apart from the J2EE integration scenario, it's trivially easy for the 
user (or a web framework component) to create a ThreadLocal PM helper 
method; the API is public (unlike most JDOHelper methods, which rely on 
"hidden methods" and an SPI layer).

Now, with that all said, I support anything that helps get us closer to 
truly transparent persistence, which I define as "not having to worry 
about the sodding PMF or PM".  What I'd really like to see is a 
configuration/injection method (per environment -- SE and EE) that makes 
it as trivial as possible to get a PM and start doing some real work.  
At the most (and overly) basic level, this becomes 
PersistenceManager.getInstance(), and the environment is responsible for 
determining exactly where the instance comes from.  In this context, 
ThreadLocal is a particular configuration strategy that may suit some 
applications.

The persistence unit concept -- or for our purposes, named PMFs -- is a 
useful bridge between configuring the environment (runtime) and 
configuring the application (design time).  For example, I might want to 
configure the environment such that PM.getInstance(), when called from 
any Tomcat threadpool thread (I think this could be done by 
ClassLoader), uses, as its secret sauce, a ThreadLocal 
PersistenceManager that comes from the "persistence-unit1" PMF 
configuration.

You could take the approach of adding, e.g., javax.jdo.ThreadLocal=true 
to the PMF properties, but I think that unnecessarily mixes the data 
access configuration with the application environment's usage of that 
configuration.

So --

I like the ability to have a ThreadLocal PM setup.  But it seems like we 
could do more here than just enshrine that one pattern.
I like the ability to use PersistenceUnitNames to look up PMFs.  I think 
this should be available regardless of the proxy scenario, via 
JDOHelper.getNamedPersistenceManagerFactory(String name) (or possibly 
overriding the semantics of getPersistenceManagerFactory(String) -- have 
to think about that).  The requirement is that when loading a PMF, it is 
interrogated for its name and registered in a hash on JDOHelper.

It's possible I've completely jumped the shark here, and if so I 
apologize and await the hail of bullets, but I hope I may provoke some 
interesting discussion.

Thoughts?

Wes

Craig L Russell wrote:

> 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