@@ -361,23 +361,31 @@ else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATIO
361361 definition .getPropagationBehavior () == TransactionDefinition .PROPAGATION_REQUIRES_NEW ||
362362 definition .getPropagationBehavior () == TransactionDefinition .PROPAGATION_NESTED ) {
363363 SuspendedResourcesHolder suspendedResources = suspend (null );
364- if (debugEnabled ) {
365- logger .debug ("Creating new transaction with name [" + definition .getName () + "]: " + definition );
366- }
364+ DefaultTransactionStatus status = null ;
367365 try {
366+ if (debugEnabled ) {
367+ logger .debug ("Creating new transaction with name [" + definition .getName () + "]: " + definition );
368+ }
369+ boolean newSynchronization = (getTransactionSynchronization () != SYNCHRONIZATION_NEVER );
370+ status = newTransactionStatus (
371+ definition , transaction , true , newSynchronization , debugEnabled , suspendedResources );
368372 doBegin (transaction , definition );
373+ return status ;
369374 }
370375 catch (RuntimeException ex ) {
376+ if (status != null && status .isNewSynchronization ()) {
377+ TransactionSynchronizationManager .clear ();
378+ }
371379 resume (null , suspendedResources );
372380 throw ex ;
373381 }
374382 catch (Error err ) {
383+ if (status != null && status .isNewSynchronization ()) {
384+ TransactionSynchronizationManager .clear ();
385+ }
375386 resume (null , suspendedResources );
376387 throw err ;
377388 }
378- boolean newSynchronization = (getTransactionSynchronization () != SYNCHRONIZATION_NEVER );
379- return newTransactionStatus (
380- definition , transaction , true , newSynchronization , debugEnabled , suspendedResources );
381389 }
382390 else {
383391 // Create "empty" transaction: no actual transaction, but potentially synchronization.
@@ -414,20 +422,28 @@ private TransactionStatus handleExistingTransaction(
414422 definition .getName () + "]" );
415423 }
416424 SuspendedResourcesHolder suspendedResources = suspend (transaction );
425+ DefaultTransactionStatus status = null ;
417426 try {
427+ boolean newSynchronization = (getTransactionSynchronization () != SYNCHRONIZATION_NEVER );
428+ status = newTransactionStatus (
429+ definition , transaction , true , newSynchronization , debugEnabled , suspendedResources );
418430 doBegin (transaction , definition );
431+ return status ;
419432 }
420433 catch (RuntimeException beginEx ) {
434+ if (status != null && status .isNewSynchronization ()) {
435+ TransactionSynchronizationManager .clear ();
436+ }
421437 resumeAfterBeginException (transaction , suspendedResources , beginEx );
422438 throw beginEx ;
423439 }
424440 catch (Error beginErr ) {
441+ if (status != null && status .isNewSynchronization ()) {
442+ TransactionSynchronizationManager .clear ();
443+ }
425444 resumeAfterBeginException (transaction , suspendedResources , beginErr );
426445 throw beginErr ;
427446 }
428- boolean newSynchronization = (getTransactionSynchronization () != SYNCHRONIZATION_NEVER );
429- return newTransactionStatus (
430- definition , transaction , true , newSynchronization , debugEnabled , suspendedResources );
431447 }
432448
433449 if (definition .getPropagationBehavior () == TransactionDefinition .PROPAGATION_NESTED ) {
@@ -452,9 +468,25 @@ private TransactionStatus handleExistingTransaction(
452468 // Nested transaction through nested begin and commit/rollback calls.
453469 // Usually only for JTA: Spring synchronization might get activated here
454470 // in case of a pre-existing JTA transaction.
455- doBegin (transaction , definition );
456471 boolean newSynchronization = (getTransactionSynchronization () != SYNCHRONIZATION_NEVER );
457- return newTransactionStatus (definition , transaction , true , newSynchronization , debugEnabled , null );
472+ DefaultTransactionStatus status = newTransactionStatus (
473+ definition , transaction , true , newSynchronization , debugEnabled , null );
474+ try {
475+ doBegin (transaction , definition );
476+ }
477+ catch (RuntimeException beginEx ) {
478+ if (status != null && status .isNewSynchronization ()) {
479+ TransactionSynchronizationManager .clear ();
480+ }
481+ throw beginEx ;
482+ }
483+ catch (Error beginErr ) {
484+ if (status != null && status .isNewSynchronization ()) {
485+ TransactionSynchronizationManager .clear ();
486+ }
487+ throw beginErr ;
488+ }
489+ return status ;
458490 }
459491 }
460492
@@ -495,18 +527,27 @@ protected DefaultTransactionStatus newTransactionStatus(
495527
496528 boolean actualNewSynchronization = newSynchronization &&
497529 !TransactionSynchronizationManager .isSynchronizationActive ();
498- if (actualNewSynchronization ) {
499- TransactionSynchronizationManager .setActualTransactionActive (transaction != null );
500- TransactionSynchronizationManager .setCurrentTransactionIsolationLevel (
501- (definition .getIsolationLevel () != TransactionDefinition .ISOLATION_DEFAULT ) ?
502- definition .getIsolationLevel () : null );
503- TransactionSynchronizationManager .setCurrentTransactionReadOnly (definition .isReadOnly ());
504- TransactionSynchronizationManager .setCurrentTransactionName (definition .getName ());
505- TransactionSynchronizationManager .initSynchronization ();
530+ try {
531+ if (actualNewSynchronization ) {
532+ TransactionSynchronizationManager .setActualTransactionActive (transaction != null );
533+ TransactionSynchronizationManager .setCurrentTransactionIsolationLevel (
534+ (definition .getIsolationLevel () != TransactionDefinition .ISOLATION_DEFAULT ) ?
535+ definition .getIsolationLevel () : null );
536+ TransactionSynchronizationManager .setCurrentTransactionReadOnly (definition .isReadOnly ());
537+ TransactionSynchronizationManager .setCurrentTransactionName (definition .getName ());
538+ TransactionSynchronizationManager .initSynchronization ();
539+ }
540+ return new DefaultTransactionStatus (
541+ transaction , newTransaction , actualNewSynchronization ,
542+ definition .isReadOnly (), debug , suspendedResources );
543+ }
544+ catch (Error err ) {
545+ // Can only really be an OutOfMemoryError...
546+ if (actualNewSynchronization ) {
547+ TransactionSynchronizationManager .clear ();
548+ }
549+ throw err ;
506550 }
507- return new DefaultTransactionStatus (
508- transaction , newTransaction , actualNewSynchronization ,
509- definition .isReadOnly (), debug , suspendedResources );
510551 }
511552
512553 /**
@@ -984,7 +1025,7 @@ private void cleanupAfterCompletion(DefaultTransactionStatus status) {
9841025 }
9851026 if (status .getSuspendedResources () != null ) {
9861027 if (status .isDebug ()) {
987- logger .debug ("Resuming suspended transaction" );
1028+ logger .debug ("Resuming suspended transaction after completion of inner transaction " );
9881029 }
9891030 resume (status .getTransaction (), (SuspendedResourcesHolder ) status .getSuspendedResources ());
9901031 }
@@ -1076,7 +1117,7 @@ protected boolean useSavepointForNestedTransaction() {
10761117 * @throws TransactionException in case of creation or system errors
10771118 */
10781119 protected abstract void doBegin (Object transaction , TransactionDefinition definition )
1079- throws TransactionException ;
1120+ throws TransactionException ;
10801121
10811122 /**
10821123 * Suspend the resources of the current transaction.
0 commit comments