|
From: Colin S. <col...@ex...> - 2004-03-25 20:09:09
|
We're on slightly different pages though. In my case, I am actually not=20
using TransactionManagerLookup... But in my case, because of the=20
exception in the flush in beforeCommit(), beforeCompletion() never gets=20
called (as it would normally). Now I do see that afterCompletion is also=20
supposed to call closeSessionIfNecessary() (I had actually missed this=20
before), but in my case, it's not getting there. I haven't traced it in=20
a debugger, which is what I will do now, as it seems to me it should get=20
to that code, certainly I do have a
"Triggering afterCompletion synchronization"
in the log which should happen right before afterCompletion() is called.
The other question is whether beforeCompletion still shouldn't be called=20
in any case even if beforeCommit fails. Ultimately, we are still before=20
completion of the transaction, unless you meant it to be only called in=20
the case of no failure.
Colin
j=FCrgen h=F6ller [werk3AT] wrote:
>Colin,
>=20
>Thanks for tracking this down. It's actually a problem with SessionFacto=
ryUtils' inner class SessionSynchronization: It assumes that beforeComple=
tion is called in any case, even if beforeCommit has thrown an exception.=
However, this just applies if you specified a TransactionManagerLookup i=
n the Hibernate configuration; else, afterCompletion will do the cleanup =
- which will be called in any case.
>=20
>When you remove the Hibernate TransactionManagerLookup, you shouldn't fa=
ce the issue - the bug doesn't have any effects then. Note that you don't=
need that TransactionManagerLookup when using Spring's JtaTransactionMan=
ager, as Spring will properly apply cache callbacks anyway. A Transaction=
ManagerLookup just adds value when used with EJB CMT or manual JTA, for u=
ltra-correct cache callbacks.
>=20
>So essentially, everything should be fine if using HibernateTransactionM=
anager, or JtaTransactionManager without a Hibernate TransactionManagerLo=
okup. This is clearly something to fix, but I guess we don't need to do a=
n immediate 1.0.1 followup release; I'd like to gather further bug report=
s first. For the time being, let's suggest to remove the TransactionManag=
erLookup from the Hibernate configuration.
>=20
>Juergen
>=20
>
>________________________________
>
>Von: Colin Sampaleanu [mailto:col...@ex...]
>Gesendet: Do 25.03.2004 20:32
>An: spr...@li...; j=FCrgen h=F6ller [=
werk3AT]
>Betreff: Re: [Springframework-developer] Hibernate resource management i=
ssue
>
>
>
>Juergen,
>
>I am almost 100% sure this block of code from
>AbstractPlatformTransactionManager is wrong:
> else {
> try {
> try {
> triggerBeforeCommit(defStatus);
> triggerBeforeCompletion(defStatus);
> if (status.isNewTransaction()) {
> logger.info("Initiating transaction commit");
> doCommit(defStatus);
> }
> }
> catch (UnexpectedRollbackException ex) {
> triggerAfterCompletion(defStatus,
>TransactionSynchronization.STATUS_ROLLED_BACK, ex);
> throw ex;
> }
> catch (TransactionException ex) {
> if (this.rollbackOnCommitFailure) {
> doRollbackOnCommitException(defStatus, ex);
> triggerAfterCompletion(defStatus,
>TransactionSynchronization.STATUS_ROLLED_BACK, ex);
> }
> else {
> triggerAfterCompletion(defStatus,
>TransactionSynchronization.STATUS_UNKNOWN, ex);
> }
> throw ex;
> }
> catch (RuntimeException ex) {
> doRollbackOnCommitException(defStatus, ex);
> triggerAfterCompletion(defStatus,
>TransactionSynchronization.STATUS_ROLLED_BACK, ex);
> throw ex;
> }
> catch (Error err) {
> doRollbackOnCommitException(defStatus, err);
> triggerAfterCompletion(defStatus,
>TransactionSynchronization.STATUS_UNKNOWN, err);
> throw err;
> }
> triggerAfterCompletion(defStatus,
>TransactionSynchronization.STATUS_COMMITTED, null);
> }
> finally {
> cleanupAfterCompletion(defStatus);
> }
> }
>
>triggerBeforeCommit() execute, which in the Hibernate case will force a
>flush. However, if that flush throws an exception, then
> triggerBeforeCompletion(defStatus);
>never gets called. However, triggerBeforeCompletion is what is actually
>supposed to release the Hibernate session holder from the current
>thread! So in this case, the session (which is totally hosed of course),
>gets left on the thread. I believe in some environments this wouldn't
>matter that much, as the threads don't get resused. In the JBoss case,
>new requests coming in will get the existing thread, and this time,
>SessionFactoryUtils will see the session is there, and try to use it.
>Bang, it all blows up...
>
>So for this code to work properly, what needs to happen is that
>triggerBeforeCompletion still needs to be called even if
>triggerBeforeCommit fails. While I am ok with writing the code in this
>method to handle this, I am not 100% sure this is safe in terms of all
>the other interactions that will happen as a result; mot of this code is
>your baby with me only having traced through it once in a while. So if
>you would prefer to resolve this that would be great.
>
>Unless I am mistaken about this bug, I think it is a pretty serious one,
>and warrants an almost immediate release of a v1.0.1 of Spring...
>
>Regards,
>Colin
>
>
>Colin Sampaleanu wrote:
>
> =20
>
>>I am tracking down a possible Hibernate resource management issue.
>>
>>In a running app, some time yesterday, some code, running in a wrapped
>>transaction with Hibernate handling ORM, encountered an Oracle
>>constraint violation and threw an exception. Fine...
>>
>>But when I log into the app myself now via the web ui and then it gets
>>a service object to read some data, the service object is wrapped with
>>a transaction interceptor, and also a hibernate interceptor. The
>>Hibernate interceptor is already seeing a Hibernate Session existing
>>on the current thread, so it is not creating a new one. Then at the
>>end of the transaction, when the Hibernate session is attempted to be
>>flushed, Hibernate tries to write out the old bad data from yesterday.
>>
>>What this essentially means is that when the error from yesterday
>>happened, the session did not get released from the thread, and has
>>been sticking around all this time. When I came via struts, I was
>>given the same thread as yesterday by the appserver, and the old
>>invalid session was still on it. The problem is not that it's reusing
>>that session, but why it was ever left that the day before.
>>
>>Will try to duplicate this...
>> =20
>>
>
>
>
>
> =20
>
|