From cd0d5c77247efd4e5108c8cfc5eea35e24a3d3ba Mon Sep 17 00:00:00 2001 From: Stefano Franz Date: Fri, 30 Aug 2019 14:58:50 +0000 Subject: [PATCH] Ensure that ServiceHub.WithEntityManager has a database transaction available (#5413) * tidy up withEntityManager * address rick review comment * api break --- .ci/api-current.txt | 2 -- .../kotlin/net/corda/core/node/ServiceHub.kt | 2 +- .../net/corda/node/internal/AbstractNode.kt | 16 +++++++++++----- .../net/corda/testing/node/MockServices.kt | 4 ++-- 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/.ci/api-current.txt b/.ci/api-current.txt index a9dfa43bd9..354adb1db8 100644 --- a/.ci/api-current.txt +++ b/.ci/api-current.txt @@ -3520,7 +3520,6 @@ public interface net.corda.core.node.ServiceHub extends net.corda.core.node.Serv @NotNull public abstract net.corda.core.contracts.StateAndRef toStateAndRef(net.corda.core.contracts.StateRef) public abstract void withEntityManager(java.util.function.Consumer) - @NotNull public abstract T withEntityManager(kotlin.jvm.functions.Function1) ## @DoNotImplement @@ -7816,7 +7815,6 @@ public class net.corda.testing.node.MockServices extends java.lang.Object implem @NotNull public net.corda.core.contracts.StateAndRef toStateAndRef(net.corda.core.contracts.StateRef) public void withEntityManager(java.util.function.Consumer) - @NotNull public T withEntityManager(kotlin.jvm.functions.Function1) public static final net.corda.testing.node.MockServices$Companion Companion ## diff --git a/core/src/main/kotlin/net/corda/core/node/ServiceHub.kt b/core/src/main/kotlin/net/corda/core/node/ServiceHub.kt index c20d6357a3..41a5a4b8e9 100644 --- a/core/src/main/kotlin/net/corda/core/node/ServiceHub.kt +++ b/core/src/main/kotlin/net/corda/core/node/ServiceHub.kt @@ -376,7 +376,7 @@ interface ServiceHub : ServicesForResolution { * * @param block a lambda function with access to an [EntityManager]. */ - fun withEntityManager(block: EntityManager.() -> T): T + fun withEntityManager(block: EntityManager.() -> T): T /** * Exposes the Java Persistence API (JPA) to flows via a restricted [EntityManager]. This method can be used to diff --git a/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt b/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt index fdf6d5a991..e6378ee979 100644 --- a/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt +++ b/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt @@ -409,7 +409,9 @@ abstract class AbstractNode(val configuration: NodeConfiguration, // Shut down the SMM so no Fibers are scheduled. runOnStop += { smm.stop(acceptableLiveFiberCountOnStop()) } (smm as? StateMachineManagerInternal)?.let { - val flowMonitor = FlowMonitor({ smm.snapshot().filter { flow -> flow !in smm.flowHospital }.toSet() }, configuration.flowMonitorPeriodMillis, configuration.flowMonitorSuspensionLoggingThresholdMillis) + val flowMonitor = FlowMonitor({ + smm.snapshot().filter { flow -> flow !in smm.flowHospital }.toSet() + }, configuration.flowMonitorPeriodMillis, configuration.flowMonitorSuspensionLoggingThresholdMillis) runOnStop += flowMonitor::stop flowMonitor.start() } @@ -596,7 +598,7 @@ abstract class AbstractNode(val configuration: NodeConfiguration, // Needed because of bug CORDA-2653 - some Corda services can utilise third-party libraries that require access to // the Thread context class loader - val oldContextClassLoader : ClassLoader? = Thread.currentThread().contextClassLoader + val oldContextClassLoader: ClassLoader? = Thread.currentThread().contextClassLoader try { Thread.currentThread().contextClassLoader = cordappLoader.appClassLoader @@ -1032,12 +1034,16 @@ abstract class AbstractNode(val configuration: NodeConfiguration, override fun jdbcSession(): Connection = database.createSession() - override fun withEntityManager(block: EntityManager.() -> T): T { - return block(contextTransaction.restrictedEntityManager) + override fun withEntityManager(block: EntityManager.() -> T): T { + return database.transaction { + block(restrictedEntityManager) + } } override fun withEntityManager(block: Consumer) { - block.accept(contextTransaction.restrictedEntityManager) + withEntityManager { + block.accept(this) + } } // allows services to register handlers to be informed when the node stop method is called diff --git a/testing/node-driver/src/main/kotlin/net/corda/testing/node/MockServices.kt b/testing/node-driver/src/main/kotlin/net/corda/testing/node/MockServices.kt index 0d2a6c8078..044c851fc4 100644 --- a/testing/node-driver/src/main/kotlin/net/corda/testing/node/MockServices.kt +++ b/testing/node-driver/src/main/kotlin/net/corda/testing/node/MockServices.kt @@ -224,7 +224,7 @@ open class MockServices private constructor( override fun jdbcSession(): Connection = persistence.createSession() - override fun withEntityManager(block: EntityManager.() -> T): T { + override fun withEntityManager(block: EntityManager.() -> T): T { return block(contextTransaction.restrictedEntityManager) } @@ -440,7 +440,7 @@ open class MockServices private constructor( override fun jdbcSession(): Connection = throw UnsupportedOperationException() - override fun withEntityManager(block: EntityManager.() -> T): T { + override fun withEntityManager(block: EntityManager.() -> T): T { throw UnsupportedOperationException() }