From 175714046a996d075ae4b16409c574dc4c9b1395 Mon Sep 17 00:00:00 2001 From: Rob Bygrave Date: Fri, 9 Feb 2018 23:03:07 +1300 Subject: [PATCH] #1254 - SpringJdbcTransactionManager inifinite recursion #1254 Yeah, nah. This is the real fix. Expose: SpiTransaction TransctionManager.getInScope(); ... and have ebean-spring-txn SpringJdbcTransactionManager call it instead of getActive(). --- .../api/SpiTransactionManager.java | 2 +- .../server/core/DefaultServer.java | 8 +++---- .../DefaultTransactionScopeManager.java | 4 ++-- .../ExternalTransactionScopeManager.java | 6 +++++ .../transaction/TransactionManager.java | 24 +++++++++---------- .../transaction/TransactionScopeManager.java | 8 +++---- 6 files changed, 29 insertions(+), 23 deletions(-) diff --git a/src/main/java/io/ebeaninternal/api/SpiTransactionManager.java b/src/main/java/io/ebeaninternal/api/SpiTransactionManager.java index e914d200e..d08e5aa2b 100644 --- a/src/main/java/io/ebeaninternal/api/SpiTransactionManager.java +++ b/src/main/java/io/ebeaninternal/api/SpiTransactionManager.java @@ -22,7 +22,7 @@ public interface SpiTransactionManager { /** * Return the currently active transaction (can be null). */ - SpiTransaction get(); + SpiTransaction getActive(); /** * Push an externally managed transaction into scope (e.g. Spring managed transaction). diff --git a/src/main/java/io/ebeaninternal/server/core/DefaultServer.java b/src/main/java/io/ebeaninternal/server/core/DefaultServer.java index 2c3c21d48..1fce54334 100644 --- a/src/main/java/io/ebeaninternal/server/core/DefaultServer.java +++ b/src/main/java/io/ebeaninternal/server/core/DefaultServer.java @@ -613,7 +613,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer { id = desc.convertId(id); PersistenceContext pc = null; - SpiTransaction t = transactionManager.get(); + SpiTransaction t = transactionManager.getActive(); if (t != null) { pc = t.getPersistenceContext(); Object existing = desc.contextGet(pc, id); @@ -725,7 +725,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer { */ @Override public SpiTransaction currentServerTransaction() { - return transactionManager.get(); + return transactionManager.getActive(); } /** @@ -773,7 +773,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer { */ @Override public Transaction currentTransaction() { - return transactionManager.get(); + return transactionManager.getActive(); } @Override @@ -2035,7 +2035,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer { if (t != null) { return new ObtainedTransaction((SpiTransaction) t); } - SpiTransaction trans = transactionManager.get(); + SpiTransaction trans = transactionManager.getActive(); if (trans != null) { return new ObtainedTransaction(trans); } diff --git a/src/main/java/io/ebeaninternal/server/transaction/DefaultTransactionScopeManager.java b/src/main/java/io/ebeaninternal/server/transaction/DefaultTransactionScopeManager.java index 0d54b9b22..0f376b3cb 100644 --- a/src/main/java/io/ebeaninternal/server/transaction/DefaultTransactionScopeManager.java +++ b/src/main/java/io/ebeaninternal/server/transaction/DefaultTransactionScopeManager.java @@ -28,12 +28,12 @@ public class DefaultTransactionScopeManager extends TransactionScopeManager { } @Override - public SpiTransaction getMaybeInactive() { + public SpiTransaction getInScope() { return DefaultTransactionThreadLocal.get(serverName); } @Override - public SpiTransaction get() { + public SpiTransaction getActive() { SpiTransaction t = DefaultTransactionThreadLocal.get(serverName); if (t == null || !t.isActive()) { return null; diff --git a/src/main/java/io/ebeaninternal/server/transaction/ExternalTransactionScopeManager.java b/src/main/java/io/ebeaninternal/server/transaction/ExternalTransactionScopeManager.java index a80ba0852..ffa3bdb1e 100644 --- a/src/main/java/io/ebeaninternal/server/transaction/ExternalTransactionScopeManager.java +++ b/src/main/java/io/ebeaninternal/server/transaction/ExternalTransactionScopeManager.java @@ -1,6 +1,7 @@ package io.ebeaninternal.server.transaction; import io.ebean.config.ExternalTransactionManager; +import io.ebeaninternal.api.SpiTransaction; /** * A TransactionScopeManager aware of external transaction managers. @@ -22,4 +23,9 @@ public class ExternalTransactionScopeManager extends DefaultTransactionScopeMana externalManager.setTransactionManager(manager); } + @Override + public SpiTransaction getActive() { + return (SpiTransaction) externalManager.getCurrentTransaction(); + } + } diff --git a/src/main/java/io/ebeaninternal/server/transaction/TransactionManager.java b/src/main/java/io/ebeaninternal/server/transaction/TransactionManager.java index 1ff2c453e..d4e0379ff 100644 --- a/src/main/java/io/ebeaninternal/server/transaction/TransactionManager.java +++ b/src/main/java/io/ebeaninternal/server/transaction/TransactionManager.java @@ -201,22 +201,22 @@ public class TransactionManager implements SpiTransactionManager { /** * Return the current active transaction. */ - public SpiTransaction get() { - return scopeManager.get(); + public SpiTransaction getActive() { + return scopeManager.getActive(); } /** * Return the current active transaction as a scoped transaction. */ - public ScopedTransaction getScoped() { - return (ScopedTransaction) scopeManager.get(); + public ScopedTransaction getActiveScoped() { + return (ScopedTransaction) scopeManager.getActive(); } /** - * Return the current scoped transaction allowing it to be inactive (already committed or rolled back). + * Return the current transaction from thread local scope. Note that it may be inactive. */ - private ScopedTransaction getMaybeInactive() { - return (ScopedTransaction)scopeManager.getMaybeInactive(); + public SpiTransaction getInScope() { + return scopeManager.getInScope(); } /** @@ -420,7 +420,7 @@ public class TransactionManager implements SpiTransactionManager { } public void externalModification(TransactionEventTable tableEvent) { - SpiTransaction t = get(); + SpiTransaction t = getActive(); if (t != null) { t.getEvent().add(tableEvent); } else { @@ -555,11 +555,11 @@ public class TransactionManager implements SpiTransactionManager { * Exit a scoped transaction (that can be inactive - already committed etc). */ public void exitScopedTransaction(Object returnOrThrowable, int opCode) { - ScopedTransaction st = getMaybeInactive(); - if (st != null) { + SpiTransaction st = getInScope(); + if (st instanceof ScopedTransaction) { // can be null for Supports as that can start as a 'No Transaction' and then // effectively be replaced by transactions inside the scope - st.complete(returnOrThrowable, opCode); + ((ScopedTransaction)st).complete(returnOrThrowable, opCode); } } @@ -588,7 +588,7 @@ public class TransactionManager implements SpiTransactionManager { txScope = initTxScope(txScope); boolean setToScope = false; - ScopedTransaction txnContainer = getScoped(); + ScopedTransaction txnContainer = getActiveScoped(); if (txnContainer == null) { setToScope = true; txnContainer = createScopedTransaction(); diff --git a/src/main/java/io/ebeaninternal/server/transaction/TransactionScopeManager.java b/src/main/java/io/ebeaninternal/server/transaction/TransactionScopeManager.java index 994a667a9..541b07b1d 100644 --- a/src/main/java/io/ebeaninternal/server/transaction/TransactionScopeManager.java +++ b/src/main/java/io/ebeaninternal/server/transaction/TransactionScopeManager.java @@ -20,14 +20,14 @@ public abstract class TransactionScopeManager implements SpiTransactionScopeMana public abstract void register(TransactionManager manager); /** - * Return the current Transaction allowing it to be inactive. + * Return the current Transaction from internal Ebean scope. */ - public abstract SpiTransaction getMaybeInactive(); + public abstract SpiTransaction getInScope(); /** - * Return the current Transaction for this serverName and Thread. + * Return the current Transaction potentially looking in external scope (like Spring). */ - public abstract SpiTransaction get(); + public abstract SpiTransaction getActive(); /** * Set a new Transaction for this serverName and Thread.