From c874b0bd4864186ddd01b8685cacbb0aee5d6f5b Mon Sep 17 00:00:00 2001 From: Andrea Boriero Date: Tue, 9 Sep 2025 16:46:03 +0200 Subject: [PATCH 1/2] [#2478] Terrible error reporting when JDBC scheme is not recognized --- .../hibernate/reactive/logging/impl/Log.java | 7 ++----- .../DefaultSqlClientPoolConfiguration.java | 21 ++++++++++++++----- .../service/NoJdbcEnvironmentInitiator.java | 8 +++++-- 3 files changed, 24 insertions(+), 12 deletions(-) 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 fa29cd8b5..41dd6a88e 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 @@ -159,11 +159,8 @@ public interface Log extends BasicLogger { @Message(id = 47, value = "Generated identifier smaller or equal to 0: %1$d") HibernateException generatedIdentifierSmallerOrEqualThanZero(Long id); - @Message(id = 48, value = "Could not determine Dialect from JDBC driver metadata (specify a connection URI with scheme 'postgresql:', 'mysql:', 'cockroachdb', or 'db2:')") - HibernateException couldNotDetermineDialectFromJdbcDriverMetadata(); - - @Message(id = 49, value = "Could not determine Dialect from connection URI: '%1$s' (specify a connection URI with scheme 'postgresql:', 'mysql:', 'cockroachdb', or 'db2:')") - HibernateException couldNotDetermineDialectFromConnectionURI(String url); + @Message(id = 49, value = "Could not determine Dialect from connection URI: '%1$s' (specify a connection URI with scheme 'postgresql:', 'postgres:', 'mariadb:', 'mysql:', 'db2:', 'cockroachdb:', 'sqlserver:' or 'oracle:' )") + IllegalArgumentException couldNotDetermineDialectFromConnectionURI(String url); @Message(id = 50, value = "SelectGenerator is not supported in Hibernate Reactive") HibernateException selectGeneratorIsNotSupportedInHibernateReactive(); 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 e0613b78c..96d58badb 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 @@ -90,12 +90,16 @@ public PoolOptions poolOptions() { @Override public SqlConnectOptions connectOptions(URI uri) { - String scheme = uri.getScheme(); - String path = scheme.equals( "oracle" ) + final String scheme = uri.getScheme(); + if ( !isSchemeSupported( scheme ) ) { + throw LOG.couldNotDetermineDialectFromConnectionURI( uri.toString() ); + } + + final String path = scheme.equals( "oracle" ) ? oraclePath( uri ) : uri.getPath(); - String database = path.length() > 0 + String database = path != null && !path.isEmpty() ? path.substring( 1 ) : ""; @@ -105,8 +109,8 @@ public SqlConnectOptions connectOptions(URI uri) { database = database.substring( 0, database.indexOf( ':' ) ); } - String host = findHost( uri, scheme ); - int port = findPort( uri, scheme ); + final String host = findHost( uri, scheme ); + final int port = findPort( uri, scheme ); //see if the credentials were specified via properties String username = user; @@ -385,4 +389,11 @@ private int defaultPort(String scheme) { } } + private boolean isSchemeSupported(String scheme) { + return switch ( scheme ) { + case "postgresql", "postgres", "mariadb", "mysql", "db2", "cockroachdb", "sqlserver", "oracle" -> true; + default -> false; + }; + } + } 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 0cf59c413..2d5209127 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 @@ -29,6 +29,8 @@ import static java.lang.Integer.parseInt; import static java.util.Objects.requireNonNullElse; import static java.util.function.Function.identity; +import static org.hibernate.cfg.JdbcSettings.ALLOW_METADATA_ON_BOOT; +import static org.hibernate.internal.util.config.ConfigurationHelper.getBooleanWrapper; import static org.hibernate.reactive.util.impl.CompletionStages.completedFuture; /** @@ -84,7 +86,8 @@ protected JdbcEnvironmentImpl getJdbcEnvironmentUsingJdbcMetadata( Integer explicitDatabaseMajorVersion, Integer explicitDatabaseMinorVersion, String explicitDatabaseVersion) { - try { + if ( getBooleanWrapper( ALLOW_METADATA_ON_BOOT, configurationValues, true ) ) { + // We query the database for the metadata to build the Dialect final Dialect dialect = new DialectBuilder( configurationValues, registry ) .build( dialectFactory, @@ -97,7 +100,8 @@ protected JdbcEnvironmentImpl getJdbcEnvironmentUsingJdbcMetadata( ); return new JdbcEnvironmentImpl( registry, dialect ); } - catch (RuntimeException e) { + else { + // We don't query the database but use default config values return getJdbcEnvironmentWithDefaults( configurationValues, registry, dialectFactory ); } } From 7740f40e9ce4632cb42c2a8ed6e3482f175c716b Mon Sep 17 00:00:00 2001 From: Andrea Boriero Date: Wed, 24 Sep 2025 10:32:36 +0200 Subject: [PATCH 2/2] [#2478] Add test for terrible error reporting when JDBC scheme is not recognized --- .../reactive/WrongJdbcUrlSchemeTest.java | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 hibernate-reactive-core/src/test/java/org/hibernate/reactive/WrongJdbcUrlSchemeTest.java diff --git a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/WrongJdbcUrlSchemeTest.java b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/WrongJdbcUrlSchemeTest.java new file mode 100644 index 000000000..24422d888 --- /dev/null +++ b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/WrongJdbcUrlSchemeTest.java @@ -0,0 +1,50 @@ +/* Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.reactive; + +import org.hibernate.cfg.Configuration; +import org.hibernate.reactive.provider.Settings; +import org.hibernate.service.spi.ServiceException; + +import org.junit.jupiter.api.Test; + +import io.vertx.junit5.Timeout; +import io.vertx.junit5.VertxTestContext; + +import static java.util.concurrent.TimeUnit.MINUTES; +import static org.assertj.core.api.Assertions.assertThat; +import static org.hibernate.reactive.testing.ReactiveAssertions.assertThrown; + +/** + * Check that the right exception is thrown when there is an error when the JDBC URI scheme is not recognized. + */ +@Timeout(value = 10, timeUnit = MINUTES) +public class WrongJdbcUrlSchemeTest extends BaseReactiveTest { + + @Override + protected void setProperties(Configuration configuration) { + configuration.setProperty( Settings.JAKARTA_JDBC_URL, "jdbc:h2:~/h2temp" ); + configuration.setProperty( Settings.JAKARTA_JDBC_USER, "abc" ); + setSqlLoggingProperties( configuration ); + } + + @Override + public void before(VertxTestContext context) { + // We need to postpone the creation of the factory so that we can check the exception + } + + @Test + public void testWithTransaction(VertxTestContext context) { + test( context, assertThrown( ServiceException.class, setupSessionFactory( this::constructConfiguration ) ) + .thenAccept( WrongJdbcUrlSchemeTest::assertException ) + ); + } + + private static void assertException(Throwable throwable) { + assertThat( throwable ).hasMessageContaining( "HR000049" ); + } + +}