Repository: hibernate/hibernate-reactive
Pull request #2231 (2025-04-30 09:46:56)

add operations for obtaining the current sessions from the context
This will make it easier to implement the necessary Quarkus integration. See https://github.com/quarkusio/quarkus/issues/47462.

DavideD: I guess it's connected to this issue: https://github.com/hibernate/hibernate-reactive/issues/1780
DavideD: Out of curiosity, did you test this?
gavinking: > did you test this?

Nope.

Patch:
diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/Mutiny.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/Mutiny.java
index aab884e7..71048e5b 100644
--- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/Mutiny.java
+++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/Mutiny.java
@@ -2269,6 +2269,31 @@ default <T> Uni<T> withStatelessTransaction(Function<StatelessSession, Uni<T>> w
 		 */
 		Statistics getStatistics();
 
+		/**
+		 * Return the current instance of {@link Session}, if any.
+		 * A current session exists only when this method is called
+		 * from within an invocation of {@link #withSession(Function)}
+		 * or {@link #withTransaction(Function)}.
+		 *
+		 * @return the current instance, if any, or {@code null}
+		 *
+		 * @since 3.0
+		 */
+		Session getCurrentSession();
+
+		/**
+		 * Return the current instance of {@link Session}, if any.
+		 * A current session exists only when this method is called
+		 * from within an invocation of
+		 * {@link #withStatelessSession(Function)} or
+		 * {@link #withStatelessTransaction(Function)}.
+		 *
+		 * @return the current instance, if any, or {@code null}
+		 *
+		 * @since 3.0
+		 */
+		StatelessSession getCurrentStatelessSession();
+
 		/**
 		 * Destroy the session factory and clean up its connection pool.
 		 */
diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/impl/MutinySessionFactoryImpl.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/impl/MutinySessionFactoryImpl.java
index f21bed53..46a71b0b 100644
--- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/impl/MutinySessionFactoryImpl.java
+++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/impl/MutinySessionFactoryImpl.java
@@ -148,6 +148,16 @@ private CompletionStage<ReactiveConnection> connection(String tenantId) {
 				: connectionPool.getConnection( tenantId );
 	}
 
+	@Override
+	public Mutiny.Session getCurrentSession() {
+		return context.get( contextKeyForSession );
+	}
+
+	@Override
+	public Mutiny.StatelessSession getCurrentStatelessSession() {
+		return context.get( contextKeyForStatelessSession );
+	}
+
 	@Override
 	public <T> Uni<T> withSession(Function<Mutiny.Session, Uni<T>> work) {
 		Objects.requireNonNull( work, "parameter 'work' is required" );
diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/stage/Stage.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/stage/Stage.java
index 7219501b..a97b05e5 100644
--- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/stage/Stage.java
+++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/stage/Stage.java
@@ -2273,6 +2273,31 @@ default <T> CompletionStage<T> withStatelessTransaction(Function<StatelessSessio
 		 */
 		Statistics getStatistics();
 
+		/**
+		 * Return the current instance of {@link Session}, if any.
+		 * A current session exists only when this method is called
+		 * from within an invocation of {@link #withSession(Function)}
+		 * or {@link #withTransaction(Function)}.
+		 *
+		 * @return the current instance, if any, or {@code null}
+		 *
+		 * @since 3.0
+		 */
+		Session getCurrentSession();
+
+		/**
+		 * Return the current instance of {@link Session}, if any.
+		 * A current session exists only when this method is called
+		 * from within an invocation of
+		 * {@link #withStatelessSession(Function)} or
+		 * {@link #withStatelessTransaction(Function)}.
+		 *
+		 * @return the current instance, if any, or {@code null}
+		 *
+		 * @since 3.0
+		 */
+		StatelessSession getCurrentStatelessSession();
+
 		/**
 		 * Destroy the session factory and clean up its connection pool.
 		 */
diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/stage/impl/StageSessionFactoryImpl.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/stage/impl/StageSessionFactoryImpl.java
index 78d52e68..56c574ce 100644
--- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/stage/impl/StageSessionFactoryImpl.java
+++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/stage/impl/StageSessionFactoryImpl.java
@@ -138,6 +138,16 @@ private CompletionStage<ReactiveConnection> connection(String tenantId) {
 				: connectionPool.getConnection( tenantId );
 	}
 
+	@Override
+	public Stage.Session getCurrentSession() {
+		return context.get( contextKeyForSession );
+	}
+
+	@Override
+	public Stage.StatelessSession getCurrentStatelessSession() {
+		return context.get( contextKeyForStatelessSession );
+	}
+
 	@Override
 	public <T> CompletionStage<T> withSession(Function<Stage.Session, CompletionStage<T>> work) {
 		Objects.requireNonNull( work, "parameter 'work' is required" );


Test patch:
diff --git a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/MutinySessionTest.java b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/MutinySessionTest.java
index fb8c7e1f..bf46f835 100644
--- a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/MutinySessionTest.java
+++ b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/MutinySessionTest.java
@@ -27,12 +27,7 @@
 import jakarta.persistence.metamodel.EntityType;
 
 import static java.util.concurrent.TimeUnit.MINUTES;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertNotEquals;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.junit.jupiter.api.Assertions.fail;
+import static org.junit.jupiter.api.Assertions.*;
 
 @Timeout(value = 10, timeUnit = MINUTES)
 
@@ -668,6 +663,38 @@ public void testForceFlushWithDelete(VertxTestContext context) {
 		);
 	}
 
+	@Test
+	public void testCurrentSession(VertxTestContext context) {
+		test( context,
+				getMutinySessionFactory().withSession(session ->
+						getMutinySessionFactory().withSession(s -> {
+							assertEquals(session, s);
+							Mutiny.Session currentSession = getMutinySessionFactory().getCurrentSession();
+							assertNotNull(currentSession);
+							assertTrue(currentSession.isOpen());
+							assertEquals(session, currentSession);
+							return Uni.createFrom().voidItem();
+						}).invoke(() -> assertNotNull(getMutinySessionFactory().getCurrentSession()))
+				).invoke(() -> assertNull(getMutinySessionFactory().getCurrentSession()))
+		);
+	}
+
+	@Test
+	public void testCurrentStatelessSession(VertxTestContext context) {
+		test( context,
+				getMutinySessionFactory().withStatelessSession(session ->
+						getMutinySessionFactory().withStatelessSession(s -> {
+							assertEquals(session, s);
+							Mutiny.StatelessSession currentSession = getMutinySessionFactory().getCurrentStatelessSession();
+							assertNotNull(currentSession);
+							assertTrue(currentSession.isOpen());
+							assertEquals(session, currentSession);
+							return Uni.createFrom().voidItem();
+						}).invoke(() -> assertNotNull(getMutinySessionFactory().getCurrentStatelessSession()))
+				).invoke(() -> assertNull(getMutinySessionFactory().getCurrentStatelessSession()))
+		);
+	}
+
 	private void assertThatPigsAreEqual(GuineaPig expected, GuineaPig actual) {
 		assertNotNull( actual );
 		assertEquals( expected.getId(), actual.getId() );
diff --git a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/ReactiveSessionTest.java b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/ReactiveSessionTest.java
index 78494bd1..ed0c724f 100644
--- a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/ReactiveSessionTest.java
+++ b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/ReactiveSessionTest.java
@@ -32,12 +32,7 @@
 
 import static java.util.concurrent.TimeUnit.MINUTES;
 import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertInstanceOf;
-import static org.junit.jupiter.api.Assertions.assertNotEquals;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.*;
 
 @Timeout(value = 10, timeUnit = MINUTES)
 
@@ -969,6 +964,42 @@ context, openSession()
 		);
 	}
 
+	@Test
+	public void testCurrentSession(VertxTestContext context) {
+		test( context,
+				getSessionFactory().withSession(session ->
+						getSessionFactory().withSession(s -> {
+							assertEquals(session, s);
+							Stage.Session currentSession = getSessionFactory().getCurrentSession();
+							assertNotNull(currentSession);
+							assertTrue(currentSession.isOpen());
+							assertEquals(session, currentSession);
+							return CompletionStages.voidFuture();
+						})
+						.thenAccept(v -> assertNotNull(getSessionFactory().getCurrentSession()))
+				)
+				.thenAccept(v -> assertNull(getSessionFactory().getCurrentSession()))
+		);
+	}
+
+	@Test
+	public void testCurrentStatelessSession(VertxTestContext context) {
+		test( context,
+				getSessionFactory().withStatelessSession(session ->
+						getSessionFactory().withStatelessSession(s -> {
+							assertEquals(session, s);
+							Stage.StatelessSession currentSession = getSessionFactory().getCurrentStatelessSession();
+							assertNotNull(currentSession);
+							assertTrue(currentSession.isOpen());
+							assertEquals(session, currentSession);
+							return CompletionStages.voidFuture();
+						})
+						.thenAccept(v -> assertNotNull(getSessionFactory().getCurrentStatelessSession()))
+				)
+				.thenAccept(v -> assertNull(getSessionFactory().getCurrentStatelessSession()))
+		);
+	}
+
 	private void assertThatPigsAreEqual(GuineaPig expected, GuineaPig actual) {
 		assertNotNull( actual );
 		assertEquals( expected.getId(), actual.getId() );