Repository: hibernate/hibernate-reactive (java)

Issue:
Upgrade Vert.x SQL client to 5

Pull request description:
Upgrade Vert.x SQL client to 5
Fix #2036 

First draft to have an idea of how the API have changed.
It needs to be  cleaned up.


Patch:
diff --git a/README.md b/README.md
index 6047808f..743540d6 100644
--- a/README.md
+++ b/README.md
@@ -39,11 +39,11 @@ Hibernate Reactive has been tested with:
 - MS SQL Server 2022
 - Oracle 23
 - [Hibernate ORM][] 7.0.0.Final
-- [Vert.x Reactive PostgreSQL Client](https://vertx.io/docs/vertx-pg-client/java/) 4.5.15
-- [Vert.x Reactive MySQL Client](https://vertx.io/docs/vertx-mysql-client/java/) 4.5.15
-- [Vert.x Reactive Db2 Client](https://vertx.io/docs/vertx-db2-client/java/) 4.5.15
-- [Vert.x Reactive MS SQL Server Client](https://vertx.io/docs/vertx-mssql-client/java/) 4.5.15
-- [Vert.x Reactive Oracle Client](https://vertx.io/docs/vertx-oracle-client/java/) 4.5.15
+- [Vert.x Reactive PostgreSQL Client](https://vertx.io/docs/vertx-pg-client/java/) 5.0.0
+- [Vert.x Reactive MySQL Client](https://vertx.io/docs/vertx-mysql-client/java/) 5.0.0
+- [Vert.x Reactive Db2 Client](https://vertx.io/docs/vertx-db2-client/java/) 5.0.0
+- [Vert.x Reactive MS SQL Server Client](https://vertx.io/docs/vertx-mssql-client/java/) 5.0.0
+- [Vert.x Reactive Oracle Client](https://vertx.io/docs/vertx-oracle-client/java/) 5.0.0
 - [Quarkus][Quarkus] via the Hibernate Reactive extension
 
 [PostgreSQL]: https://www.postgresql.org
diff --git a/build.gradle b/build.gradle
index 452f7ea2..f927371e 100644
--- a/build.gradle
+++ b/build.gradle
@@ -22,7 +22,7 @@ ext {
     // Example:
     // ./gradlew build -PvertxSqlClientVersion=4.0.0-SNAPSHOT
     if ( !project.hasProperty( 'vertxSqlClientVersion' ) ) {
-        vertxSqlClientVersion = '4.5.15'
+        vertxSqlClientVersion = '5.0.0'
     }
 
     testcontainersVersion = '1.21.0'
diff --git a/documentation/src/main/asciidoc/reference/introduction.adoc b/documentation/src/main/asciidoc/reference/introduction.adoc
index 4f2237ed..ee5090c2 100644
--- a/documentation/src/main/asciidoc/reference/introduction.adoc
+++ b/documentation/src/main/asciidoc/reference/introduction.adoc
@@ -89,7 +89,7 @@ Optionally, you might also add any of the following additional features:
 | Hibernate Validator | `org.hibernate.validator:hibernate-validator` and `org.glassfish:jakarta.el`
 | Compile-time checking for your HQL queries | `org.hibernate:query-validator`
 | Second-level cache support via JCache and EHCache | `org.hibernate.orm:hibernate-jcache` along with `org.ehcache:ehcache`
-| SCRAM authentication support for PostgreSQL | `com.ongres.scram:client:2.1`
+| SCRAM authentication support for PostgreSQL | `com.ongres.scram:scram-client:3.1`
 |===
 
 You might also add the Hibernate {enhancer}[bytecode enhancer] to your
diff --git a/examples/native-sql-example/build.gradle b/examples/native-sql-example/build.gradle
index c79ec898..3b650d34 100644
--- a/examples/native-sql-example/build.gradle
+++ b/examples/native-sql-example/build.gradle
@@ -40,7 +40,7 @@ dependencies {
     runtimeOnly "org.apache.logging.log4j:log4j-core:2.20.0"
 
     // Allow authentication to PostgreSQL using SCRAM:
-    runtimeOnly 'com.ongres.scram:client:2.1'
+    runtimeOnly 'com.ongres.scram:scram-client:3.1'
 }
 
 // Optional: enable the bytecode enhancements
diff --git a/examples/session-example/build.gradle b/examples/session-example/build.gradle
index 4da40ba6..a001112d 100644
--- a/examples/session-example/build.gradle
+++ b/examples/session-example/build.gradle
@@ -41,7 +41,7 @@ dependencies {
     runtimeOnly "org.apache.logging.log4j:log4j-core:2.20.0"
 
     // Allow authentication to PostgreSQL using SCRAM:
-    runtimeOnly 'com.ongres.scram:client:2.1'
+    runtimeOnly 'com.ongres.scram:scram-client:3.1'
 }
 
 // Optional: enable the bytecode enhancements
diff --git a/gradle.properties b/gradle.properties
index 5cd93733..36bc0c5a 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -47,9 +47,9 @@ hibernateOrmVersion = 7.0.0.Final
 #skipOrmVersionParsing = true
 
 # Override default Vert.x Sql client version
-#vertxSqlClientVersion = 4.5.15-SNAPSHOT
+#vertxSqlClientVersion = 5.0.0-SNAPSHOT
 
 # Override default Vert.x Web client and server versions. For integration tests, both default to vertxSqlClientVersion
-#vertxWebVersion = 4.5.15
-#vertxWebtClientVersion = 4.5.15
+#vertxWebVersion = 5.0.0
+#vertxWebtClientVersion = 5.0.0
 
diff --git a/hibernate-reactive-core/build.gradle b/hibernate-reactive-core/build.gradle
index 01f593d8..26a4de75 100644
--- a/hibernate-reactive-core/build.gradle
+++ b/hibernate-reactive-core/build.gradle
@@ -39,7 +39,7 @@ dependencies {
     testImplementation "io.vertx:vertx-micrometer-metrics:${vertxSqlClientVersion}"
 
     // Optional dependency of vertx-pg-client, essential when connecting via SASL SCRAM
-    testImplementation 'com.ongres.scram:client:2.1'
+    testImplementation 'com.ongres.scram:scram-client:3.1'
 
     // JUnit Jupiter
     testImplementation 'org.junit.jupiter:junit-jupiter-api:5.11.3'
diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/context/impl/VertxContext.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/context/impl/VertxContext.java
index 4448c9b6..02c28af5 100644
--- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/context/impl/VertxContext.java
+++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/context/impl/VertxContext.java
@@ -8,7 +8,7 @@
 import java.lang.invoke.MethodHandles;
 
 import io.vertx.core.Vertx;
-import io.vertx.core.impl.ContextInternal;
+import io.vertx.core.internal.ContextInternal;
 
 import org.hibernate.reactive.context.Context;
 import org.hibernate.reactive.logging.impl.Log;
@@ -36,7 +36,7 @@ public void injectServices(ServiceRegistryImplementor serviceRegistry) {
 
 	@Override
 	public <T> void put(Key<T> key, T instance) {
-		final io.vertx.core.Context context = Vertx.currentContext();
+		final ContextInternal context = currentContext();
 		if ( context != null ) {
 			if ( trace ) LOG.tracef( "Putting key,value in context: [%1$s, %2$s]", key, instance );
 			context.putLocal( key, instance );
@@ -47,9 +47,13 @@ public <T> void put(Key<T> key, T instance) {
 		}
 	}
 
+	private static ContextInternal currentContext() {
+		return (ContextInternal) Vertx.currentContext();
+	}
+
 	@Override
 	public <T> T get(Key<T> key) {
-		final io.vertx.core.Context context = Vertx.currentContext();
+		final ContextInternal context = currentContext();
 		if ( context != null ) {
 			T local = context.getLocal( key );
 			if ( trace ) LOG.tracef( "Getting value %2$s from context for key %1$s", key, local  );
@@ -63,7 +67,7 @@ public <T> T get(Key<T> key) {
 
 	@Override
 	public void remove(Key<?> key) {
-		final io.vertx.core.Context context = Vertx.currentContext();
+		final ContextInternal context = currentContext();
 		if ( context != null ) {
 			boolean removed = context.removeLocal( key );
 			if ( trace ) LOG.tracef( "Key %s removed from context: %s", key, removed );
@@ -75,7 +79,7 @@ public void remove(Key<?> key) {
 
 	@Override
 	public void execute(Runnable runnable) {
-		final io.vertx.core.Context currentContext = Vertx.currentContext();
+		final io.vertx.core.Context currentContext = currentContext();
 		if ( currentContext == null ) {
 			if ( trace ) LOG.tracef( "Not in a Vert.x context, checking the VertxInstance service" );
 			final io.vertx.core.Context newContext = vertxInstance.getVertx().getOrCreateContext();
@@ -83,6 +87,7 @@ public void execute(Runnable runnable) {
 			// that could lead to unintentionally share the same session with other streams.
 			ContextInternal newContextInternal = (ContextInternal) newContext;
 			final ContextInternal duplicate = newContextInternal.duplicate();
+
 			if ( trace ) LOG.tracef( "Using duplicated context from VertxInstance: %s", duplicate );
 			duplicate.runOnContext( x -> runnable.run() );
 		}
diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/id/impl/BlockingIdentifierGenerator.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/id/impl/BlockingIdentifierGenerator.java
index c820f513..329792f2 100644
--- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/id/impl/BlockingIdentifierGenerator.java
+++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/id/impl/BlockingIdentifierGenerator.java
@@ -14,9 +14,9 @@
 
 import io.vertx.core.Context;
 import io.vertx.core.Vertx;
-import io.vertx.core.net.impl.pool.CombinerExecutor;
-import io.vertx.core.net.impl.pool.Executor;
-import io.vertx.core.net.impl.pool.Task;
+import io.vertx.core.internal.pool.CombinerExecutor;
+import io.vertx.core.internal.pool.Executor;
+import io.vertx.core.internal.pool.Task;
 
 import static org.hibernate.reactive.util.impl.CompletionStages.completedFuture;
 
@@ -44,7 +44,7 @@ public abstract class BlockingIdentifierGenerator implements ReactiveIdentifierG
 	//modification access.
 	//This replaces the synchronization blocks one would see in a similar
 	//service in Hibernate ORM, but using a non-blocking cooperative design.
-	private final CombinerExecutor executor = new CombinerExecutor( state );
+	private final CombinerExecutor<GeneratorState> executor = new CombinerExecutor<>( state );
 
 	/**
 	 * Allocate a new block, by obtaining the next "hi" value from the database
diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/pool/impl/DefaultSqlClientPool.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/pool/impl/DefaultSqlClientPool.java
index 67476f71..5249a79e 100644
--- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/pool/impl/DefaultSqlClientPool.java
+++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/pool/impl/DefaultSqlClientPool.java
@@ -13,6 +13,7 @@
 import java.util.ServiceConfigurationError;
 import java.util.ServiceLoader;
 import java.util.concurrent.CompletionStage;
+import java.util.function.Supplier;
 
 import org.hibernate.engine.jdbc.spi.JdbcServices;
 import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
@@ -31,13 +32,13 @@
 
 import io.vertx.core.Future;
 import io.vertx.core.Vertx;
+import io.vertx.core.net.NetClientOptions;
 import io.vertx.sqlclient.Pool;
 import io.vertx.sqlclient.PoolOptions;
 import io.vertx.sqlclient.SqlConnectOptions;
+import io.vertx.sqlclient.impl.Utils;
 import io.vertx.sqlclient.spi.Driver;
 
-import static java.util.Collections.singletonList;
-
 /**
  * A pool of reactive connections backed by a Vert.x {@link Pool}.
  * The {@code Pool} itself is backed by an instance of {@link Vertx}
@@ -189,7 +190,7 @@ protected Pool createPool(URI uri) {
 	 *
 	 * @return the new {@link Pool}
 	 */
-	protected Pool createPool(URI uri, SqlConnectOptions connectOptions, PoolOptions poolOptions, Vertx vertx) {
+	protected <T extends SqlConnectOptions> Pool createPool(URI uri, T connectOptions, PoolOptions poolOptions, Vertx vertx) {
 		try {
 			// First try to load the Pool using the standard ServiceLoader pattern
 			// This only works if exactly 1 Driver is on the classpath.
@@ -198,8 +199,9 @@ protected Pool createPool(URI uri, SqlConnectOptions connectOptions, PoolOptions
 		catch (ServiceConfigurationError e) {
 			// Backup option if multiple drivers are on the classpath.
 			// We will be able to remove this once Vertx 3.9.2 is available
-			final Driver driver = findDriver( uri, e );
-			return driver.createPool( vertx, singletonList( connectOptions ), poolOptions );
+			final Driver<SqlConnectOptions> driver = findDriver( uri, e );
+			Supplier<Future<SqlConnectOptions>> database = Utils.singletonSupplier( driver.downcast( connectOptions ) );
+			return driver.createPool( vertx, database, poolOptions, new NetClientOptions(), null );
 		}
 	}
 
@@ -222,15 +224,14 @@ protected URI jdbcUrl(Map<?,?> configurationValues) {
 	 * so we need to disambiguate according to the scheme specified
 	 * in the given {@link URI}.
 	 *
-	 * @param uri the JDBC URL or database URI
+	 * @param uri           the JDBC URL or database URI
 	 * @param originalError the error that was thrown
-	 *
 	 * @return the disambiguated {@link Driver}
 	 */
-	private Driver findDriver(URI uri, ServiceConfigurationError originalError) {
+	private Driver<SqlConnectOptions> findDriver(URI uri, ServiceConfigurationError originalError) {
 		String scheme = scheme( uri );
-		List<Driver> selected = new ArrayList<>();
-		for ( Driver d : ServiceLoader.load( Driver.class ) ) {
+		List<Driver<SqlConnectOptions>> selected = new ArrayList<>();
+		for ( Driver<SqlConnectOptions> d : ServiceLoader.load( Driver.class ) ) {
 			String driverName = d.getClass().getCanonicalName();
 			if ( matchesScheme( driverName, scheme ) ) {
 				LOG.selectedDriver( driverName );
diff --git a/tooling/jbang/Example.java b/tooling/jbang/Example.java
index 21dc2502..3dde6e2b 100644
--- a/tooling/jbang/Example.java
+++ b/tooling/jbang/Example.java
@@ -5,10 +5,10 @@
  * Copyright: Red Hat Inc. and Hibernate Authors
  */
 
-//DEPS com.ongres.scram:client:2.1
-//DEPS io.vertx:vertx-pg-client:${vertx.version:4.5.15}
-//DEPS io.vertx:vertx-mysql-client:${vertx.version:4.5.15}
-//DEPS io.vertx:vertx-db2-client:${vertx.version:4.5.15}
+//DEPS com.ongres.scram:scram-client:3.1
+//DEPS io.vertx:vertx-pg-client:${vertx.version:5.0.0}
+//DEPS io.vertx:vertx-mysql-client:${vertx.version:5.0.0}
+//DEPS io.vertx:vertx-db2-client:${vertx.version:5.0.0}
 //DEPS org.hibernate.reactive:hibernate-reactive-core:${hibernate-reactive.version:4.0.0.Final}
 //DEPS org.slf4j:slf4j-simple:2.0.7
 //DESCRIPTION Allow authentication to PostgreSQL using SCRAM:


Test patch:
diff --git a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/BaseReactiveTest.java b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/BaseReactiveTest.java
index 07a79379..508625bc 100644
--- a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/BaseReactiveTest.java
+++ b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/BaseReactiveTest.java
@@ -7,7 +7,6 @@
 
 import java.util.Collection;
 import java.util.List;
-import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.CompletionStage;
 import java.util.function.Supplier;
 
@@ -29,6 +28,7 @@
 import org.hibernate.reactive.provider.service.ReactiveGenerationTarget;
 import org.hibernate.reactive.stage.Stage;
 import org.hibernate.reactive.testing.SessionFactoryManager;
+import org.hibernate.reactive.util.impl.CompletionStages;
 import org.hibernate.tool.schema.spi.SchemaManagementTool;
 
 import org.junit.jupiter.api.AfterAll;
@@ -41,7 +41,6 @@
 import io.micrometer.core.instrument.Metrics;
 import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
 import io.smallrye.mutiny.Uni;
-import io.vertx.core.Promise;
 import io.vertx.core.VertxOptions;
 import io.vertx.junit5.RunTestOnContext;
 import io.vertx.junit5.Timeout;
@@ -75,7 +74,7 @@ public abstract class BaseReactiveTest {
 	 * Configure Vertx JUnit5 test context
 	 */
 	@RegisterExtension
-	static RunTestOnContext testOnContext = new RunTestOnContext( vertxOptions() );
+	static RunTestOnContext testOnContext = new RunTestOnContext( vertxOptions(), false );
 
 	private static VertxOptions vertxOptions() {
 		Metrics.addRegistry( new SimpleMeterRegistry() );
@@ -217,33 +216,19 @@ protected CompletionStage<Void> setupSessionFactory(Configuration configuration)
 	 * @return a {@link CompletionStage} void that succeeds when the factory is ready.
 	 */
 	protected CompletionStage<Void> setupSessionFactory(Supplier<Configuration> confSupplier) {
-		CompletableFuture<Void> future = new CompletableFuture<>();
-		testOnContext.vertx()
+		return testOnContext.vertx()
 				.executeBlocking(
 						// schema generation is a blocking operation and so it causes an
 						// exception when run on the Vert.x event loop. So call it using
 						// Vertx.executeBlocking()
-						promise -> startFactoryManager( promise, confSupplier ),
-						event -> {
-							if ( event.succeeded() ) {
-								future.complete( null );
-							}
-							else {
-								future.completeExceptionally( event.cause() );
-							}
-						}
-				);
-		return future;
-	}
-
-	private void startFactoryManager(Promise<Object> p, Supplier<Configuration> confSupplier) {
-		try {
-			factoryManager.start( () -> createHibernateSessionFactory( confSupplier.get() ) );
-			p.complete();
-		}
-		catch (Throwable e) {
-			p.fail( e );
-		}
+						() -> startFactoryManager( confSupplier ),
+						false
+				).toCompletionStage().thenCompose( CompletionStages::voidFuture );
+	}
+
+	private Object startFactoryManager(Supplier<Configuration> confSupplier) {
+		factoryManager.start( () -> createHibernateSessionFactory( confSupplier.get() ) );
+		return null;
 	}
 
 	private SessionFactory createHibernateSessionFactory(Configuration configuration) {
diff --git a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/TenantDependentPool.java b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/TenantDependentPool.java
index 70b3a1ba..4dd18b30 100644
--- a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/TenantDependentPool.java
+++ b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/TenantDependentPool.java
@@ -7,16 +7,12 @@
 
 import java.net.URI;
 import java.util.Map;
-import java.util.function.Function;
 import java.util.stream.Collectors;
 
 import org.hibernate.reactive.MyCurrentTenantIdentifierResolver.Tenant;
 import org.hibernate.reactive.pool.impl.DefaultSqlClientPool;
 
-import io.vertx.core.AsyncResult;
-import io.vertx.core.Context;
 import io.vertx.core.Future;
-import io.vertx.core.Handler;
 import io.vertx.core.Vertx;
 import io.vertx.sqlclient.Pool;
 import io.vertx.sqlclient.PoolOptions;
@@ -58,8 +54,18 @@ protected Pool createPool(URI uri, SqlConnectOptions connectOptions, PoolOptions
 		return pools;
 	}
 
-	private Pool createPool(URI uri, SqlConnectOptions connectOptions, PoolOptions poolOptions, Vertx vertx, Tenant tenant) {
-		return super.createPool( changeDbName( uri, tenant ), changeDbName( connectOptions, tenant ), poolOptions, vertx );
+	private Pool createPool(
+			URI uri,
+			SqlConnectOptions connectOptions,
+			PoolOptions poolOptions,
+			Vertx vertx,
+			Tenant tenant) {
+		return super.createPool(
+				changeDbName( uri, tenant ),
+				changeDbName( connectOptions, tenant ),
+				poolOptions,
+				vertx
+		);
 	}
 
 	/**
@@ -100,11 +106,6 @@ public Pool getTenantPool(Tenant tenantId) {
 			return poolMap.get( tenantId );
 		}
 
-		@Override
-		public void getConnection(Handler<AsyncResult<SqlConnection>> handler) {
-			poolMap.get( defaultTenantId ).getConnection( handler );
-		}
-
 		@Override
 		public Future<SqlConnection> getConnection() {
 			return poolMap.get( defaultTenantId ).getConnection();
@@ -125,21 +126,6 @@ public PreparedQuery<RowSet<Row>> preparedQuery(String sql, PrepareOptions optio
 			return poolMap.get( defaultTenantId ).preparedQuery( sql, options );
 		}
 
-		@Override
-		public void close(Handler<AsyncResult<Void>> handler) {
-			poolMap.forEach( (tenant, pool) -> pool.close( handler ) );
-		}
-
-		@Override
-		public Pool connectHandler(Handler<SqlConnection> handler) {
-			return poolMap.get( defaultTenantId ).connectHandler( handler );
-		}
-
-		@Override
-		public Pool connectionProvider(Function<Context, Future<SqlConnection>> provider) {
-			return poolMap.get( defaultTenantId ).connectionProvider( provider );
-		}
-
 		@Override
 		public int size() {
 			return poolMap.get( defaultTenantId ).size();
diff --git a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/schema/SchemaValidationTest.java b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/schema/SchemaValidationTest.java
index 3132b849..56def4ef 100644
--- a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/schema/SchemaValidationTest.java
+++ b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/schema/SchemaValidationTest.java
@@ -34,6 +34,7 @@
 import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.DB2;
 import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.MARIA;
 import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.MYSQL;
+import static org.hibernate.reactive.testing.ReactiveAssertions.assertThrown;
 import static org.hibernate.tool.schema.JdbcMetadaAccessStrategy.GROUPED;
 import static org.hibernate.tool.schema.JdbcMetadaAccessStrategy.INDIVIDUALLY;
 import static org.junit.jupiter.params.provider.Arguments.arguments;
@@ -126,13 +127,8 @@ context, setupFactory( strategy, type )
 							validateConf.addAnnotatedClass( BasicTypesTestEntity.class );
 							// The table mapping this entity shouldn't be in the db
 							validateConf.addAnnotatedClass( Extra.class );
-							return setupSessionFactory( validateConf )
-									.handle( (unused, throwable) -> {
-										assertThat( throwable )
-												.isInstanceOf( SchemaManagementException.class )
-												.hasMessage( errorMessage );
-										return null;
-									} );
+							return assertThrown( SchemaManagementException.class, setupSessionFactory( validateConf ) )
+									.thenAccept( throwable -> assertThat( throwable ).hasMessage( errorMessage ) );
 						} )
 		);
 	}
diff --git a/integration-tests/bytecode-enhancements-it/build.gradle b/integration-tests/bytecode-enhancements-it/build.gradle
index 17ffdf10..07174599 100644
--- a/integration-tests/bytecode-enhancements-it/build.gradle
+++ b/integration-tests/bytecode-enhancements-it/build.gradle
@@ -30,7 +30,7 @@ dependencies {
     runtimeOnly "io.vertx:vertx-pg-client:${vertxSqlClientVersion}"
 
     // Allow authentication to PostgreSQL using SCRAM:
-    runtimeOnly 'com.ongres.scram:client:2.1'
+    runtimeOnly 'com.ongres.scram:scram-client:3.1'
 
     // logging
     runtimeOnly "org.apache.logging.log4j:log4j-core:${log4jVersion}"
diff --git a/integration-tests/bytecode-enhancements-it/src/test/java/org/hibernate/reactive/it/BaseReactiveIT.java b/integration-tests/bytecode-enhancements-it/src/test/java/org/hibernate/reactive/it/BaseReactiveIT.java
index 2388cb42..70251e20 100644
--- a/integration-tests/bytecode-enhancements-it/src/test/java/org/hibernate/reactive/it/BaseReactiveIT.java
+++ b/integration-tests/bytecode-enhancements-it/src/test/java/org/hibernate/reactive/it/BaseReactiveIT.java
@@ -7,7 +7,6 @@
 
 import java.util.Collection;
 import java.util.List;
-import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.CompletionStage;
 import java.util.concurrent.TimeUnit;
 import java.util.function.Supplier;
@@ -20,6 +19,7 @@
 import org.hibernate.reactive.provider.ReactiveServiceRegistryBuilder;
 import org.hibernate.reactive.provider.Settings;
 import org.hibernate.reactive.stage.Stage;
+import org.hibernate.reactive.util.impl.CompletionStages;
 
 import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.AfterEach;
@@ -29,7 +29,6 @@
 import org.junit.jupiter.api.extension.RegisterExtension;
 
 import io.smallrye.mutiny.Uni;
-import io.vertx.core.Promise;
 import io.vertx.core.VertxOptions;
 import io.vertx.junit5.RunTestOnContext;
 import io.vertx.junit5.VertxExtension;
@@ -73,7 +72,7 @@ public abstract class BaseReactiveIT {
 	 * Configure Vertx JUnit5 test context
 	 */
 	@RegisterExtension
-	static RunTestOnContext testOnContext = new RunTestOnContext( vertxOptions() );
+	static RunTestOnContext testOnContext = new RunTestOnContext( vertxOptions(), false );
 
 	private static VertxOptions vertxOptions() {
 		return new VertxOptions()
@@ -202,33 +201,19 @@ protected CompletionStage<Void> setupSessionFactory(Configuration configuration)
 	 * @return a {@link CompletionStage} void that succeeds when the factory is ready.
 	 */
 	protected CompletionStage<Void> setupSessionFactory(Supplier<Configuration> confSupplier) {
-		CompletableFuture<Void> future = new CompletableFuture<>();
-		testOnContext.vertx()
+		return testOnContext.vertx()
 				.executeBlocking(
 						// schema generation is a blocking operation and so it causes an
 						// exception when run on the Vert.x event loop. So call it using
 						// Vertx.executeBlocking()
-						promise -> startFactoryManager( promise, confSupplier ),
-						event -> {
-							if ( event.succeeded() ) {
-								future.complete( null );
-							}
-							else {
-								future.completeExceptionally( event.cause() );
-							}
-						}
-				);
-		return future;
+						() -> startFactoryManager( confSupplier ),
+						true
+				).toCompletionStage().thenCompose( CompletionStages::voidFuture );
 	}
 
-	private void startFactoryManager(Promise<Object> p, Supplier<Configuration> confSupplier) {
-		try {
-			ormSessionFactory = createHibernateSessionFactory( confSupplier.get() );
-			p.complete();
-		}
-		catch (Throwable e) {
-			p.fail( e );
-		}
+	private Object startFactoryManager(Supplier<Configuration> confSupplier) {
+		ormSessionFactory = createHibernateSessionFactory( confSupplier.get() );
+		return null;
 	}
 
 	private SessionFactory createHibernateSessionFactory(Configuration configuration) {
diff --git a/integration-tests/hibernate-validator-postgres-it/build.gradle b/integration-tests/hibernate-validator-postgres-it/build.gradle
index 27689b24..abd6e2bc 100644
--- a/integration-tests/hibernate-validator-postgres-it/build.gradle
+++ b/integration-tests/hibernate-validator-postgres-it/build.gradle
@@ -32,7 +32,7 @@ dependencies {
     runtimeOnly "io.vertx:vertx-pg-client:${vertxSqlClientVersion}"
 
     // Allow authentication to PostgreSQL using SCRAM:
-    runtimeOnly 'com.ongres.scram:client:2.1'
+    runtimeOnly 'com.ongres.scram:scram-client:3.1'
 
     // logging
     runtimeOnly "org.apache.logging.log4j:log4j-core:${log4jVersion}"
diff --git a/integration-tests/hibernate-validator-postgres-it/src/test/java/org/hibernate/reactive/it/quarkus/qe/database/BaseReactiveIT.java b/integration-tests/hibernate-validator-postgres-it/src/test/java/org/hibernate/reactive/it/quarkus/qe/database/BaseReactiveIT.java
index 7debdbb2..f65358ce 100644
--- a/integration-tests/hibernate-validator-postgres-it/src/test/java/org/hibernate/reactive/it/quarkus/qe/database/BaseReactiveIT.java
+++ b/integration-tests/hibernate-validator-postgres-it/src/test/java/org/hibernate/reactive/it/quarkus/qe/database/BaseReactiveIT.java
@@ -7,7 +7,6 @@
 
 import java.util.Collection;
 import java.util.List;
-import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.CompletionStage;
 import java.util.concurrent.TimeUnit;
 import java.util.function.Supplier;
@@ -20,6 +19,7 @@
 import org.hibernate.reactive.provider.ReactiveServiceRegistryBuilder;
 import org.hibernate.reactive.provider.Settings;
 import org.hibernate.reactive.stage.Stage;
+import org.hibernate.reactive.util.impl.CompletionStages;
 
 import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.AfterEach;
@@ -29,7 +29,6 @@
 import org.junit.jupiter.api.extension.RegisterExtension;
 
 import io.smallrye.mutiny.Uni;
-import io.vertx.core.Promise;
 import io.vertx.core.VertxOptions;
 import io.vertx.junit5.RunTestOnContext;
 import io.vertx.junit5.VertxExtension;
@@ -73,7 +72,7 @@ public abstract class BaseReactiveIT {
 	 * Configure Vertx JUnit5 test context
 	 */
 	@RegisterExtension
-	static RunTestOnContext testOnContext = new RunTestOnContext( vertxOptions() );
+	static RunTestOnContext testOnContext = new RunTestOnContext( vertxOptions(), false );
 
 	private static VertxOptions vertxOptions() {
 		return new VertxOptions()
@@ -202,33 +201,19 @@ protected CompletionStage<Void> setupSessionFactory(Configuration configuration)
 	 * @return a {@link CompletionStage} void that succeeds when the factory is ready.
 	 */
 	protected CompletionStage<Void> setupSessionFactory(Supplier<Configuration> confSupplier) {
-		CompletableFuture<Void> future = new CompletableFuture<>();
-		testOnContext.vertx()
+		return testOnContext.vertx()
 				.executeBlocking(
 						// schema generation is a blocking operation and so it causes an
 						// exception when run on the Vert.x event loop. So call it using
 						// Vertx.executeBlocking()
-						promise -> startFactoryManager( promise, confSupplier ),
-						event -> {
-							if ( event.succeeded() ) {
-								future.complete( null );
-							}
-							else {
-								future.completeExceptionally( event.cause() );
-							}
-						}
-				);
-		return future;
+						() -> startFactoryManager( confSupplier ),
+						true
+				)
+				.toCompletionStage().thenCompose( CompletionStages::voidFuture );
 	}
 
-	private void startFactoryManager(Promise<Object> p, Supplier<Configuration> confSupplier) {
-		try {
-			ormSessionFactory = createHibernateSessionFactory( confSupplier.get() );
-			p.complete();
-		}
-		catch (Throwable e) {
-			p.fail( e );
-		}
+	private Object startFactoryManager(Supplier<Configuration> confSupplier) {
+		return ormSessionFactory = createHibernateSessionFactory( confSupplier.get() );
 	}
 
 	private SessionFactory createHibernateSessionFactory(Configuration configuration) {
diff --git a/integration-tests/techempower-postgres-it/build.gradle b/integration-tests/techempower-postgres-it/build.gradle
index 5c4ecda4..603a60db 100644
--- a/integration-tests/techempower-postgres-it/build.gradle
+++ b/integration-tests/techempower-postgres-it/build.gradle
@@ -30,7 +30,7 @@ dependencies {
 
 	runtimeOnly "io.vertx:vertx-pg-client:${vertxSqlClientVersion}"
 	// The Pg client requires this dependency
-	runtimeOnly "com.ongres.scram:client:2.1"
+	runtimeOnly "com.ongres.scram:scram-client:3.1"
 	runtimeOnly "com.fasterxml.jackson.core:jackson-databind:${jacksonDatabindVersion}"
 
 	// logging
diff --git a/integration-tests/techempower-postgres-it/src/main/java/org/hibernate/reactive/it/techempower/WorldVerticle.java b/integration-tests/techempower-postgres-it/src/main/java/org/hibernate/reactive/it/techempower/WorldVerticle.java
index 4a12c216..8b89e2d9 100644
--- a/integration-tests/techempower-postgres-it/src/main/java/org/hibernate/reactive/it/techempower/WorldVerticle.java
+++ b/integration-tests/techempower-postgres-it/src/main/java/org/hibernate/reactive/it/techempower/WorldVerticle.java
@@ -45,19 +45,14 @@ public WorldVerticle(Supplier<Mutiny.SessionFactory> emfSupplier) {
 		this.emfSupplier = emfSupplier;
 	}
 
-	private void startHibernate(Promise<Object> p) {
-		try {
-			this.emf = emfSupplier.get();
-			p.complete();
-		}
-		catch (Throwable t) {
-			p.fail( t );
-		}
+	private Object startHibernate() {
+		this.emf = emfSupplier.get();
+		return null;
 	}
 
 	@Override
 	public void start(Promise<Void> startPromise) {
-		final Future<Object> startHibernate = vertx.executeBlocking( this::startHibernate )
+		final Future<Object> startHibernate = vertx.executeBlocking( this::startHibernate, true )
 				.onSuccess( s -> LOG.infof( "✅ Hibernate Reactive is ready" ) );
 
 		Router router = Router.router( vertx );
diff --git a/integration-tests/techempower-postgres-it/src/test/java/org/hibernate/reactive/techempower/TechEmpowerTest.java b/integration-tests/techempower-postgres-it/src/test/java/org/hibernate/reactive/techempower/TechEmpowerTest.java
index 1f28b2bb..ac628337 100644
--- a/integration-tests/techempower-postgres-it/src/test/java/org/hibernate/reactive/techempower/TechEmpowerTest.java
+++ b/integration-tests/techempower-postgres-it/src/test/java/org/hibernate/reactive/techempower/TechEmpowerTest.java
@@ -73,7 +73,7 @@ public void testWorldRepository(VertxTestContext context) {
 				.compose( this::updates )
 				.onSuccess( res -> context.completeNow() )
 				.onFailure( context::failNow )
-				.eventually( unused -> vertx.close() );
+				.eventually( vertx::close );
 	}
 
 	/**
diff --git a/integration-tests/verticle-postgres-it/build.gradle b/integration-tests/verticle-postgres-it/build.gradle
index 0be23462..cf98e8f5 100644
--- a/integration-tests/verticle-postgres-it/build.gradle
+++ b/integration-tests/verticle-postgres-it/build.gradle
@@ -30,7 +30,7 @@ dependencies {
 
     runtimeOnly "io.vertx:vertx-pg-client:${vertxSqlClientVersion}"
     // The Pg client requires this dependency
-    runtimeOnly "com.ongres.scram:client:2.1"
+    runtimeOnly "com.ongres.scram:scram-client:3.1"
     runtimeOnly "com.fasterxml.jackson.core:jackson-databind:${jacksonDatabindVersion}"
 
     // logging
diff --git a/integration-tests/verticle-postgres-it/src/main/java/org/hibernate/reactive/it/verticle/ProductVerticle.java b/integration-tests/verticle-postgres-it/src/main/java/org/hibernate/reactive/it/verticle/ProductVerticle.java
index 882231ad..91d88611 100644
--- a/integration-tests/verticle-postgres-it/src/main/java/org/hibernate/reactive/it/verticle/ProductVerticle.java
+++ b/integration-tests/verticle-postgres-it/src/main/java/org/hibernate/reactive/it/verticle/ProductVerticle.java
@@ -40,19 +40,14 @@ public ProductVerticle(Supplier<Mutiny.SessionFactory> emfSupplier) {
 		this.emfSupplier = emfSupplier;
 	}
 
-	private void startHibernate(Promise<Object> p) {
-		try {
-			this.emf = emfSupplier.get();
-			p.complete();
-		}
-		catch (Throwable t) {
-			p.fail( t );
-		}
+	private Object startHibernate() {
+		this.emf = emfSupplier.get();
+		return null;
 	}
 
 	@Override
 	public void start(Promise<Void> startPromise) {
-		final Future<Object> startHibernate = vertx.executeBlocking( this::startHibernate )
+		final Future<Object> startHibernate = vertx.executeBlocking( this::startHibernate, true )
 				.onSuccess( s -> LOG.infof( "✅ Hibernate Reactive is ready" ) );
 
 		Router router = Router.router( vertx );
diff --git a/integration-tests/verticle-postgres-it/src/test/java/org/hibernate/reactive/it/LocalContextTest.java b/integration-tests/verticle-postgres-it/src/test/java/org/hibernate/reactive/it/LocalContextTest.java
index 0c819a39..c2300977 100644
--- a/integration-tests/verticle-postgres-it/src/test/java/org/hibernate/reactive/it/LocalContextTest.java
+++ b/integration-tests/verticle-postgres-it/src/test/java/org/hibernate/reactive/it/LocalContextTest.java
@@ -31,7 +31,6 @@
 import io.vertx.junit5.VertxExtension;
 import io.vertx.junit5.VertxTestContext;
 
-import static io.vertx.core.CompositeFuture.all;
 import static io.vertx.core.Future.all;
 import static io.vertx.core.Future.failedFuture;
 import static io.vertx.core.Future.succeededFuture;
@@ -88,7 +87,7 @@ public void testProductsGeneration(VertxTestContext context) {
 				.compose( this::findProducts )
 				.onSuccess( res -> context.completeNow() )
 				.onFailure( context::failNow )
-				.eventually( unused -> vertx.close() );
+				.eventually( vertx::close );
 	}
 
 	/**
@@ -97,7 +96,7 @@ public void testProductsGeneration(VertxTestContext context) {
 	 * @see #REQUEST_NUMBER
 	 */
 	private Future<?> createProducts(WebClient webClient) {
-		List<Future> postRequests = new ArrayList<>();
+		List<Future<?>> postRequests = new ArrayList<>();
 		for ( int i = 0; i < REQUEST_NUMBER; i++ ) {
 			final Product product = new Product( i + 1 );
 
diff --git a/tooling/jbang/CockroachDBReactiveTest.java.qute b/tooling/jbang/CockroachDBReactiveTest.java.qute
index 43ca4432..d0ebda56 100755
--- a/tooling/jbang/CockroachDBReactiveTest.java.qute
+++ b/tooling/jbang/CockroachDBReactiveTest.java.qute
@@ -5,8 +5,8 @@
  * Copyright: Red Hat Inc. and Hibernate Authors
  */
 
-//DEPS io.vertx:vertx-pg-client:$\{vertx.version:4.5.15}
-//DEPS io.vertx:vertx-unit:$\{vertx.version:4.5.15}
+//DEPS io.vertx:vertx-pg-client:$\{vertx.version:5.0.0}
+//DEPS io.vertx:vertx-unit:$\{vertx.version:5.0.0}
 //DEPS org.hibernate.reactive:hibernate-reactive-core:$\{hibernate-reactive.version:4.0.0.Final}
 //DEPS org.assertj:assertj-core:3.27.3
 //DEPS junit:junit:4.13.2
diff --git a/tooling/jbang/Db2ReactiveTest.java.qute b/tooling/jbang/Db2ReactiveTest.java.qute
index 3a0f544e..d9396c13 100755
--- a/tooling/jbang/Db2ReactiveTest.java.qute
+++ b/tooling/jbang/Db2ReactiveTest.java.qute
@@ -5,8 +5,8 @@
  * Copyright: Red Hat Inc. and Hibernate Authors
  */
 
-//DEPS io.vertx:vertx-db2-client:$\{vertx.version:4.5.15}
-//DEPS io.vertx:vertx-unit:$\{vertx.version:4.5.15}
+//DEPS io.vertx:vertx-db2-client:$\{vertx.version:5.0.0}
+//DEPS io.vertx:vertx-unit:$\{vertx.version:5.0.0}
 //DEPS org.hibernate.reactive:hibernate-reactive-core:$\{hibernate-reactive.version:4.0.0.Final}
 //DEPS org.assertj:assertj-core:3.27.3
 //DEPS junit:junit:4.13.2
diff --git a/tooling/jbang/MariaDBReactiveTest.java.qute b/tooling/jbang/MariaDBReactiveTest.java.qute
index b6eb4ace..d3f30414 100755
--- a/tooling/jbang/MariaDBReactiveTest.java.qute
+++ b/tooling/jbang/MariaDBReactiveTest.java.qute
@@ -5,8 +5,8 @@
  * Copyright: Red Hat Inc. and Hibernate Authors
  */
 
-//DEPS io.vertx:vertx-mysql-client:$\{vertx.version:4.5.15}
-//DEPS io.vertx:vertx-unit:$\{vertx.version:4.5.15}
+//DEPS io.vertx:vertx-mysql-client:$\{vertx.version:5.0.0}
+//DEPS io.vertx:vertx-unit:$\{vertx.version:5.0.0}
 //DEPS org.hibernate.reactive:hibernate-reactive-core:$\{hibernate-reactive.version:4.0.0.Final}
 //DEPS org.assertj:assertj-core:3.27.3
 //DEPS junit:junit:4.13.2
diff --git a/tooling/jbang/MySQLReactiveTest.java.qute b/tooling/jbang/MySQLReactiveTest.java.qute
index 9747f989..67925f99 100755
--- a/tooling/jbang/MySQLReactiveTest.java.qute
+++ b/tooling/jbang/MySQLReactiveTest.java.qute
@@ -5,8 +5,8 @@
  * Copyright: Red Hat Inc. and Hibernate Authors
  */
 
-//DEPS io.vertx:vertx-mysql-client:$\{vertx.version:4.5.15}
-//DEPS io.vertx:vertx-unit:$\{vertx.version:4.5.15}
+//DEPS io.vertx:vertx-mysql-client:$\{vertx.version:5.0.0}
+//DEPS io.vertx:vertx-unit:$\{vertx.version:5.0.0}
 //DEPS org.hibernate.reactive:hibernate-reactive-core:$\{hibernate-reactive.version:4.0.0.Final}
 //DEPS org.assertj:assertj-core:3.27.3
 //DEPS junit:junit:4.13.2
diff --git a/tooling/jbang/PostgreSQLReactiveTest.java.qute b/tooling/jbang/PostgreSQLReactiveTest.java.qute
index 54ba2c45..0993b922 100755
--- a/tooling/jbang/PostgreSQLReactiveTest.java.qute
+++ b/tooling/jbang/PostgreSQLReactiveTest.java.qute
@@ -5,8 +5,8 @@
  * Copyright: Red Hat Inc. and Hibernate Authors
  */
 
-//DEPS io.vertx:vertx-pg-client:$\{vertx.version:4.5.15}
-//DEPS io.vertx:vertx-unit:$\{vertx.version:4.5.15}
+//DEPS io.vertx:vertx-pg-client:$\{vertx.version:5.0.0}
+//DEPS io.vertx:vertx-unit:$\{vertx.version:5.0.0}
 //DEPS org.hibernate.reactive:hibernate-reactive-core:$\{hibernate-reactive.version:4.0.0.Final}
 //DEPS org.assertj:assertj-core:3.27.3
 //DEPS junit:junit:4.13.2
diff --git a/tooling/jbang/ReactiveTest.java b/tooling/jbang/ReactiveTest.java
index 116c60a8..28656a50 100755
--- a/tooling/jbang/ReactiveTest.java
+++ b/tooling/jbang/ReactiveTest.java
@@ -5,11 +5,11 @@
  */
 
 ///usr/bin/env jbang "$0" "$@" ; exit $?
-//DEPS io.vertx:vertx-pg-client:${vertx.version:4.5.15}
-//DEPS com.ongres.scram:client:2.1
-//DEPS io.vertx:vertx-db2-client:${vertx.version:4.5.15}
-//DEPS io.vertx:vertx-mysql-client:${vertx.version:4.5.15}
-//DEPS io.vertx:vertx-unit:${vertx.version:4.5.15}
+//DEPS io.vertx:vertx-pg-client:${vertx.version:5.0.0}
+//DEPS com.ongres.scram:scram-client:3.1
+//DEPS io.vertx:vertx-db2-client:${vertx.version:5.0.0}
+//DEPS io.vertx:vertx-mysql-client:${vertx.version:5.0.0}
+//DEPS io.vertx:vertx-unit:${vertx.version:5.0.0}
 //DEPS org.hibernate.reactive:hibernate-reactive-core:${hibernate-reactive.version:4.0.0.Final}
 //DEPS org.assertj:assertj-core:3.27.3
 //DEPS junit:junit:4.13.2