From 07253ca7d0ceebe4d9bf027de20223043b092060 Mon Sep 17 00:00:00 2001 From: Davide Date: Mon, 28 Feb 2022 20:30:38 +0000 Subject: [PATCH 1/2] [#333] Only accept Vert.x style url --- .../hibernate/reactive/logging/impl/Log.java | 5 +- .../pool/impl/DefaultSqlClientPool.java | 14 +- .../DefaultSqlClientPoolConfiguration.java | 199 +----------------- .../hibernate/reactive/BaseReactiveTest.java | 11 +- .../hibernate/reactive/DefaultPortTest.java | 20 +- .../hibernate/reactive/MutinySessionTest.java | 4 + .../reactive/ORMReactivePersistenceTest.java | 12 ++ .../reactive/StandAloneReactiveTest.java | 2 +- .../org/hibernate/reactive/UriConfigTest.java | 2 +- .../configuration/JdbcUrlParserTest.java | 73 ------- .../ReactiveConnectionPoolTest.java | 6 +- .../containers/CockroachDBDatabase.java | 34 +-- .../reactive/containers/DB2Database.java | 31 +-- .../containers/DatabaseConfiguration.java | 8 +- .../containers/MSSQLServerDatabase.java | 31 +-- .../reactive/containers/MariaDatabase.java | 35 +-- .../reactive/containers/MySQLDatabase.java | 39 +--- .../reactive/containers/OracleDatabase.java | 54 ++--- .../containers/PostgreSQLDatabase.java | 35 +-- .../reactive/containers/TestableDatabase.java | 30 ++- .../containers/VertxMariaContainer.java | 122 ++++++----- .../containers/VertxMySqlContainer.java | 122 ++++++----- 22 files changed, 265 insertions(+), 624 deletions(-) delete mode 100644 hibernate-reactive-core/src/test/java/org/hibernate/reactive/configuration/JdbcUrlParserTest.java diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/logging/impl/Log.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/logging/impl/Log.java index 336da18ba..06c9774f0 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/logging/impl/Log.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/logging/impl/Log.java @@ -64,6 +64,10 @@ public interface Log extends BasicLogger { @Message(id = 18, value = "Instantiating reactive pool: %1$s") void instantiatingReactivePool(@FormatWith(ClassFormatter.class) Class implClass); + @Message(id = 19, value = "Cannot specify URL using the JDBC syntax. Check the Hibernate Reactive or Vert.x SQL client documentation for more details." + + " Invalid URL: %s") + HibernateException invalidJdbcUrl(String url); + @LogMessage(level = WARN) @Message(id = 21, value = "DDL command failed [%1$s]") void ddlCommandFailed(String message); @@ -253,5 +257,4 @@ public interface Log extends BasicLogger { @LogMessage(level = WARN) @Message(id = 447, value= "Explicit use of UPGRADE_SKIPLOCKED in lock() calls is not recommended; use normal UPGRADE locking instead") void explicitSkipLockedLockCombo(); - } 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 29a38bdc2..cfc4c925e 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 @@ -125,7 +125,7 @@ public void injectServices(ServiceRegistryImplementor serviceRegistry) { @Override public void configure(Map configuration) { - uri = jdbcUrl( configuration ); + uri = connectionUri( configuration ); } @Override @@ -198,7 +198,7 @@ protected Pool createPool(URI uri, SqlConnectOptions connectOptions, PoolOptions * * @return the JDBC URL as a {@link URI} */ - protected URI jdbcUrl(Map configurationValues) { + protected URI connectionUri(Map configurationValues) { String url = ConfigurationHelper.getString( Settings.URL, configurationValues ); LOG.sqlClientUrl( url); return parse( url ); @@ -240,21 +240,15 @@ public void stop() { } 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( updateUrl( url.substring( 5 ) ) ); + throw LOG.invalidJdbcUrl( url ); } - return URI.create( updateUrl( url ) ); - } - - private static String updateUrl(String url) { - return url.replaceAll( "^cockroachdb:", "postgres:" ); + return URI.create( url ); } - } 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 fb022d734..3acb7dad4 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 @@ -10,7 +10,6 @@ import java.util.Map; import java.util.concurrent.TimeUnit; -import org.hibernate.HibernateError; import org.hibernate.reactive.logging.impl.Log; import org.hibernate.reactive.logging.impl.LoggerFactory; import org.hibernate.reactive.provider.Settings; @@ -64,7 +63,6 @@ public void configure(Map configuration) { @Override public PoolOptions poolOptions() { PoolOptions poolOptions = new PoolOptions(); - LOG.connectionPoolSize( poolSize ); poolOptions.setMaxSize( poolSize ); if ( maxWaitQueueSize != null ) { @@ -90,122 +88,23 @@ public PoolOptions poolOptions() { @Override public SqlConnectOptions connectOptions(URI uri) { - String scheme = uri.getScheme(); - String path = scheme.equals( "oracle" ) - ? oraclePath( uri ) - : uri.getPath(); - - String database = path.length() > 0 - ? path.substring( 1 ) - : ""; + String url = uri.toString().replaceAll( "^cockroachdb:", "postgres:" ); + final SqlConnectOptions connectOptions = SqlConnectOptions.fromUri( url ); - if ( scheme.equals( "db2" ) && database.indexOf( ':' ) > 0 ) { - // DB2 URLs are a bit odd and have the format: - // jdbc:db2://:/:key1=value1;key2=value2; - database = database.substring( 0, database.indexOf( ':' ) ); + if ( connectOptions.getUser() == null && user == null ) { + throw new IllegalArgumentException( "database username not specified (set the property 'hibernate.connection.username', or include it as a parameter in the connection URL)" ); } - String host = scheme.equals( "oracle" ) - ? oracleHost( uri ) - : uri.getHost(); - - int port = scheme.equals( "oracle" ) - ? oraclePort( uri ) - : uri.getPort(); - - int index = uri.toString().indexOf( ';' ); - if ( scheme.equals( "sqlserver" ) && index > 0 ) { - // SQL Server separates parameters in the url with a semicolon (';') - // and the URI class doesn't get the right value for host and port when the url - // contains parameters - URI uriWithoutParams = URI.create( uri.toString().substring( 0, index ) ); - host = uriWithoutParams.getHost(); - port = uriWithoutParams.getPort(); + if ( user != null ) { + connectOptions.setUser( user ); } - if ( port == -1 ) { - port = defaultPort( scheme ); - } - - //see if the credentials were specified via properties - String username = user; - String password = pass; - if ( username == null || password == null ) { - //if not, look for URI-style user info first - String userInfo = uri.getUserInfo(); - if ( userInfo != null ) { - String[] bits = userInfo.split( ":" ); - username = bits[0]; - if ( bits.length > 1 ) { - password = bits[1]; - } - } - else { - //check the query for named parameters - //in case it's a JDBC-style URL - String[] params = {}; - // DB2 URLs are a bit odd and have the format: - // jdbc:db2://:/:key1=value1;key2=value2; - if ( scheme.equals( "db2" ) ) { - int queryIndex = uri.getPath().indexOf( ':' ) + 1; - if ( queryIndex > 0 ) { - params = uri.getPath().substring( queryIndex ).split( ";" ); - } - } - else if ( scheme.contains( "sqlserver" ) ) { - // SQL Server separates parameters in the url with a semicolon (';') - // Ex: jdbc:sqlserver://:;=AdventureWorks;user=;password= - String query = uri.getQuery(); - String rawQuery = uri.getRawQuery(); - String s = uri.toString(); - int queryIndex = s.indexOf( ';' ) + 1; - if ( queryIndex > 0 ) { - params = s.substring( queryIndex ).split( ";" ); - } - } - else { - final String query = scheme.equals( "oracle" ) - ? oracleQuery( uri ) - : uri.getQuery(); - if ( query != null ) { - params = query.split( "&" ); - } - } - for ( String param : params ) { - if ( param.startsWith( "user=" ) ) { - username = param.substring( 5 ); - } - else if ( param.startsWith( "pass=" ) ) { - password = param.substring( 5 ); - } - else if ( param.startsWith( "password=" ) ) { - password = param.substring( 9 ); - } - else if ( param.startsWith( "database=" ) ) { - database = param.substring( 9 ); - } - } - } - } - - if ( username == null ) { - throw new HibernateError( - "database username not specified (set the property 'javax.persistence.jdbc.user', or include it as a parameter in the connection URL)" ); - } - - SqlConnectOptions connectOptions = new SqlConnectOptions() - .setHost( host ) - .setPort( port ) - .setDatabase( database ) - .setUser( username ); - - if ( password != null ) { - connectOptions.setPassword( password ); + if ( pass != null ) { + connectOptions.setPassword( pass ); } //enable the prepared statement cache by default connectOptions.setCachePreparedStatements( true ); - if ( cacheMaxSize != null ) { if ( cacheMaxSize <= 0 ) { LOG.preparedStatementCacheDisabled(); @@ -225,86 +124,4 @@ else if ( param.startsWith( "database=" ) ) { return connectOptions; } - - private int oraclePort(URI uri) { - String s = uri.toString().substring( "oracle:thin:".length() ); - if ( s.indexOf( ':' ) > -1 ) { - // Example: localhost:1234... - s = s.substring( s.indexOf( ':' ) + 1 ); - if ( s.indexOf( '/' ) != -1 ) { - // Example: 1234/ - s = s.substring( 0, s.indexOf( '/' ) ); - return Integer.valueOf( s ); - } - if ( s.indexOf( '?' ) != -1 ) { - // Example: 1234?param=value - s = s.substring( 0, s.indexOf( '?' ) ); - return Integer.valueOf( s ); - } - // Example: 1234 - return Integer.valueOf( s ); - } - return -1; - } - - // For Oracle the host part starts with a '@' - // Example oracle:thin:[username/password]@localhost:1234/database?param=value - private String oracleHost(URI uri) { - String s = uri.toString(); - String host = s.substring( s.indexOf( '@' ) + 1 ); - int end = host.indexOf( ':' ); - if ( end == -1 ) { - end = host.indexOf( '/' ); - if ( end == -1) { - end = host.indexOf( '?' ); - } - } - return host.substring( 0, end ); - } - - private String oracleQuery(URI uri) { - String string = uri.toString(); - int start = string.indexOf( '?' ); - return start == -1 - ? null - : string.substring( start + 1 ); - } - - private String oraclePath(URI uri) { - String string = uri.toString(); - // Remove everything before localhost:port - final int i = string.indexOf( '@' ); - string = string.substring( i + 1 ); - // Check the start of the path - int start = string.indexOf( '/' ); - if ( start == -1) { - return ""; - } - int end = string.indexOf( '?' ) == -1 - ? string.length() - : string.indexOf( '?' ); - return string.substring( start, end ); - } - - private int defaultPort(String scheme) { - switch ( scheme ) { - case "postgresql": - case "postgres": - return 5432; - case "mariadb": - case "mysql": - return 3306; - case "db2": - return 50000; - case "cockroachdb": - return 26257; - case "sqlserver": - return 1433; - case "oracle": - return 1521; - default: - throw new IllegalArgumentException( "Unknown default port for scheme: " + scheme ); - } - } - } 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 04cee4b79..71cafe7f0 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 @@ -9,6 +9,7 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; import java.util.concurrent.TimeUnit; +import java.util.function.Supplier; import java.util.stream.Collectors; import org.hibernate.SessionFactory; @@ -119,7 +120,7 @@ public static void test(Async async, TestContext context, Uni uni) { protected Configuration constructConfiguration() { Configuration configuration = new Configuration(); configuration.setProperty( Settings.HBM2DDL_AUTO, "create" ); - configuration.setProperty( Settings.URL, DatabaseConfiguration.getJdbcUrl() ); + configuration.setProperty( Settings.URL, DatabaseConfiguration.getConnectionUri() ); if ( DatabaseConfiguration.dbType() == DBType.DB2 && !doneTablespace ) { configuration.setProperty(Settings.HBM2DDL_IMPORT_FILES, "/db2.sql"); doneTablespace = true; @@ -153,17 +154,21 @@ public CompletionStage deleteEntities(String... entities) { @Before public void before(TestContext context) { - test( context, setupSessionFactory( constructConfiguration() ) ); + test( context, setupSessionFactory( () -> constructConfiguration() ) ); } protected CompletionStage setupSessionFactory(Configuration configuration) { + return setupSessionFactory( () -> configuration ); + } + + protected CompletionStage setupSessionFactory(Supplier configurationSupplier) { CompletableFuture future = new CompletableFuture<>(); vertxContextRule.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, configuration ), + promise -> startFactoryManager( promise, configurationSupplier.get() ), event -> { if ( event.succeeded() ) { future.complete( null ); diff --git a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/DefaultPortTest.java b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/DefaultPortTest.java index 05c913441..b08d82a1b 100644 --- a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/DefaultPortTest.java +++ b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/DefaultPortTest.java @@ -8,12 +8,13 @@ import java.net.URI; import java.net.URISyntaxException; import java.util.HashMap; -import java.util.Locale; import java.util.Map; +import java.util.ServiceConfigurationError; import org.hibernate.reactive.containers.DatabaseConfiguration; import org.hibernate.reactive.pool.impl.DefaultSqlClientPoolConfiguration; import org.hibernate.reactive.provider.Settings; +import org.hibernate.reactive.testing.DatabaseSelectionRule; import org.junit.Rule; import org.junit.Test; @@ -22,6 +23,7 @@ import io.vertx.sqlclient.SqlConnectOptions; import org.assertj.core.api.Assertions; +import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.ORACLE; import static org.hibernate.reactive.containers.DatabaseConfiguration.dbType; /** @@ -29,6 +31,9 @@ */ public class DefaultPortTest { + @Rule + public DatabaseSelectionRule skipDbs = DatabaseSelectionRule.skipTestsFor( ORACLE ); + @Rule public ExpectedException thrown = ExpectedException.none(); @@ -36,7 +41,7 @@ public class DefaultPortTest { public void testDefaultPortIsSet() throws URISyntaxException { DefaultSqlClientPoolConfiguration configuration = new DefaultSqlClientPoolConfiguration(); configuration.configure( requiredProperties() ); - SqlConnectOptions sqlConnectOptions = configuration.connectOptions( new URI( scheme() + "://localhost/database" ) ); + SqlConnectOptions sqlConnectOptions = configuration.connectOptions( new URI( uriString() ) ); Assertions.assertThat( sqlConnectOptions.getPort() ) .as( "Default port not defined for " + dbType() ) .isEqualTo( dbType().getDefaultPort() ); @@ -44,17 +49,20 @@ public void testDefaultPortIsSet() throws URISyntaxException { @Test public void testUnrecognizedSchemeException() throws URISyntaxException { - thrown.expect( IllegalArgumentException.class ); + thrown.expect( ServiceConfigurationError.class ); URI uri = new URI( "bogusScheme://localhost/database" ); new DefaultSqlClientPoolConfiguration().connectOptions( uri ); } - private static String scheme() { + private static String uriString() { if ( dbType() == DatabaseConfiguration.DBType.MARIA ) { - return "mariadb"; + return "mariadb://localhost/database"; + } + if ( dbType() == ORACLE ) { + return "oracle:thin:@localhost:orcl"; } - return dbType().name().toLowerCase( Locale.ROOT ); + return dbType().name().toLowerCase() + "://localhost/database"; } // Only set the required properties 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 7cdc6e71c..7f64eb776 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 @@ -539,6 +539,10 @@ public void testSessionPropagation(TestContext context) { } ) ); } + private void metodo() { + + } + @Test public void testDupeException(TestContext context) { test( diff --git a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/ORMReactivePersistenceTest.java b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/ORMReactivePersistenceTest.java index 917b7b86f..cbdc27768 100644 --- a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/ORMReactivePersistenceTest.java +++ b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/ORMReactivePersistenceTest.java @@ -24,8 +24,12 @@ import org.junit.Test; import io.vertx.ext.unit.TestContext; +import org.jetbrains.annotations.NotNull; import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.POSTGRESQL; +import static org.hibernate.reactive.containers.DatabaseConfiguration.PASSWORD; +import static org.hibernate.reactive.containers.DatabaseConfiguration.USERNAME; +import static org.hibernate.reactive.containers.DatabaseConfiguration.getConnectionUri; /** * This test class verifies that data can be persisted and queried on the same database @@ -48,8 +52,11 @@ protected Configuration constructConfiguration() { @Before public void prepareOrmFactory() { Configuration configuration = constructConfiguration(); + configuration.setProperty( Settings.USER, USERNAME ); + configuration.setProperty( Settings.PASS, PASSWORD ); configuration.setProperty( Settings.DRIVER, "org.postgresql.Driver" ); configuration.setProperty( Settings.DIALECT, "org.hibernate.dialect.PostgreSQL95Dialect"); + configuration.setProperty( Settings.URL, jdbcConnectionUrl() ); StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder() .applySettings( configuration.getProperties() ); @@ -58,6 +65,11 @@ public void prepareOrmFactory() { ormFactory = configuration.buildSessionFactory( registry ); } + @NotNull + private String jdbcConnectionUrl() { + return "jdbc:" + getConnectionUri().replaceAll( USERNAME + ":" + PASSWORD + "@", "" ); + } + @After public void cleanDb(TestContext context) { ormFactory.close(); diff --git a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/StandAloneReactiveTest.java b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/StandAloneReactiveTest.java index 12473b6f7..d321550e2 100644 --- a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/StandAloneReactiveTest.java +++ b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/StandAloneReactiveTest.java @@ -22,7 +22,7 @@ public void createReactiveSessionFactory() { StandardServiceRegistry registry = new ReactiveServiceRegistryBuilder() .applySetting( Settings.TRANSACTION_COORDINATOR_STRATEGY, "jta" ) .applySetting( Settings.DIALECT, PostgreSQL9Dialect.class.getName() ) - .applySetting( Settings.URL, "jdbc:postgresql://localhost/hreact?user=none" ) + .applySetting( Settings.URL, "postgresql://localhost/hreact?user=none" ) .build(); Stage.SessionFactory factory = new MetadataSources( registry ) diff --git a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/UriConfigTest.java b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/UriConfigTest.java index 7a0c96a0a..2b2e9fa40 100644 --- a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/UriConfigTest.java +++ b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/UriConfigTest.java @@ -42,7 +42,7 @@ protected Configuration constructConfiguration() { Configuration configuration = super.constructConfiguration(); configuration.setProperty( Environment.DIALECT, dialect.getName() ); - configuration.setProperty( Settings.URL, DatabaseConfiguration.getUri() ); + configuration.setProperty( Settings.URL, DatabaseConfiguration.getConnectionUri() ); configuration.setProperty( Settings.SQL_CLIENT_POOL_CONFIG, UriPoolConfiguration.class.getName() ); return configuration; } diff --git a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/configuration/JdbcUrlParserTest.java b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/configuration/JdbcUrlParserTest.java deleted file mode 100644 index 0aa9a0518..000000000 --- a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/configuration/JdbcUrlParserTest.java +++ /dev/null @@ -1,73 +0,0 @@ -/* Hibernate, Relational Persistence for Idiomatic Java - * - * SPDX-License-Identifier: Apache-2.0 - * Copyright: Red Hat Inc. and Hibernate Authors - */ -package org.hibernate.reactive.configuration; - -import org.hibernate.HibernateError; -import org.hibernate.reactive.pool.impl.DefaultSqlClientPool; -import org.hibernate.reactive.pool.impl.DefaultSqlClientPoolConfiguration; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -import java.net.URI; - -import io.vertx.sqlclient.SqlConnectOptions; - -import static org.assertj.core.api.Assertions.assertThat; - -public class JdbcUrlParserTest { - - @Rule - public ExpectedException thrown = ExpectedException.none(); - - @Test - public void returnsNullForNull() { - thrown.expect( HibernateError.class ); - URI uri = DefaultSqlClientPool.parse( null ); - assertThat( uri ).isNull(); - } - - @Test - public void invalidParameter() { - thrown.expect( HibernateError.class ); - URI uri = DefaultSqlClientPool.parse( "jdbc:postgresql://localhost:5432/hreact"); - DefaultSqlClientPoolConfiguration cfg = new DefaultSqlClientPoolConfiguration(); - final SqlConnectOptions connectOptions = cfg.connectOptions( uri ); - } - - @Test - public void parameters() { - URI uri = DefaultSqlClientPool.parse( "jdbc:postgresql://localhost:5432/hreact?user=hello"); - DefaultSqlClientPoolConfiguration cfg = new DefaultSqlClientPoolConfiguration(); - final SqlConnectOptions connectOptions = cfg.connectOptions( uri ); - assertThat(connectOptions).isNotNull(); - } - - @Test - public void uriCreation() { - URI uri = DefaultSqlClientPool.parse( "jdbc:postgresql://localhost:5432/hreact"); - assertThat(uri).isNotNull(); - } - - @Test - public void parsePort() { - URI uri = DefaultSqlClientPool.parse( "jdbc:postgresql://localhost:5432/hreact"); - assertThat(uri).hasPort(5432); - } - - @Test - public void parseHost() { - URI uri = DefaultSqlClientPool.parse( "jdbc:postgresql://localhost:5432/hreact"); - assertThat(uri).hasHost("localhost"); - } - - @Test - public void parseScheme() { - URI uri = DefaultSqlClientPool.parse( "jdbc:postgresql://localhost:5432/hreact"); - assertThat(uri).hasScheme("postgresql"); - } -} diff --git a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/configuration/ReactiveConnectionPoolTest.java b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/configuration/ReactiveConnectionPoolTest.java index b56c52d84..2605bc2e3 100644 --- a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/configuration/ReactiveConnectionPoolTest.java +++ b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/configuration/ReactiveConnectionPoolTest.java @@ -85,7 +85,7 @@ public SqlStatementLogger getSqlStatementLogger() { @Test public void configureWithJdbcUrl(TestContext context) { - String url = DatabaseConfiguration.getJdbcUrl(); + String url = DatabaseConfiguration.getConnectionUri(); Map config = new HashMap<>(); config.put( Settings.URL, url ); ReactiveConnectionPool reactivePool = configureAndStartPool( config ); @@ -96,7 +96,7 @@ public void configureWithJdbcUrl(TestContext context) { public void configureWithCredentials(TestContext context) { // Set up URL with invalid credentials so we can ensure that // explicit USER and PASS settings take precedence over credentials in the URL - String url = DatabaseConfiguration.getJdbcUrl(); + String url = DatabaseConfiguration.getConnectionUri(); url = url.replace( "user=" + DatabaseConfiguration.USERNAME, "user=bogus" ); url = url.replace( "password=" + DatabaseConfiguration.PASSWORD, "password=bogus" ); @@ -116,7 +116,7 @@ public void configureWithWrongCredentials(TestContext context) { thrown.expectMessage( "io.vertx.pgclient.PgException:" ); thrown.expectMessage( "bogus" ); - String url = DatabaseConfiguration.getJdbcUrl(); + String url = DatabaseConfiguration.getConnectionUri(); Map config = new HashMap<>(); config.put( Settings.URL, url ); config.put( Settings.USER, "bogus" ); diff --git a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/CockroachDBDatabase.java b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/CockroachDBDatabase.java index 4540c220e..ecdade61d 100644 --- a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/CockroachDBDatabase.java +++ b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/CockroachDBDatabase.java @@ -30,32 +30,19 @@ class CockroachDBDatabase extends PostgreSQLDatabase { // Testcontainers will use a database named 'postgres' and the 'root' user .withReuse( true ); - private String getRegularJdbcUrl() { - return "jdbc:postgres://localhost:26257/" + cockroachDb.getDatabaseName(); - } - @Override - public String getJdbcUrl() { - return buildJdbcUrlWithCredentials( address() ) - .replaceAll( "^jdbc:postgre(s|sql):", "jdbc:cockroachdb:" ); + public String getDefaultUrl() { + return "cockroachdb://" + TestableDatabase.credentials( cockroachDb ) + "localhost:26257/" + cockroachDb.getDatabaseName(); } @Override - public String getUri() { - return buildUriWithCredentials( address() ) - .replaceAll( "^postgre(s|sql):", "jdbc:cockroachdb:" ); - } - - private String address() { + public String getConnectionUri() { + String vertxUri = disableSslMode( connectionUri( cockroachDb ) ) + .replaceAll( "^postgre(s|sql):", "cockroachdb:" ); if ( DatabaseConfiguration.USE_DOCKER ) { - // Calling start() will start the container (if not already started) - // It is required to call start() before obtaining the JDBC URL because it will contain a randomized port - cockroachDb.start(); enableTemporaryTables(); - return disableSslMode( cockroachDb.getJdbcUrl() ); } - - return disableSslMode( getRegularJdbcUrl() ); + return vertxUri; } private static String disableSslMode(String url) { @@ -89,15 +76,6 @@ private static void runSql(String command) { } } - private static String buildJdbcUrlWithCredentials(String jdbcUrl) { - return jdbcUrl + "&user=" + cockroachDb.getUsername(); - } - - private static String buildUriWithCredentials(String jdbcUrl) { - String suffix = jdbcUrl.replaceAll( "^jdbc:postgre(s|sql)://", "" ); - return "postgresql://" + cockroachDb.getUsername() + "@" + suffix; - } - private CockroachDBDatabase() { } } diff --git a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/DB2Database.java b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/DB2Database.java index 821d7cb10..ae419c242 100644 --- a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/DB2Database.java +++ b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/DB2Database.java @@ -90,18 +90,14 @@ class DB2Database implements TestableDatabase { .acceptLicense() .withReuse( true ); - private String getRegularJdbcUrl() { - return "jdbc:db2://localhost:50000/" + db2.getDatabaseName(); - } - @Override - public String getJdbcUrl() { - return buildJdbcUrlWithCredentials( address() ); + public String getDefaultUrl() { + return "db2://" + TestableDatabase.credentials( db2 ) + "localhost:50000/" + db2.getDatabaseName(); } @Override - public String getUri() { - return buildUriWithCredentials( address() ); + public String getConnectionUri() { + return connectionUri( db2 ); } @Override @@ -114,25 +110,6 @@ public String getExpectedNativeDatatype(Class dataType) { return expectedDBTypeForClass.get( dataType ); } - private String address() { - if ( DatabaseConfiguration.USE_DOCKER ) { - // Calling start() will start the container (if not already started) - // It is required to call start() before obtaining the JDBC URL because it will contain a randomized port - db2.start(); - return db2.getJdbcUrl(); - } - - return getRegularJdbcUrl(); - } - - private static String buildJdbcUrlWithCredentials(String jdbcUrl) { - return jdbcUrl + ":user=" + db2.getUsername() + ";password=" + db2.getPassword() + ";"; - } - - private static String buildUriWithCredentials(String jdbcUrl) { - return "db2://" + db2.getUsername() + ":" + db2.getPassword() + "@" + jdbcUrl.substring(11); - } - private DB2Database() { } diff --git a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/DatabaseConfiguration.java b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/DatabaseConfiguration.java index affac41a3..ab4f96ecd 100644 --- a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/DatabaseConfiguration.java +++ b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/DatabaseConfiguration.java @@ -84,12 +84,8 @@ public static DBType dbType() { return dbType; } - public static String getJdbcUrl() { - return dbType().configuration.getJdbcUrl(); - } - - public static String getUri() { - return dbType().configuration.getUri(); + public static String getConnectionUri() { + return dbType().configuration.getConnectionUri(); } public static String getDatatypeQuery(String tableName, String columnName) { diff --git a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/MSSQLServerDatabase.java b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/MSSQLServerDatabase.java index ec8ebfa4a..fe4a9a6fe 100644 --- a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/MSSQLServerDatabase.java +++ b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/MSSQLServerDatabase.java @@ -97,17 +97,13 @@ class MSSQLServerDatabase implements TestableDatabase { .withReuse( true ); @Override - public String getJdbcUrl() { - return buildJdbcUrlWithCredentials( address() ); - } - - private String getRegularJdbcUrl() { - return "jdbc:sqlserver://localhost:1433"; + public String getConnectionUri() { + return connectionUri( mssqlserver ); } @Override - public String getUri() { - return buildUriWithCredentials( address() ); + public String getDefaultUrl() { + return "sqlserver:// " + TestableDatabase.credentials( mssqlserver ) + "localhost:1433/" + mssqlserver.getDatabaseName(); } @Override @@ -115,25 +111,6 @@ public String getExpectedNativeDatatype(Class dataType) { return expectedDBTypeForClass.get( dataType ); } - private String address() { - if ( DatabaseConfiguration.USE_DOCKER ) { - // Calling start() will start the container (if not already started) - // It is required to call start() before obtaining the JDBC URL because it will contain a randomized port - mssqlserver.start(); - return mssqlserver.getJdbcUrl(); - } - - return getRegularJdbcUrl(); - } - - private String buildJdbcUrlWithCredentials(String jdbcUrl) { - return jdbcUrl + ";user=" + mssqlserver.getUsername() + ";password=" + mssqlserver.getPassword(); - } - - private static String buildUriWithCredentials(String jdbcUrl) { - return "sqlserver://" + mssqlserver.getUsername() + ":" + mssqlserver.getPassword() + "@" + jdbcUrl.substring( "jdbc:sqlserver://".length() ); - } - private MSSQLServerDatabase() { } diff --git a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/MariaDatabase.java b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/MariaDatabase.java index 7a9ea4efd..73a112674 100644 --- a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/MariaDatabase.java +++ b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/MariaDatabase.java @@ -24,41 +24,16 @@ class MariaDatabase extends MySQLDatabase { .withDatabaseName( DatabaseConfiguration.DB_NAME ) .withReuse( true ); - private String getRegularJdbcUrl() { - return "jdbc:mariadb://localhost:3306/" + maria.getDatabaseName(); + protected MariaDatabase() { } @Override - public String getJdbcUrl() { - return buildJdbcUrlWithCredentials( address() ); + public String getConnectionUri() { + return connectionUri( maria ); } @Override - public String getUri() { - return buildUriWithCredentials( address() ); + public String getDefaultUrl() { + return super.getDefaultUrl().replaceAll( "^mysql:", "mariadb:" ); } - - private String address() { - if ( DatabaseConfiguration.USE_DOCKER ) { - // Calling start() will start the container (if not already started) - // It is required to call start() before obtaining the JDBC URL because it will contain a randomized port - maria.start(); - return maria.getJdbcUrl(); - } - - return getRegularJdbcUrl(); - } - - static String buildJdbcUrlWithCredentials(String jdbcUrl) { - return jdbcUrl + "?user=" + maria.getUsername() + "&password=" + maria.getPassword() + "&serverTimezone=UTC"; - } - - private static String buildUriWithCredentials(String jdbcUrl) { - return "mariadb://" + maria.getUsername() + ":" + maria.getPassword() + "@" - + jdbcUrl.substring( "jdbc:mariadb://".length() ); - } - - private MariaDatabase() { - } - } diff --git a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/MySQLDatabase.java b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/MySQLDatabase.java index bacad1789..b13dda7df 100644 --- a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/MySQLDatabase.java +++ b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/MySQLDatabase.java @@ -28,6 +28,7 @@ import org.hibernate.type.YesNoType; import org.hibernate.type.descriptor.java.PrimitiveByteArrayTypeDescriptor; + class MySQLDatabase implements TestableDatabase { static MySQLDatabase INSTANCE = new MySQLDatabase(); @@ -84,50 +85,24 @@ class MySQLDatabase implements TestableDatabase { .withUsername( DatabaseConfiguration.USERNAME ) .withPassword( DatabaseConfiguration.PASSWORD ) .withDatabaseName( DatabaseConfiguration.DB_NAME ) + .withLogConsumer( of -> System.out.println( of.getUtf8String() ) ) .withReuse( true ); - private String getRegularJdbcUrl() { - return "jdbc:mysql://localhost:3306/" + mysql.getDatabaseName(); + protected MySQLDatabase() { } @Override - public String getJdbcUrl() { - return buildJdbcUrlWithCredentials( address() ); + public String getConnectionUri() { + return connectionUri( mysql ); } @Override - public String getUri() { - return buildUriWithCredentials( address() ); + public String getDefaultUrl() { + return "mysql://" + TestableDatabase.credentials( mysql ) + "localhost:3306/" + mysql.getDatabaseName(); } @Override public String getExpectedNativeDatatype(Class dataType) { return expectedDBTypeForClass.get( dataType ); } - - private String address() { - String address; - if ( DatabaseConfiguration.USE_DOCKER ) { - // Calling start() will start the container (if not already started) - // It is required to call start() before obtaining the JDBC URL because it will contain a randomized port - mysql.start(); - address = mysql.getJdbcUrl(); - } - else { - address = getRegularJdbcUrl(); - } - return address; - } - - static String buildJdbcUrlWithCredentials(String jdbcUrl) { - return jdbcUrl + "?user=" + mysql.getUsername() + "&password=" + mysql.getPassword() + "&serverTimezone=UTC"; - } - - private static String buildUriWithCredentials(String jdbcUrl) { - return "mysql://" + mysql.getUsername() + ":" + mysql.getPassword() + "@" + jdbcUrl.substring(13); - } - - protected MySQLDatabase() { - } - } diff --git a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/OracleDatabase.java b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/OracleDatabase.java index 2aae0eeed..77826f8fb 100644 --- a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/OracleDatabase.java +++ b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/OracleDatabase.java @@ -90,19 +90,24 @@ class OracleDatabase implements TestableDatabase { .withReuse( true ); @Override - public String getJdbcUrl() { - return addCredentialsAsParameters( address() ); - } + public String getConnectionUri() { + if ( DatabaseConfiguration.USE_DOCKER ) { + // Calling start() will start the container (if not already started) + // It is required to call start() before obtaining the JDBC URL because it will contain a randomized port + oracle.start(); + return oracle.getJdbcUrl() + .replace( "jdbc:oracle:thin:@", "oracle:thin:" + getCredentials() ) + // This should actually end with /databaseName but there is a bug in the Vert.x client + .replaceAll( "/" + oracle.getDatabaseName() + "$", ":" + oracle.getDatabaseName() ); + } - private String getRegularJdbcUrl() { - return "jdbc:oracle:thin:" + getCredentials() + "@localhost:1521/" + oracle.getDatabaseName(); + return getDefaultUrl(); } @Override - public String getUri() { - // The url is different here because we expect it to work with io.vertx.oracleclient.impl.OracleConnectionUriParser - return addCredentialsToUri( address() ) - .replaceAll( "/" + oracle.getDatabaseName() + "$", ":" + oracle.getDatabaseName() ); + public String getDefaultUrl() { + // This should actually end with /databaseName but there is a bug in the Vert.x client + return "oracle:thin:" + getCredentials() + "localhost:1521:" + oracle.getDatabaseName(); } @Override @@ -115,38 +120,11 @@ public String getExpectedNativeDatatype(Class dataType) { return expectedDBTypeForClass.get( dataType ); } - private String address() { - if ( DatabaseConfiguration.USE_DOCKER ) { - // Calling start() will start the container (if not already started) - // It is required to call start() before obtaining the JDBC URL because it will contain a randomized port - oracle.start(); - return oracle.getJdbcUrl(); - } - - return getRegularJdbcUrl(); - } - private static String getCredentials() { - if ( oracle.getUsername() == null - || oracle.getUsername().trim().length() == 0 ) { + if ( oracle.getUsername() == null || oracle.getUsername().trim().length() == 0 ) { return ""; } - return oracle.getUsername() + "/" + oracle.getPassword(); - } - - private static String addCredentialsAsParameters(String jdbcUrl) { - return jdbcUrl + "?user=" + oracle.getUsername() + "&password=" + oracle.getPassword(); - } - - private static String addCredentialsToUri(String jdbcUrl) { - // The JDBC url will look something like: - // jdbc:oracle:thin:@localhost:49413/hreact - String uri = jdbcUrl; - if ( uri.startsWith( "jdbc:" ) ) { - jdbcUrl.substring( "jdbc:".length() ); - } - uri = uri.replace( "thin:@", "thin:" + getCredentials() + "@"); - return uri; + return oracle.getUsername() + "/" + oracle.getPassword() + "@"; } private OracleDatabase() { diff --git a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/PostgreSQLDatabase.java b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/PostgreSQLDatabase.java index 69681d3ad..9982e36eb 100644 --- a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/PostgreSQLDatabase.java +++ b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/PostgreSQLDatabase.java @@ -36,7 +36,7 @@ class PostgreSQLDatabase implements TestableDatabase { public final static String IMAGE_NAME = "postgres:14.1"; - private static Map, String> expectedDBTypeForClass = new HashMap<>(); + private static final Map, String> expectedDBTypeForClass = new HashMap<>(); static {{ expectedDBTypeForClass.put( boolean.class, "boolean" ); @@ -88,18 +88,17 @@ class PostgreSQLDatabase implements TestableDatabase { .withDatabaseName( DatabaseConfiguration.DB_NAME ) .withReuse( true ); - private String getRegularJdbcUrl() { - return "jdbc:postgresql://localhost:5432/" + postgresql.getDatabaseName() + "?loggerLevel=OFF"; + protected PostgreSQLDatabase() { } @Override - public String getJdbcUrl() { - return buildJdbcUrlWithCredentials( address() ); + public String getConnectionUri() { + return connectionUri( postgresql ); } @Override - public String getUri() { - return buildUriWithCredentials( address() ); + public String getDefaultUrl() { + return "postgresql://" + TestableDatabase.credentials( postgresql ) + "localhost:5432/" + postgresql.getDatabaseName(); } @Override @@ -111,26 +110,4 @@ public String getNativeDatatypeQuery(String tableName, String columnName) { public String getExpectedNativeDatatype(Class dataType) { return expectedDBTypeForClass.get( dataType ); } - - private String address() { - if ( DatabaseConfiguration.USE_DOCKER ) { - // Calling start() will start the container (if not already started) - // It is required to call start() before obtaining the JDBC URL because it will contain a randomized port - postgresql.start(); - return postgresql.getJdbcUrl(); - } - - return getRegularJdbcUrl(); - } - - private static String buildJdbcUrlWithCredentials(String jdbcUrl) { - return jdbcUrl + "&user=" + postgresql.getUsername() + "&password=" + postgresql.getPassword(); - } - - private static String buildUriWithCredentials(String jdbcUrl) { - return "postgresql://" + postgresql.getUsername() + ":" + postgresql.getPassword() + "@" + jdbcUrl.substring(18); - } - - protected PostgreSQLDatabase() { - } } diff --git a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/TestableDatabase.java b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/TestableDatabase.java index 23ab5cdfd..887459aef 100644 --- a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/TestableDatabase.java +++ b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/TestableDatabase.java @@ -5,14 +5,40 @@ */ package org.hibernate.reactive.containers; +import org.testcontainers.containers.JdbcDatabaseContainer; + /** * A database that we use for testing. */ public interface TestableDatabase { - String getJdbcUrl(); + String getConnectionUri(); + + default String connectionUri(JdbcDatabaseContainer container) { + if ( DatabaseConfiguration.USE_DOCKER ) { + // Calling start() will start the container (if not already started) + // It is required to call start() before obtaining the JDBC URL because it will contain a randomized port + container.start(); + return TestableDatabase.vertxUrl( container ); + } + + return getDefaultUrl(); + } + + String getDefaultUrl(); + + static String vertxUrl(JdbcDatabaseContainer container) { + String vertxUrl = container.getJdbcUrl().replaceAll( "^jdbc:", "" ); + int start = vertxUrl.indexOf( ":" ) + 1; + String scheme = vertxUrl.substring( 0, start ); + vertxUrl = vertxUrl.substring( start ).replaceAll( "^//", "" ); + final String uri = scheme + "//" + credentials( container ) + vertxUrl; + return uri; + } - String getUri(); + static String credentials(JdbcDatabaseContainer container) { + return container.getUsername() + ":" + container.getPassword() + "@"; + } default String getNativeDatatypeQuery(String tableName, String columnName) { return "select data_type from information_schema.columns where table_name = '" + tableName + "' and column_name = '" + columnName + "'"; diff --git a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/VertxMariaContainer.java b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/VertxMariaContainer.java index 133212349..5243b67bd 100644 --- a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/VertxMariaContainer.java +++ b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/VertxMariaContainer.java @@ -6,6 +6,7 @@ package org.hibernate.reactive.containers; import io.vertx.core.AsyncResult; +import io.vertx.core.Vertx; import io.vertx.mysqlclient.MySQLPool; import io.vertx.sqlclient.SqlConnection; import org.testcontainers.containers.ContainerLaunchException; @@ -30,70 +31,75 @@ public VertxMariaContainer(String dockerImageName) { } @Override - protected void waitUntilContainerStarted() { - logger().info( "Waiting for database connection to become available at {} using query '{}'", getVertxUrl(), getTestQueryString()); + protected void waitUntilContainerStarted() { + logger().info( "Waiting for database connection to become available at {} using query '{}'", getVertxUrl(), getTestQueryString() ); - // Repeatedly try and open a connection to the DB and execute a test query - long start = System.currentTimeMillis(); - try { - while (System.currentTimeMillis() < start + (1000 * getStartupTimeoutSeconds())) { - try { - if (!isRunning()) { - Thread.sleep(100L); - continue; // Don't attempt to connect yet - } + // Repeatedly try and open a connection to the DB and execute a test query + long start = System.currentTimeMillis(); + try { + while ( System.currentTimeMillis() < start + ( 1000 * getStartupTimeoutSeconds() ) ) { + try { + if ( !isRunning() ) { + Thread.sleep( 100L ); + continue; // Don't attempt to connect yet + } - AtomicReference> result = new AtomicReference<>(); - CountDownLatch countDown = new CountDownLatch( 1 ); - SqlConnection connection = createVertxConnection(); - connection.query( getTestQueryString() ).execute( ar -> { - result.set( ar ); - countDown.countDown(); - }); - await(countDown); - if (result.get().succeeded()) { - break; - } else { - throw result.get().cause(); - } - } catch (Throwable e) { - // ignore so that we can try again - logger().debug("Failure when trying test query", e); - Thread.sleep(100L); - } - } - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new ContainerLaunchException("Container startup wait was interrupted", e); - } + AtomicReference> result = new AtomicReference<>(); + CountDownLatch countDown = new CountDownLatch( 1 ); + SqlConnection connection = createVertxConnection(); + connection.query( getTestQueryString() ).execute( ar -> { + result.set( ar ); + countDown.countDown(); + } ); + await( countDown ); + if ( result.get().succeeded() ) { + break; + } + else { + throw result.get().cause(); + } + } + catch (Throwable e) { + // ignore so that we can try again + logger().debug( "Failure when trying test query", e ); + Thread.sleep( 100L ); + } + } + } + catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new ContainerLaunchException( "Container startup wait was interrupted", e ); + } - logger().info("Container is started (URL: {})", getVertxUrl()); - } + logger().info( "Container is started (URL: {})", getVertxUrl() ); + } - public String getVertxUrl() { - return MariaDatabase.buildJdbcUrlWithCredentials( getJdbcUrl().replace( "jdbc:", "" ) ); - } + public String getVertxUrl() { + return TestableDatabase.vertxUrl( this ); + } - public SqlConnection createVertxConnection() { - String url = getVertxUrl(); - CountDownLatch countDown = new CountDownLatch( 1 ); - AtomicReference> result = new AtomicReference<>(); - MySQLPool.pool( url ).getConnection( ar -> { - result.set( ar ); - countDown.countDown(); - }); - await(countDown); - SqlConnection con = result.get().result(); - if (con != null) - return con; - else - throw new ContainerLaunchException( "Failed to obtain a connection", result.get().cause() ); - } + public SqlConnection createVertxConnection() { + String url = getVertxUrl(); + CountDownLatch countDown = new CountDownLatch( 1 ); + AtomicReference> result = new AtomicReference<>(); + MySQLPool.pool( Vertx.currentContext().owner(), url ).getConnection( ar -> { + result.set( ar ); + countDown.countDown(); + } ); + await( countDown ); + SqlConnection con = result.get().result(); + if ( con != null ) { + return con; + } + else { + throw new ContainerLaunchException( "Failed to obtain a connection", result.get().cause() ); + } + } - @Override - public Connection createConnection(String queryString) throws NoDriverFoundException { - throw new UnsupportedOperationException(); - } + @Override + public Connection createConnection(String queryString) throws NoDriverFoundException { + throw new UnsupportedOperationException(); + } private void await(CountDownLatch latch) { try { diff --git a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/VertxMySqlContainer.java b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/VertxMySqlContainer.java index 7e3aad4ca..779580732 100644 --- a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/VertxMySqlContainer.java +++ b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/VertxMySqlContainer.java @@ -10,6 +10,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; +import io.vertx.core.Vertx; import org.testcontainers.containers.ContainerLaunchException; import org.testcontainers.containers.MySQLContainer; @@ -31,70 +32,75 @@ public VertxMySqlContainer(String dockerImageName) { } @Override - protected void waitUntilContainerStarted() { - logger().info( "Waiting for database connection to become available at {} using query '{}'", getVertxUrl(), getTestQueryString()); + protected void waitUntilContainerStarted() { + logger().info( "Waiting for database connection to become available at {} using query '{}'", getVertxUrl(), getTestQueryString() ); - // Repeatedly try and open a connection to the DB and execute a test query - long start = System.currentTimeMillis(); - try { - while (System.currentTimeMillis() < start + ( 1000L * getStartupTimeoutSeconds())) { - try { - if (!isRunning()) { - Thread.sleep(100L); - continue; // Don't attempt to connect yet - } + // Repeatedly try and open a connection to the DB and execute a test query + long start = System.currentTimeMillis(); + try { + while ( System.currentTimeMillis() < start + ( 1000L * getStartupTimeoutSeconds() ) ) { + try { + if ( !isRunning() ) { + Thread.sleep( 100L ); + continue; // Don't attempt to connect yet + } - AtomicReference> result = new AtomicReference<>(); - CountDownLatch countDown = new CountDownLatch( 1 ); - SqlConnection connection = createVertxConnection(); - connection.query( getTestQueryString() ).execute( ar -> { - result.set( ar ); - countDown.countDown(); - }); - await(countDown); - if (result.get().succeeded()) { - break; - } else { - throw result.get().cause(); - } - } catch (Throwable e) { - // ignore so that we can try again - logger().debug("Failure when trying test query", e); - Thread.sleep(100L); - } - } - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new ContainerLaunchException("Container startup wait was interrupted", e); - } + AtomicReference> result = new AtomicReference<>(); + CountDownLatch countDown = new CountDownLatch( 1 ); + SqlConnection connection = createVertxConnection(); + connection.query( getTestQueryString() ).execute( ar -> { + result.set( ar ); + countDown.countDown(); + } ); + await( countDown ); + if ( result.get().succeeded() ) { + break; + } + else { + throw result.get().cause(); + } + } + catch (Throwable e) { + // ignore so that we can try again + logger().debug( "Failure when trying test query", e ); + Thread.sleep( 100L ); + } + } + } + catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new ContainerLaunchException( "Container startup wait was interrupted", e ); + } - logger().info("Container is started (URL: {})", getVertxUrl()); - } + logger().info( "Container is started (URL: {})", getVertxUrl() ); + } - public String getVertxUrl() { - return MySQLDatabase.buildJdbcUrlWithCredentials( getJdbcUrl().replace( "jdbc:", "" ) ); - } + public String getVertxUrl() { + return TestableDatabase.vertxUrl( this ); + } - public SqlConnection createVertxConnection() { - String url = getVertxUrl(); - CountDownLatch countDown = new CountDownLatch( 1 ); - AtomicReference> result = new AtomicReference<>(); - MySQLPool.pool( url ).getConnection( ar -> { - result.set( ar ); - countDown.countDown(); - }); - await(countDown); - SqlConnection con = result.get().result(); - if (con != null) - return con; - else - throw new ContainerLaunchException( "Failed to obtain a connection", result.get().cause() ); - } + public SqlConnection createVertxConnection() { + String url = getVertxUrl(); + CountDownLatch countDown = new CountDownLatch( 1 ); + AtomicReference> result = new AtomicReference<>(); + MySQLPool.pool( Vertx.currentContext().owner(), url ).getConnection( ar -> { + result.set( ar ); + countDown.countDown(); + } ); + await( countDown ); + SqlConnection con = result.get().result(); + if ( con != null ) { + return con; + } + else { + throw new ContainerLaunchException( "Failed to obtain a connection", result.get().cause() ); + } + } - @Override - public Connection createConnection(String queryString) throws NoDriverFoundException { - throw new UnsupportedOperationException(); - } + @Override + public Connection createConnection(String queryString) throws NoDriverFoundException { + throw new UnsupportedOperationException(); + } private void await(CountDownLatch latch) { try { From ef3dbb9792c5210e8b1f9076bfdcabfe965bdcf8 Mon Sep 17 00:00:00 2001 From: Davide Date: Tue, 1 Mar 2022 14:00:08 +0000 Subject: [PATCH 2/2] Fix examples and integration test --- .../src/main/resources/META-INF/persistence.xml | 2 +- .../src/main/resources/META-INF/persistence.xml | 4 ++-- .../org/hibernate/reactive/it/verticle/StartVerticle.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/native-sql-example/src/main/resources/META-INF/persistence.xml b/examples/native-sql-example/src/main/resources/META-INF/persistence.xml index b7e14f9b3..0f12f0727 100644 --- a/examples/native-sql-example/src/main/resources/META-INF/persistence.xml +++ b/examples/native-sql-example/src/main/resources/META-INF/persistence.xml @@ -13,7 +13,7 @@ + value="postgresql://localhost/hreact"/> + value="postgresql://localhost/hreact"/> + value="mysql://localhost/hreact"/>