|
Home > Archive > Apache JDO Project > October 2006 > Proposal for new method (long)
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
Proposal for new method (long)
|
|
| Craig L Russell 2006-10-09, 1:11 pm |
| | |
| Erik Bengtson 2006-10-09, 7:11 pm |
| what if two PMFs have txs on the same thread?
Could the persistent-unit from JPA concept be applied?
like:
JDOHelper.getPersistenceManager("persistent-unit1")
JDOHelper.getPersistenceManager("persistent-unit2")
Quoting Craig L Russell <Craig.Russell@sun.com>:
> 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!
>
>
| |
| Craig L Russell 2006-10-09, 7:11 pm |
| | |
| Ilan Kirsh 2006-10-09, 7:11 pm |
| Hi Craig,
This proposal reminds me the proxy EntityManagers that a Java EE 5 container can use, which mean that my post yesterday regarding automatic injection of JEntityManager was probably too naive. Maybe the new proxy PersistenceManager can also help somehow in injection of a PersistenceManager in a Java EE 5 container? Also, it might make sense to implement such a proxy (or most of its activity) on the JDO side rather than by every implementation (I guess that at least other vendors may agree with that). Therefore the right location for a new method might be in JDOHelper.
Regards,
Ilan
----- Original Message -----
From: Craig L Russell
To: Apache JDO project ; JDO Expert Group
Sent: Monday, October 09, 2006 7:58 PM
Subject: Proposal for new method (long)
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!
| |
| Wes Biggs 2006-10-11, 1:11 pm |
| 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!
>
>
| |
| Geoff hendrey 2006-10-11, 7:11 pm |
| How do we deal with the fact that any components stored in a Page state (wi=
cket/tapestry lingo) need to be serializable?=0A=0AIn the case of wicket, P=
age is serialized all the time, not just when clustering is applies. The pa=
ges are serialized and deserialized in order to minimize the memory footpri=
nt of an application when there are lots of concurrent sessions. You can't =
put ANYTHING into the Servlet session, or any page state variable, in any r=
eal application, that isn't serializable. If you do, you are back to the "s=
odding" solutions of proxies, activation/passivation-type callbacks, hell-o=
n-earth-bad-programming-paradigms.=0A=0AIn Shades, I've addressed this by m=
aking the DatabaseSession (equivalent to PM) serializable. This is possible=
because the DatabaseSession does not hang on to connections. =0A=0AAlso, I=
mentioned a long time ago that users WOULD want to keep a PersistenceManag=
er-per-session, and I recall postings on JDO central where users asked for =
it. There seemed to be very little support for this idea. I'm following thi=
s thread somewhat loosly, but are we now saying PM-per-session is a valid p=
attern that we want to support? At the time I proposed this, detachment was=
the prefered alternative. (I continiue to believe detachment is an anti-pa=
ttern that arrises because of the non-serializability problem of the PM, an=
d in situations where the web programming model is fundamentally broken ...=
E.G Struts).=0A=0AOK, I've stirred the pot a bit. :-) don't take it the wr=
ong way.=0A=0A-geoff =0A=0A=0A=0A=0A=0A=0A----- Original Message ----=0AFro=
m: Wes Biggs <wes@tralfamadore.com>=0ATo: Craig L Russell <Craig.Russell@su=
n.com>=0ACc: JDO Experts Group <jdo-experts-ext@sun.com>; Apache JDO projec=
t <jdo-dev@db.apache.org>=0ASent: Wednesday, October 11, 2006 5:42:24 AM=0A=
Subject: Re: Proposal for new method (long)=0A=0ACraig,=0A=0AI've used this=
approach myself, and found it to generally improve =0Aproductivity in web =
application development.=0A=0AHowever, I would question whether enshrining =
it in the API is really =0Athat valuable. There are definite limitations t=
o the usefulness of a =0AThreadLocal PM, from the obvious one of not being =
able to easily share =0Ait in threaded subtasks (producer-consumer, for exa=
mple, or other =0Ascenarios where a web request initiates an asynchronous a=
ction), to the =0Alack of ability to control PM lifecycle (from a user pers=
pective) and =0Athe lack of ability to optimize PM reuse and caching (from =
a provider =0Aperspective). ThreadLocals are also notoriously difficult to=
debug, =0Aparticularly in the area of memory leaks. Undoubtedly there are=
=0Atechniques to get around all of those, but let's just say it's not a =
=0Asilver bullet.=0A=0AApart from the J2EE integration scenario, it's trivi=
ally easy for the =0Auser (or a web framework component) to create a Thread=
Local PM helper =0Amethod; the API is public (unlike most JDOHelper methods=
, which rely on =0A"hidden methods" and an SPI layer).=0A=0ANow, with that =
all said, I support anything that helps get us closer to =0Atruly transpare=
nt persistence, which I define as "not having to worry =0Aabout the sodding=
PMF or PM". What I'd really like to see is a =0Aconfiguration/injection m=
ethod (per environment -- SE and EE) that makes =0Ait as trivial as possibl=
e to get a PM and start doing some real work. =0AAt the most (and overly) =
basic level, this becomes =0APersistenceManager.getInstance(), and the envi=
ronment is responsible for =0Adetermining exactly where the instance comes =
from. In this context, =0AThreadLocal is a particular configuration strate=
gy that may suit some =0Aapplications.=0A=0AThe persistence unit concept --=
or for our purposes, named PMFs -- is a =0Auseful bridge between configuri=
ng the environment (runtime) and =0Aconfiguring the application (design tim=
e). For example, I might want to =0Aconfigure the environment such that PM=
..getInstance(), when called from =0Aany Tomcat threadpool thread (I think t=
his could be done by =0AClassLoader), uses, as its secret sauce, a ThreadLo=
cal =0APersistenceManager that comes from the "persistence-unit1" PMF =0Aco=
nfiguration.=0A=0AYou could take the approach of adding, e.g., javax.jdo.Th=
readLocal=3Dtrue =0Ato the PMF properties, but I think that unnecessarily m=
ixes the data =0Aaccess configuration with the application environment's us=
age of that =0Aconfiguration.=0A=0ASo --=0A=0AI like the ability to have a =
ThreadLocal PM setup. But it seems like we =0Acould do more here than just=
enshrine that one pattern.=0AI like the ability to use PersistenceUnitName=
s to look up PMFs. I think =0Athis should be available regardless of the p=
roxy scenario, via =0AJDOHelper. getNamedPersistenceManagerFactory(String
na=
me) (or possibly =0Aoverriding the semantics of getPersistenceManagerFactor=
y(String) -- have =0Ato think about that). The requirement is that when lo=
ading a PMF, it is =0Ainterrogated for its name and registered in a hash on=
JDOHelper.=0A=0AIt's possible I've completely jumped the shark here, and i=
f so I =0Aapologize and await the hail of bullets, but I hope I may provoke=
some =0Ainteresting discussion.=0A=0AThoughts?=0A=0AWes=0A=0ACraig L Russe=
ll wrote:=0A=0A> Javadogs,=0A>=0A> I'd like to propose a solution to a prob=
lem that we have with =0A> usability in the web tier. When using a servlet,=
each method that =0A> needs access to a PersistenceManager needs to figure=
out where the =0A> current PersistenceManager is, and if it is even active=
.. There are =0A> many ways around this issue, but they are not general. Amo=
ng the =0A> workarounds are putting the active PersistenceManager into the =
servlet =0A> context as a request or session attribute, passing the =0A> Pe=
rsistenceManager explicitly as a parameter, and putting the =0A> Persistenc=
eManager into a ThreadLocal field. =0A>=0A> Of these workarounds, the one w=
ith the most appeal is the ThreadLocal =0A> solution. So I'd like to propos=
e that we formalize this by adding a =0A> method to return a thread-safe Pe=
rsistenceManager proxy associated =0A> with a PersistenceManagerFactory tha=
t can be implemented as a =0A> singleton, stored in a component's static fi=
eld, and that dynamically =0A> binds to the PersistenceManager that is curr=
ently active on the thread.=0A>=0A> Multiple PersistenceManager proxies can=
be active, each with its own =0A> binding to a (possibly different) Persis=
tenceManagerFactory.=0A>=0A> The benefit of this proposal is ease of use fo=
r web and ejb components =0A> that currently have to manage their own Persi=
stenceManager resources. =0A> Instead of having to look up and store a Pers=
istenceManager in each =0A> method of each component that needs one, lookin=
g up the =0A> PersistenceManagerFactory can be done once during initializat=
ion of =0A> the component.=0A>=0A> The limitations of the proposal is that =
in environments that do not =0A> support Java EE 5 TransactionSynchronizati=
onRegistry (i.e. J2SE =0A> servers and Java SE), only one PersistenceManage=
r per =0A> PersistenceManagerFactory can be used per thread (which maps to =
a =0A> single web request), and only one transaction can be used per =0A> P=
ersistenceManager.=0A>=0A> In environments that support Java EE 5 =0A> Tran=
sactionSynchronizationRegistry, container-managed transactions can =0A> be =
used, including the ability to suspend transactions. =0A>=0A> If used in an=
environment that does not support Java EE 5 =0A> TransactionSynchronizatio=
nRegistry, the behavior is as follows:=0A>=0A> The first component to use a=
PersistenceManager method on a thread =0A> would get a PersistenceManager =
from the factory. Subsequent callers =0A> would use the same PersistenceMan=
ager delegate until the transaction =0A> completed, at which time the Persi=
stenceManager is cleared and the =0A> first subsequent request would create=
a new one.=0A>=0A> Implementation: The proxy would delegate most methods t=
o the current =0A> PersistenceManager, as determined by the ThreadLocal fie=
ld being =0A> non-null. Calling close() would have no effect. If the Thread=
Local =0A> field is null, then getPersistenceManager() would be called on t=
he =0A> PersistenceManagerFactory. A synchronization instance would be crea=
ted =0A> and registered with the currentTransaction of the newly acquired =
=0A> PersistenceManager, the PersistenceManager would be set into the =0A> =
ThreadLocal, and then the request wold be delegated to the new =0A> Persist=
enceManager. At afterCompletion, the ThreadLocal would be =0A> nullified.=
=0A>=0A> If used in an environment that supports Java EE =0A> 5 Transaction=
SynchronizationRegistry, the behavior is as follows:=0A>=0A> The first comp=
onent to use a PersistenceManager method in a managed =0A> transaction woul=
d get a PersistenceManager from the factory. =0A> Subsequent callers in the=
same transaction would use the same =0A> PersistenceManager delegate until=
the transaction completed, at which =0A> time the PersistenceManager is cl=
eared and the first request in a new =0A> transaction would create a new on=
e.=0A>=0A> Implementation: The proxy would delegate most methods to the cur=
rent =0A> PersistenceManager, as determined by =0A> the TransactionSynchron=
izationRegistry entry for the =0A> PersistenceManagerFactory being non-null=
.. Calling close() would have =0A> no effect. If the TransactionSynchronizat=
ionRegistry entry for the =0A> PersistenceManagerFactory is null, then getP=
ersistenceManager() would =0A> be called on the PersistenceManagerFactory. =
An interposed =0A> synchronization instance would be created and registered=
with =0A> the TransactionSynchronizationRegistry, the PersistenceManager w=
ould =0A> be set into the TransactionSynchronizationRegistry entry for the =
=0A> PersistenceManagerFactory, and then the request wold be delegated to =
=0A> the new PersistenceManager. At afterCompletion, =0A> the TransactionSy=
nchronizationRegistry entry for the =0A> PersistenceManagerFactory would be=
nullified.=0A>=0A> If we agree on the semantics of this behavior, the meth=
od can be =0A> implemented as a helper method of JDOHelper, PersistenceMana=
ger =0A> getPersistenceManagerProxy or something like it (suggestions welco=
me).=0A>=0A> To support container-managed transactions in J2EE servers (1.4=
and =0A> earlier), we would have to put the method on PersistenceManagerFa=
ctory =0A> and allow the implementation to use its own secret sauce to prov=
ide =0A> the proper semantics. If the jdo implementation chose, it could si=
mply =0A> delegate to the JDOHelper version of the method, with the limitat=
ions =0A> therein.=0A>=0A> Craig=0A>=0A> Craig Russell=0A>=0A> Architect, S=
un Java Enterprise System http://java.sun.com/products/jdo=0A>=0A> 408 276-=
5638 mailto:Craig.Russell@sun.com=0A>=0A> P.S. A good JDO? O, Gasp!=0A>=0A>=
=0A=0A=0A=0A
| |
| Craig L Russell 2006-10-11, 7:11 pm |
| | |
| David Bullock 2006-10-12, 7:11 pm |
| On 10/10/06, Craig L Russell <Craig.Russell@sun.com > wrote:
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.
>
One issue that I can see with this is that servlet engines are nowhere
forced to use thread-per-request designs (unless that is something new in
JavaEE 5). While this design is admittedly common, its days are few. Take
a quick look at Greg Wilkins' writeup of Jetty 6's support for
'continuations' - http://docs.codehaus.org/display/JETTY/Continuations - to
get a feel for where application servers are headed, especially as so-called
'AJAX' becomes more common (and super-threaded CPU's rush to the scene).
The correct approach to acquiring a PM in web-components is to associate it
with the HttpServletRequest object. This can be done easily in the
ServletRequestListener.requestInitialised() method as follows:
public class PMManager implements ServletRequestListener {
public void requestInitialized(ServletRequestEvent e) {
e.getRequest().setAttribute(PM_ATTR, getFreshPm());
}
public void requestDestroyed(ServletRequestEvent e) {
PersistenceManager pm = acquire(e.getRequest());
// close it, etc.
}
public static PersistenceManager acquire(HttpServletRequest req) {
return req.getAtrribute(PM_ATTR);
}
}
.... notice how web-component code can simply:
PMManager.acquire(req);
to get the PM.
That isn't to say that acquiring a thread-local PM proxy might not be a
useful feature. I just wouldn't push it as a best-practice in
web-applications.
IMHO,
David Bullock.
|
|
|
|
|