|
From: Juergen H. <ju...@in...> - 2005-06-21 21:34:18
|
Sounds plausible - thanks for tracking this down. Please do create a =
JIRA
issue for this; I'll fix the issue for Spring 1.2.2.
Essentially, SpringSessionSynchronization needs to keep a marker that it =
has
already removed the current Session from the thread, and suppress =
suspend
and resume accordingly. It could simply hold a boolean flag as instance
variable for this.
Juergen
-----Urspr=FCngliche Nachricht-----
Von: spr...@li...
[mailto:spr...@li...] Im =
Auftrag
von Andy Depue
Gesendet: Dienstag, 21. Juni 2005 23:27
An: spr...@li...
Betreff: Re: [Springframework-developer] Problems with advanced =
transaction
synchronization
As I track this problem further, I see that it lies Hibernate3's=20
SessionFactoryUtils. SessionFactoryUtils has an inner class,=20
"SpringSessionSynchronization", that is instantiated and registered =
against=20
the current transaction when using Spring for session management. =
During=20
transaction suspend and resume, this implementation will *always* call=20
TransactionSynchronizationManager.unbindResource(this.sessionFactory) =
and=20
TransactionSynchronizationManager.bindResource(this.sessionFactory,=20
this.sessionHolder), respectively. When Spring performs a commit, it =
calls=20
synchronization methods in this order:
1. beforeCommit
2. beforeCompletion
3. afterCompletion
In beforeCompletion, SpringSessionSynchronization will=20
unbindResource(this.sessionFactory), and sometimes close the Hibernate=20
Session. However, SpringSessionSynchronization will not reflect this in =
its
internal state in any way. Now imagine that a =
TransactionSynchronization=20
implementation suspends the transaction in afterCompletion. =20
SessionFactoryUtils.SpringSessionSynchronization will have its suspend
method=20
called, which will attempt to unbindResource(this.sessionFactory), =
causing
an=20
exception since it has already been unbound. Moreover, even if it =
performed
a check and did not unbind the resource, resume() would still attempt to =
rebind the resource (whose Hibernate Session was most likely closed in=20
beforeCompletion), leaving that closed resource bound to the current =
thread=20
even after the main transaction has been committed.
Basically, SpringSessionSynchronization needs to be modified to handle =
this=20
call sequence:
1. beforeCommit
2. beforeCompletion
3. suspend
4. resume
5. afterCompletion
Which it does not now support (though this was working in older versions =
of=20
Spring). I'm willing to open a JIRA issue, make these changes, and =
submit a
patch if no one has a problem with them.
- Andy
On Monday 20 June 2005 03:28 pm, Andy Depue wrote:
> I'm attempting to do some advanced transaction synchronization. =
During
> synchronization, I need to update a status row in a DB table. Of =
course,
> since DB access is itself transactional, I create a new transaction =
for
the
> duration of the update using PROPAGATION_REQUIRES_NEW. The problem =
occurs
> when I attempt to execute this in "afterCompletion". I sometimes get =
this
> exception:
> java.lang.IllegalStateException: No value for key
> [org.hibernate.impl.SessionFactoryImpl@1f37bf1] bound to thread =
[Timer-3]
>
> Here is an abbreviated version of my code:
>
> ------------
> TransactionSynchronizationManager.registerSynchronization(new
> TransactionSynchronization() {
>
> public void suspend() { }
> public void resume() { }
> public void beforeCommit(boolean readOnly)
> {
> getTransactionTemplate().execute(new
> TransactionCallbackWithoutResult() {
> protected void doInTransactionWithoutResult(final
> TransactionStatus status) {
> update("update m_t set trans_time=3Dnull where =
trans_id=3D?",
> new Object[] { transId });
> }
> });
> }
> public void beforeCompletion() { }
> public void afterCompletion(final int status) {
> getTransactionTemplate().execute(new
> TransactionCallbackWithoutResult() {
> protected void doInTransactionWithoutResult(final
> TransactionStatus ts) {
> if(status =3D=3D STATUS_ROLLED_BACK) {
> update("update m_t set s_last=3Dtrans_s_start, =
trans_id=3Dnull,
> trans_time=3Dnull where trans_id=3D?",
> new Object[] { transId} );
> } else {
> update("update m_t set trans_id=3Dnull, =
trans_time=3Dnull,
> trans_s_start=3Dnull where trans_id=3D?",
> new Object[] { transId });
> }
> }
> });
> }
> });
> ---------------
>
> The TransactionTemplate returned from getTransactionTemplate() was =
created
> like this:
> transactionTemplate =3D new =
TransactionTemplate(transactionManager);
> =20
>
transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGAT=
IO
>N_REQUIRES_NEW);
> transactionTemplate.setTimeout(getTransactionTimeoutInMs());
> transactionTemplate.setReadOnly(false);
>
>
> My question is, should I be able to do this? The exception is not =
thrown
> in many cases - however, in this particular case, an exception was =
thrown
> via other code in the context of the main transaction, though it did =
not
> cause a rollback to occur, so the transaction was in the process of =
being
> committed - and while committing the main transaction, the process of
> starting a new transaction caused this related exception to be thrown.
> This is against Spring 1.2.1.
>
> - Andy
>
> PS. Here is a full stack trace, for what its worth:
> java.lang.IllegalStateException: No value for key
> [org.hibernate.impl.SessionFactoryImpl@1f37bf1] bound to thread =
[Timer-3]
> at
>
org.springframework.transaction.support.TransactionSynchronizationManager=
.u
>nbindResource(TransactionSynchronizationManager.java:175) at
>
org.springframework.orm.hibernate3.SessionFactoryUtils$SpringSessionSynch=
ro
>nization.suspend(SessionFactoryUtils.java:846) at
>
org.springframework.transaction.support.AbstractPlatformTransactionManage=
r.
>suspend(AbstractPlatformTransactionManager.java:350) at
>
org.springframework.transaction.support.AbstractPlatformTransactionManage=
r.
>getExistingTransaction(AbstractPlatformTransactionManager.java:271) at
>
org.springframework.transaction.support.AbstractPlatformTransactionManage=
r.
>getTransaction(AbstractPlatformTransactionManager.java:215) at
>
org.springframework.transaction.support.TransactionTemplate.execute(Trans=
ac
>tionTemplate.java:111) at
> com.marathon.service.dao.jdbc.PSDAO$2.afterCompletion(PSDAO.java:185) =
at
>
org.springframework.transaction.support.AbstractPlatformTransactionManage=
r.
>triggerAfterCompletion(AbstractPlatformTransactionManager.java:610) at
>
org.springframework.transaction.support.AbstractPlatformTransactionManage=
r.
>commit(AbstractPlatformTransactionManager.java:467) at
>
org.springframework.transaction.interceptor.TransactionAspectSupport.doCl=
os
>eTransactionAfterThrowing(TransactionAspectSupport.java:294) at
>
org.springframework.transaction.interceptor.TransactionInterceptor.invoke=
(T
>ransactionInterceptor.java:61) at
>
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(Refl=
ec
>tiveMethodInvocation.java:144) at
>
net.sf.acegisecurity.intercept.method.aopalliance.MethodSecurityIntercept=
or
>.invoke(MethodSecurityInterceptor.java:80) at
>
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(Refl=
ec
>tiveMethodInvocation.java:144) at
>
org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAop=
Pr
>oxy.java:174) at $Proxy58.postApproved(Unknown Source)
>
>
> -------------------------------------------------------
> SF.Net email is sponsored by: Discover Easy Linux Migration Strategies
> from IBM. Find simple to follow Roadmaps, straightforward articles,
> informative Webcasts and more! Get everything you need to get up to
> speed, fast. =
http://ads.osdn.com/?ad_id=3D7477&alloc_id=3D16492&op=3Dclick
> _______________________________________________
> Springframework-developer mailing list
> Spr...@li...
> https://lists.sourceforge.net/lists/listinfo/springframework-developer
-------------------------------------------------------
SF.Net email is sponsored by: Discover Easy Linux Migration Strategies
from IBM. Find simple to follow Roadmaps, straightforward articles,
informative Webcasts and more! Get everything you need to get up to
speed, fast. =
http://ads.osdn.com/?ad_id=3D7477&alloc_id=3D16492&op=3Dclick
_______________________________________________
Springframework-developer mailing list
Spr...@li...
https://lists.sourceforge.net/lists/listinfo/springframework-developer
|