From 0d1ae5ead98312ea602c2b536e5ad451e44f7664 Mon Sep 17 00:00:00 2001 From: Martin Kouba Date: Wed, 30 Aug 2023 08:29:11 +0200 Subject: [PATCH] Hibernate Reactive Panache: fix WithSessionOnDemand implementation - fixes #35568 --- .../common/runtime/SessionOperations.java | 14 ++++-- .../deployment/pom.xml | 5 ++ .../panache/test/WithSessionOnDemandTest.java | 46 +++++++++++++++++++ 3 files changed, 62 insertions(+), 3 deletions(-) create mode 100644 extensions/panache/hibernate-reactive-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/panache/test/WithSessionOnDemandTest.java diff --git a/extensions/panache/hibernate-reactive-panache-common/runtime/src/main/java/io/quarkus/hibernate/reactive/panache/common/runtime/SessionOperations.java b/extensions/panache/hibernate-reactive-panache-common/runtime/src/main/java/io/quarkus/hibernate/reactive/panache/common/runtime/SessionOperations.java index 99c15a8691d11..6c18c85066417 100644 --- a/extensions/panache/hibernate-reactive-panache-common/runtime/src/main/java/io/quarkus/hibernate/reactive/panache/common/runtime/SessionOperations.java +++ b/extensions/panache/hibernate-reactive-panache-common/runtime/src/main/java/io/quarkus/hibernate/reactive/panache/common/runtime/SessionOperations.java @@ -49,6 +49,7 @@ public Key get() { // This key is used to indicate that a reactive session should be opened lazily (when needed) in the current vertx context private static final String SESSION_ON_DEMAND_KEY = "hibernate.reactive.panache.sessionOnDemand"; + private static final String SESSION_ON_DEMAND_OPENED_KEY = "hibernate.reactive.panache.sessionOnDemandOpened"; /** * Marks the current vertx duplicated context as "lazy" which indicates that a reactive session should be opened lazily if @@ -70,6 +71,7 @@ static Uni withSessionOnDemand(Supplier> work) { // perform the work and eventually close the session and remove the key return work.get().eventually(() -> { context.removeLocal(SESSION_ON_DEMAND_KEY); + context.removeLocal(SESSION_ON_DEMAND_OPENED_KEY); return closeSession(); }); } @@ -148,9 +150,15 @@ public static Uni getSession() { return Uni.createFrom().item(current); } else { if (context.getLocal(SESSION_ON_DEMAND_KEY) != null) { - // open a new reactive session and store it in the vertx duplicated context - // the context was marked as "lazy" which means that the session will be eventually closed - return getSessionFactory().openSession().invoke(s -> context.putLocal(key, s)); + if (context.getLocal(SESSION_ON_DEMAND_OPENED_KEY) != null) { + // a new reactive session is opened in a previous stage + return Uni.createFrom().item(() -> getCurrentSession()); + } else { + // open a new reactive session and store it in the vertx duplicated context + // the context was marked as "lazy" which means that the session will be eventually closed + context.putLocal(SESSION_ON_DEMAND_OPENED_KEY, true); + return getSessionFactory().openSession().invoke(s -> context.putLocal(key, s)); + } } else { throw new IllegalStateException("No current Mutiny.Session found" + "\n\t- no reactive session was found in the context and the context was not marked to open a new session lazily" diff --git a/extensions/panache/hibernate-reactive-panache/deployment/pom.xml b/extensions/panache/hibernate-reactive-panache/deployment/pom.xml index 6e7f2b66cb6c2..0282b59e06f11 100644 --- a/extensions/panache/hibernate-reactive-panache/deployment/pom.xml +++ b/extensions/panache/hibernate-reactive-panache/deployment/pom.xml @@ -35,6 +35,11 @@ quarkus-junit5-internal test + + io.quarkus + quarkus-test-hibernate-reactive-panache + test + io.quarkus quarkus-reactive-pg-client-deployment diff --git a/extensions/panache/hibernate-reactive-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/panache/test/WithSessionOnDemandTest.java b/extensions/panache/hibernate-reactive-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/panache/test/WithSessionOnDemandTest.java new file mode 100644 index 0000000000000..e86ae99de555e --- /dev/null +++ b/extensions/panache/hibernate-reactive-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/panache/test/WithSessionOnDemandTest.java @@ -0,0 +1,46 @@ +package io.quarkus.hibernate.reactive.panache.test; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; + +import org.hibernate.reactive.mutiny.Mutiny.Session; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.arc.Unremovable; +import io.quarkus.hibernate.reactive.panache.Panache; +import io.quarkus.hibernate.reactive.panache.common.WithSessionOnDemand; +import io.quarkus.test.QuarkusUnitTest; +import io.quarkus.test.vertx.RunOnVertxContext; +import io.quarkus.test.vertx.UniAsserter; +import io.smallrye.mutiny.Uni; + +public class WithSessionOnDemandTest { + + @RegisterExtension + static QuarkusUnitTest config = new QuarkusUnitTest() + .withApplicationRoot(root -> root.addClasses(MrBean.class, MyEntity.class)); + + @Inject + MrBean bean; + + @RunOnVertxContext + @Test + public void testSharedSession(UniAsserter asserter) { + asserter.assertEquals(() -> bean.ping(), "true"); + } + + @Unremovable + @ApplicationScoped + static class MrBean { + + @WithSessionOnDemand + Uni ping() { + Uni s1 = Panache.getSession(); + Uni s2 = Panache.getSession(); + // Test that both unis receive the same session + return s1.chain(s1Val -> s2.map(s2Val -> "" + (s1Val == s2Val))); + } + + } +}