From d15360b62eedd513cd4dc2c652261d4d23aef67d Mon Sep 17 00:00:00 2001 From: blafond Date: Tue, 22 Mar 2022 14:01:54 -0500 Subject: [PATCH] [#929] H2 client pool and build dependencies --- hibernate-reactive-core/build.gradle | 5 + .../DefaultSqlClientPoolConfiguration.java | 7 + .../reactive/pool/impl/H2SqlClientPool.java | 127 ++++++++++++++++++ .../service/NoJdbcEnvironmentInitiator.java | 4 + 4 files changed, 143 insertions(+) create mode 100644 hibernate-reactive-core/src/main/java/org/hibernate/reactive/pool/impl/H2SqlClientPool.java diff --git a/hibernate-reactive-core/build.gradle b/hibernate-reactive-core/build.gradle index 54ce895835..3b116f134e 100644 --- a/hibernate-reactive-core/build.gradle +++ b/hibernate-reactive-core/build.gradle @@ -26,6 +26,9 @@ dependencies { //Specific implementation details of Hibernate Reactive: implementation "io.vertx:vertx-sql-client:${vertxVersion}" + implementation 'io.agroal:agroal-api:1.12' + implementation 'io.agroal:agroal-pool:1.12' + implementation "io.vertx:vertx-jdbc-client:${vertxVersion}" // Testing testImplementation 'org.assertj:assertj-core:3.20.2' @@ -65,6 +68,8 @@ dependencies { testImplementation "org.testcontainers:cockroachdb:${testcontainersVersion}" testImplementation "org.testcontainers:mssqlserver:${testcontainersVersion}" testImplementation "org.testcontainers:oracle-xe:${testcontainersVersion}" + + testImplementation "com.h2database:h2:2.1.210" } // Print a summary of the results of the tests (number of failures, successes and skipped) diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/pool/impl/DefaultSqlClientPoolConfiguration.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/pool/impl/DefaultSqlClientPoolConfiguration.java index 2e114d4bc9..412ead56c7 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/pool/impl/DefaultSqlClientPoolConfiguration.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/pool/impl/DefaultSqlClientPoolConfiguration.java @@ -92,6 +92,13 @@ public PoolOptions poolOptions() { @Override public SqlConnectOptions connectOptions(URI uri) { String scheme = uri.getScheme(); + if( scheme.equalsIgnoreCase( "h2" )) { + return new SqlConnectOptions() + // username + .setUser("sa") + // password + .setPassword(""); + } String path = scheme.equals( "oracle" ) ? oraclePath( uri ) : uri.getPath(); diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/pool/impl/H2SqlClientPool.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/pool/impl/H2SqlClientPool.java new file mode 100644 index 0000000000..b49ab06c6d --- /dev/null +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/pool/impl/H2SqlClientPool.java @@ -0,0 +1,127 @@ +/* Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.reactive.pool.impl; + + +import java.lang.invoke.MethodHandles; +import java.net.URI; +import java.util.Map; +import java.util.concurrent.CompletionStage; + +import org.hibernate.HibernateError; +import org.hibernate.engine.jdbc.spi.JdbcServices; +import org.hibernate.engine.jdbc.spi.SqlStatementLogger; +import org.hibernate.internal.util.config.ConfigurationHelper; +import org.hibernate.reactive.logging.impl.Log; +import org.hibernate.reactive.logging.impl.LoggerFactory; +import org.hibernate.reactive.provider.Settings; +import org.hibernate.reactive.vertx.VertxInstance; +import org.hibernate.service.spi.Configurable; +import org.hibernate.service.spi.ServiceRegistryAwareService; +import org.hibernate.service.spi.ServiceRegistryImplementor; +import org.hibernate.service.spi.Startable; +import org.hibernate.service.spi.Stoppable; + +import io.vertx.core.Future; +import io.vertx.core.Vertx; +import io.vertx.jdbcclient.JDBCConnectOptions; +import io.vertx.jdbcclient.JDBCPool; +import io.vertx.sqlclient.Pool; +import io.vertx.sqlclient.PoolOptions; +import io.vertx.sqlclient.SqlConnectOptions; + +public class H2SqlClientPool extends SqlClientPool + implements ServiceRegistryAwareService, Configurable, Stoppable, Startable { + + private static final Log LOG = LoggerFactory.make( Log.class, MethodHandles.lookup() ); + + //Asynchronous shutdown promise: we can't return it from #close as we implement a + //blocking interface. + private volatile Future closeFuture = Future.succeededFuture(); + + private Pool pools; + private URI uri; + private SqlStatementLogger sqlStatementLogger; + private ServiceRegistryImplementor serviceRegistry; + + public H2SqlClientPool() { + } + + @Override + public void injectServices(ServiceRegistryImplementor serviceRegistry) { + this.serviceRegistry = serviceRegistry; + sqlStatementLogger = serviceRegistry.getService( JdbcServices.class ).getSqlStatementLogger(); + } + + @Override + public void configure(Map configuration) { + uri = jdbcUrl( configuration ); + } + + @Override + public void start() { + if ( pools == null ) { + pools = createPool( uri ); + } + } + + @Override + public CompletionStage getCloseFuture() { + return closeFuture.toCompletionStage(); + } + + @Override + protected Pool getPool() { + return pools; + } + + private Pool createPool(URI uri) { + SqlClientPoolConfiguration configuration = serviceRegistry.getService( SqlClientPoolConfiguration.class ); + VertxInstance vertx = serviceRegistry.getService( VertxInstance.class ); + return createPool( uri, configuration.connectOptions( uri ), configuration.poolOptions(), vertx.getVertx() ); + } + + private Pool createPool(URI uri, SqlConnectOptions connectOptions, PoolOptions poolOptions, Vertx vertx) { + JDBCConnectOptions jdbcOptions = new JDBCConnectOptions(); + jdbcOptions.setUser( connectOptions.getUser() ); + jdbcOptions.setJdbcUrl( "jdbc:" + uri.toString() ); + JDBCPool pool = JDBCPool.pool( vertx, jdbcOptions, poolOptions ); + return pool; + } + + private URI jdbcUrl(Map configurationValues) { + String url = ConfigurationHelper.getString( Settings.URL, configurationValues ); + LOG.sqlClientUrl( url ); + return parse( url ); + } + + @Override + public void stop() { + if ( pools != null ) { + this.closeFuture = pools.close(); + } + } + + public static URI parse(String url) { + + if ( url == null || url.trim().isEmpty() ) { + throw new HibernateError( + "The configuration property '" + Settings.URL + "' was not provided, or is in invalid format. This is required when using the default DefaultSqlClientPool: " + + "either provide the configuration setting or integrate with a different SqlClientPool implementation" ); + } + + if ( url.startsWith( "jdbc:" ) ) { + return URI.create( url.substring( 5 ) ); + } + + return URI.create( url ); + } + + @Override + protected SqlStatementLogger getSqlStatementLogger() { + return sqlStatementLogger; + } +} diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/provider/service/NoJdbcEnvironmentInitiator.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/provider/service/NoJdbcEnvironmentInitiator.java index e1975380fb..8371a6f02c 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/provider/service/NoJdbcEnvironmentInitiator.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/provider/service/NoJdbcEnvironmentInitiator.java @@ -9,6 +9,7 @@ import org.hibernate.dialect.CockroachDB201Dialect; import org.hibernate.dialect.DB297Dialect; import org.hibernate.dialect.Dialect; +import org.hibernate.dialect.H2Dialect; import org.hibernate.dialect.MariaDB103Dialect; import org.hibernate.dialect.MySQL8Dialect; import org.hibernate.dialect.Oracle12cDialect; @@ -147,6 +148,9 @@ else if ( url.startsWith( "sqlserver:" ) ) { else if ( url.startsWith( "oracle:" ) ) { return Oracle12cDialect.class; } + else if ( url.startsWith( "h2:" ) ) { + return H2Dialect.class; + } else { return null; }