Skip to content

Commit

Permalink
[hibernate#929] hibernate-reactive-h2 module
Browse files Browse the repository at this point in the history
  • Loading branch information
blafond authored and DavideD committed Jun 22, 2022
1 parent bff1835 commit 0a4946e
Show file tree
Hide file tree
Showing 10 changed files with 309 additions and 0 deletions.
60 changes: 60 additions & 0 deletions hibernate-reactive-h2/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
ext {
mavenPomName = 'Hibernate Reactive H2'
}

description = 'The H2 module of Hibernate Reactive'

apply from: publishScript

dependencies {
implementation project(':hibernate-reactive-core')
implementation "com.h2database:h2:2.1.214"

// Dependencies for using H2 with Vert.x:
implementation "io.vertx:vertx-jdbc-client:${vertxVersion}"

// Testing
testImplementation 'org.assertj:assertj-core:3.20.2'
testImplementation "io.vertx:vertx-unit:${vertxVersion}"

// log4j
testRuntimeOnly 'org.apache.logging.log4j:log4j-core:2.17.1'
}

// Print a summary of the results of the tests (number of failures, successes and skipped)
def loggingSummary(db, result, desc) {
if ( !desc.parent ) { // will match the outermost suite
def output = "${db} results: ${result.resultType} (${result.testCount} tests, ${result.successfulTestCount} passed, ${result.failedTestCount} failed, ${result.skippedTestCount} skipped)"
def repeatLength = output.length() + 1
logger.lifecycle '\n' + ('-' * repeatLength) + '\n' + output + '\n' + ('-' * repeatLength)
}
}

// Configuration for the tests
tasks.withType(Test) {
defaultCharacterEncoding = "UTF-8"
testLogging {
displayGranularity 1
showStandardStreams = project.hasProperty('showStandardOutput')
showStackTraces = true
exceptionFormat = 'full'
events 'PASSED', 'FAILED', 'SKIPPED'
}
systemProperty 'org.hibernate.reactive.common.InternalStateAssertions.ENFORCE', 'true'

if ( project.hasProperty( 'includeTests' ) ) {
// Example: ./gradlew testAll -PincludeTests=DefaultPortTest
filter {
includeTestsMatching project.getProperty( 'includeTests' ) ?: '*'
}
}
}

test {
afterSuite { desc, result ->
loggingSummary( 'H2', result, desc )
}
doFirst {
systemProperty 'db', 'H2'
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/* Hibernate, Relational Persistence for Idiomatic Java
*
* SPDX-License-Identifier: Apache-2.0
* Copyright: Red Hat Inc. and Hibernate Authors
*/
package org.hibernate.reactive.jdbc.boot.impl;

import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.reactive.jdbc.pool.impl.H2ReactiveConnectionPoolInitiator;
import org.hibernate.service.spi.ServiceContributor;

public class H2ServiceContributor implements ServiceContributor {
@Override
public void contribute(StandardServiceRegistryBuilder serviceRegistryBuilder) {
serviceRegistryBuilder.addInitiator( H2ReactiveConnectionPoolInitiator.INSTANCE );
serviceRegistryBuilder.addInitiator( JdbcSqlClientPoolConfigurationInitiator.INSTANCE );
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/* Hibernate, Relational Persistence for Idiomatic Java
*
* SPDX-License-Identifier: Apache-2.0
* Copyright: Red Hat Inc. and Hibernate Authors
*/
package org.hibernate.reactive.jdbc.boot.impl;

import java.util.Map;

import org.hibernate.boot.registry.StandardServiceInitiator;
import org.hibernate.reactive.jdbc.pool.impl.H2ClientPoolConfiguration;
import org.hibernate.reactive.pool.impl.JdbcClientPoolConfiguration;
import org.hibernate.service.spi.ServiceRegistryImplementor;

public class JdbcSqlClientPoolConfigurationInitiator implements StandardServiceInitiator<JdbcClientPoolConfiguration> {

public static final JdbcSqlClientPoolConfigurationInitiator INSTANCE = new JdbcSqlClientPoolConfigurationInitiator() {
};

@Override
public JdbcClientPoolConfiguration initiateService(Map configurationValues, ServiceRegistryImplementor registry) {
return new H2ClientPoolConfiguration();
}

@Override
public Class<JdbcClientPoolConfiguration> getServiceInitiated() {
return JdbcClientPoolConfiguration.class;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/**
// * Hibernate Reactive is an adaptation of Hibernate ORM to the
// * world of reactive programming, and replaces JDBC for database
// * access with a non-blocking database client.
// * <p>
// * <p>
*/
package org.hibernate.reactive.jdbc;
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/* Hibernate, Relational Persistence for Idiomatic Java
*
* SPDX-License-Identifier: Apache-2.0
* Copyright: Red Hat Inc. and Hibernate Authors
*/
package org.hibernate.reactive.jdbc.pool.impl;

import java.net.URI;

import org.hibernate.reactive.pool.impl.DefaultSqlClientPoolConfiguration;
import org.hibernate.reactive.pool.impl.JdbcClientPoolConfiguration;

import io.vertx.core.json.JsonObject;

public class H2ClientPoolConfiguration extends DefaultSqlClientPoolConfiguration implements JdbcClientPoolConfiguration {

@Override
public JsonObject jdbcConnectOptions(URI uri) {
return new JsonObject()
.put( "url", uri.toString() )
.put( "user", "sa" )
.put( "pass", null );
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/* Hibernate, Relational Persistence for Idiomatic Java
*
* SPDX-License-Identifier: Apache-2.0
* Copyright: Red Hat Inc. and Hibernate Authors
*/
package org.hibernate.reactive.jdbc.pool.impl;

import java.util.Map;

import org.hibernate.internal.util.config.ConfigurationHelper;
import org.hibernate.reactive.pool.ReactiveConnectionPool;
import org.hibernate.reactive.pool.impl.ReactiveConnectionPoolInitiator;
import org.hibernate.reactive.provider.Settings;
import org.hibernate.service.spi.ServiceRegistryImplementor;

public class H2ReactiveConnectionPoolInitiator extends ReactiveConnectionPoolInitiator {

public static final H2ReactiveConnectionPoolInitiator INSTANCE = new H2ReactiveConnectionPoolInitiator();

@Override
public ReactiveConnectionPool initiateService(Map configurationValues, ServiceRegistryImplementor registry) {
String url = ConfigurationHelper.getString( Settings.URL, configurationValues );
// Check URL for H2 and return H2 specific pool
if ( url.startsWith( "jdbc:h2:" ) ) {
return new H2SqlClientPool();
}

// delegate to super class to initiate the DefaultSqlClientPool
return super.initiateService( configurationValues, registry );
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/* Hibernate, Relational Persistence for Idiomatic Java
*
* SPDX-License-Identifier: Apache-2.0
* Copyright: Red Hat Inc. and Hibernate Authors
*/
package org.hibernate.reactive.jdbc.pool.impl;


import java.lang.invoke.MethodHandles;
import java.net.URI;
import java.util.Map;
import java.util.concurrent.CompletionStage;

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.pool.impl.JdbcClientPoolConfiguration;
import org.hibernate.reactive.pool.impl.SqlClientPool;
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.json.JsonObject;
import io.vertx.jdbcclient.JDBCPool;
import io.vertx.sqlclient.Pool;

public class H2SqlClientPool extends SqlClientPool
implements ServiceRegistryAwareService, Configurable, Stoppable, Startable {

private static final Log LOG = LoggerFactory.make( Log.class, MethodHandles.lookup() );

public static final String DEFAULT_URL = "jdbc:h2:mem:hreact";

//Asynchronous shutdown promise: we can't return it from #close as we implement a
//blocking interface.
private volatile Future<Void> 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 );
}

protected URI jdbcUrl(Map<?,?> configurationValues) {
String url = ConfigurationHelper.getString( Settings.URL, configurationValues, DEFAULT_URL );
LOG.sqlClientUrl( url);
return URI.create( url );
}

@Override
public void start() {
if ( pools == null ) {
pools = createPool( uri );
}
}

@Override
public CompletionStage<Void> getCloseFuture() {
return closeFuture.toCompletionStage();
}

@Override
protected Pool getPool() {
return pools;
}

private Pool createPool(URI uri) {
JdbcClientPoolConfiguration configuration = serviceRegistry.getService( JdbcClientPoolConfiguration.class );
VertxInstance vertx = serviceRegistry.getService( VertxInstance.class );
JsonObject poolOptions = configuration.poolOptions().toJson();
JsonObject connectOptions = configuration.jdbcConnectOptions( uri );
JsonObject config = poolOptions.mergeIn( connectOptions );
return JDBCPool.pool( vertx.getVertx(), config );
}

@Override
public void stop() {
if ( pools != null ) {
this.closeFuture = pools.close();
}
}

@Override
protected SqlStatementLogger getSqlStatementLogger() {
return sqlStatementLogger;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/* 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.net.URI;

import org.hibernate.service.Service;

import io.vertx.core.json.JsonObject;
import io.vertx.sqlclient.PoolOptions;

public interface JdbcClientPoolConfiguration extends Service {
/**
* The {@link PoolOptions} used to configure the {@code Pool}
*/
PoolOptions poolOptions();

/**
* The {@link JsonObject} used to configure the {@code Pool}
*
* @param uri A {@link URI} representing the JDBC URL or connection URI
* specified in the configuration properties, usually via
* {@link org.hibernate.cfg.Environment#JPA_JDBC_URL}, or
* {@code null} if not specified.
*/
JsonObject jdbcConnectOptions(URI uri);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
org.hibernate.reactive.jdbc.pool.impl.H2SqlClientPool
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
org.hibernate.reactive.jdbc.boot.impl.H2ServiceContributor

0 comments on commit 0a4946e

Please sign in to comment.