From 4f63e899b0e1050c24d1620842d85c74b3afcdfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Tue, 9 Jan 2024 17:44:54 +0100 Subject: [PATCH] Test runtime configuration property quarkus.datasource.active --- .../AgroalMetricsConfigActiveFalseTest.java | 51 +++++++ ...onfigActiveFalseDefaultDatasourceTest.java | 91 ++++++++++++ .../ConfigActiveFalseNamedDatasourceTest.java | 96 ++++++++++++ ...ourceHealthCheckConfigActiveFalseTest.java | 30 ++++ ...ourcesAsAlternativesWithActiveDS1Test.java | 98 ++++++++++++ ...ourcesAsAlternativesWithActiveDS2Test.java | 98 ++++++++++++ ...onfigActiveFalseDefaultDatasourceTest.java | 38 +++++ ...nConfigActiveFalseNamedDataSourceTest.java | 49 ++++++ ...efaultDatasourceConfigActiveFalseTest.java | 42 ++++++ ...tNamedDatasourceConfigActiveFalseTest.java | 52 +++++++ ...plicitDatasourceConfigActiveFalseTest.java | 41 +++++ ...plicitDatasourceConfigActiveFalseTest.java | 36 +++++ ...plicitDatasourceConfigActiveFalseTest.java | 41 +++++ ...iplePUAsAlternativesWithActivePU1Test.java | 119 +++++++++++++++ ...iplePUAsAlternativesWithActivePU2Test.java | 119 +++++++++++++++ ...plicitDatasourceConfigActiveFalseTest.java | 37 +++++ ...onfigActiveFalseDefaultDatasourceTest.java | 39 +++++ ...nConfigActiveFalseNamedDatasourceTest.java | 48 ++++++ ...efaultDatasourceConfigActiveFalseTest.java | 42 ++++++ ...tNamedDatasourceConfigActiveFalseTest.java | 52 +++++++ ...onfigActiveFalseDefaultDatasourceTest.java | 133 +++++++++++++++++ .../ConfigActiveFalseNamedDatasourceTest.java | 140 ++++++++++++++++++ ...ourceHealthCheckConfigActiveFalseTest.java | 30 ++++ ...onfigActiveFalseDefaultDatasourceTest.java | 133 +++++++++++++++++ .../ConfigActiveFalseNamedDatasourceTest.java | 140 ++++++++++++++++++ ...ourceHealthCheckConfigActiveFalseTest.java | 30 ++++ ...onfigActiveFalseDefaultDatasourceTest.java | 133 +++++++++++++++++ .../ConfigActiveFalseNamedDatasourceTest.java | 140 ++++++++++++++++++ ...ourceHealthCheckConfigActiveFalseTest.java | 30 ++++ ...onfigActiveFalseDefaultDatasourceTest.java | 133 +++++++++++++++++ .../ConfigActiveFalseNamedDatasourceTest.java | 140 ++++++++++++++++++ ...ourceHealthCheckConfigActiveFalseTest.java | 30 ++++ 32 files changed, 2431 insertions(+) create mode 100644 extensions/agroal/deployment/src/test/java/io/quarkus/agroal/test/AgroalMetricsConfigActiveFalseTest.java create mode 100644 extensions/agroal/deployment/src/test/java/io/quarkus/agroal/test/ConfigActiveFalseDefaultDatasourceTest.java create mode 100644 extensions/agroal/deployment/src/test/java/io/quarkus/agroal/test/ConfigActiveFalseNamedDatasourceTest.java create mode 100644 extensions/agroal/deployment/src/test/java/io/quarkus/agroal/test/DataSourceHealthCheckConfigActiveFalseTest.java create mode 100644 extensions/agroal/deployment/src/test/java/io/quarkus/agroal/test/MultipleDataSourcesAsAlternativesWithActiveDS1Test.java create mode 100644 extensions/agroal/deployment/src/test/java/io/quarkus/agroal/test/MultipleDataSourcesAsAlternativesWithActiveDS2Test.java create mode 100644 extensions/flyway/deployment/src/test/java/io/quarkus/flyway/test/FlywayExtensionConfigActiveFalseDefaultDatasourceTest.java create mode 100644 extensions/flyway/deployment/src/test/java/io/quarkus/flyway/test/FlywayExtensionConfigActiveFalseNamedDataSourceTest.java create mode 100644 extensions/flyway/deployment/src/test/java/io/quarkus/flyway/test/FlywayExtensionMigrateAtStartDefaultDatasourceConfigActiveFalseTest.java create mode 100644 extensions/flyway/deployment/src/test/java/io/quarkus/flyway/test/FlywayExtensionMigrateAtStartNamedDatasourceConfigActiveFalseTest.java create mode 100644 extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/config/datasource/EntitiesInDefaultPUWithExplicitDatasourceConfigActiveFalseTest.java create mode 100644 extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/config/datasource/EntitiesInDefaultPUWithImplicitDatasourceConfigActiveFalseTest.java create mode 100644 extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/config/datasource/EntitiesInNamedPUWithExplicitDatasourceConfigActiveFalseTest.java create mode 100644 extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/config/datasource/MultiplePUAsAlternativesWithActivePU1Test.java create mode 100644 extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/config/datasource/MultiplePUAsAlternativesWithActivePU2Test.java create mode 100644 extensions/hibernate-reactive/deployment/src/test/java/io/quarkus/hibernate/reactive/config/datasource/EntitiesInDefaultPUWithImplicitDatasourceConfigActiveFalseTest.java create mode 100644 extensions/liquibase/deployment/src/test/java/io/quarkus/liquibase/test/LiquibaseExtensionConfigActiveFalseDefaultDatasourceTest.java create mode 100644 extensions/liquibase/deployment/src/test/java/io/quarkus/liquibase/test/LiquibaseExtensionConfigActiveFalseNamedDatasourceTest.java create mode 100644 extensions/liquibase/deployment/src/test/java/io/quarkus/liquibase/test/LiquibaseExtensionMigrateAtStartDefaultDatasourceConfigActiveFalseTest.java create mode 100644 extensions/liquibase/deployment/src/test/java/io/quarkus/liquibase/test/LiquibaseExtensionMigrateAtStartNamedDatasourceConfigActiveFalseTest.java create mode 100644 extensions/reactive-mssql-client/deployment/src/test/java/io/quarkus/reactive/mssql/client/ConfigActiveFalseDefaultDatasourceTest.java create mode 100644 extensions/reactive-mssql-client/deployment/src/test/java/io/quarkus/reactive/mssql/client/ConfigActiveFalseNamedDatasourceTest.java create mode 100644 extensions/reactive-mssql-client/deployment/src/test/java/io/quarkus/reactive/mssql/client/DataSourceHealthCheckConfigActiveFalseTest.java create mode 100644 extensions/reactive-mysql-client/deployment/src/test/java/io/quarkus/reactive/mysql/client/ConfigActiveFalseDefaultDatasourceTest.java create mode 100644 extensions/reactive-mysql-client/deployment/src/test/java/io/quarkus/reactive/mysql/client/ConfigActiveFalseNamedDatasourceTest.java create mode 100644 extensions/reactive-mysql-client/deployment/src/test/java/io/quarkus/reactive/mysql/client/DataSourceHealthCheckConfigActiveFalseTest.java create mode 100644 extensions/reactive-oracle-client/deployment/src/test/java/io/quarkus/reactive/oracle/client/ConfigActiveFalseDefaultDatasourceTest.java create mode 100644 extensions/reactive-oracle-client/deployment/src/test/java/io/quarkus/reactive/oracle/client/ConfigActiveFalseNamedDatasourceTest.java create mode 100644 extensions/reactive-oracle-client/deployment/src/test/java/io/quarkus/reactive/oracle/client/DataSourceHealthCheckConfigActiveFalseTest.java create mode 100644 extensions/reactive-pg-client/deployment/src/test/java/io/quarkus/reactive/pg/client/ConfigActiveFalseDefaultDatasourceTest.java create mode 100644 extensions/reactive-pg-client/deployment/src/test/java/io/quarkus/reactive/pg/client/ConfigActiveFalseNamedDatasourceTest.java create mode 100644 extensions/reactive-pg-client/deployment/src/test/java/io/quarkus/reactive/pg/client/DataSourceHealthCheckConfigActiveFalseTest.java diff --git a/extensions/agroal/deployment/src/test/java/io/quarkus/agroal/test/AgroalMetricsConfigActiveFalseTest.java b/extensions/agroal/deployment/src/test/java/io/quarkus/agroal/test/AgroalMetricsConfigActiveFalseTest.java new file mode 100644 index 0000000000000..b680914997d6a --- /dev/null +++ b/extensions/agroal/deployment/src/test/java/io/quarkus/agroal/test/AgroalMetricsConfigActiveFalseTest.java @@ -0,0 +1,51 @@ +package io.quarkus.agroal.test; + +import jakarta.inject.Inject; + +import org.eclipse.microprofile.metrics.Counter; +import org.eclipse.microprofile.metrics.Gauge; +import org.eclipse.microprofile.metrics.MetricID; +import org.eclipse.microprofile.metrics.MetricRegistry; +import org.eclipse.microprofile.metrics.Tag; +import org.eclipse.microprofile.metrics.annotation.RegistryType; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.test.QuarkusUnitTest; + +public class AgroalMetricsConfigActiveFalseTest { + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .withConfigurationResource("application-metrics-enabled.properties") + .overrideConfigKey("quarkus.datasource.active", "false") + .overrideConfigKey("quarkus.datasource.ds1.active", "false"); + + @Inject + @RegistryType(type = MetricRegistry.Type.VENDOR) + MetricRegistry registry; + + @Test + public void testMetricsOfDefaultDS() { + Counter acquireCount = registry.getCounters() + .get(new MetricID("agroal.acquire.count", new Tag("datasource", "default"))); + Gauge maxUsed = registry.getGauges() + .get(new MetricID("agroal.max.used.count", new Tag("datasource", "default"))); + + Assertions.assertNull(acquireCount, "Agroal metrics should not be registered for deactivated datasources eagerly"); + Assertions.assertNull(maxUsed, "Agroal metrics should not be registered for deactivated datasources eagerly"); + } + + @Test + public void testMetricsOfDs1() { + Counter acquireCount = registry.getCounters().get(new MetricID("agroal.acquire.count", + new Tag("datasource", "ds1"))); + Gauge maxUsed = registry.getGauges().get(new MetricID("agroal.max.used.count", + new Tag("datasource", "ds1"))); + + Assertions.assertNull(acquireCount, "Agroal metrics should not be registered for deactivated datasources eagerly"); + Assertions.assertNull(maxUsed, "Agroal metrics should not be registered for deactivated datasources eagerly"); + } + +} diff --git a/extensions/agroal/deployment/src/test/java/io/quarkus/agroal/test/ConfigActiveFalseDefaultDatasourceTest.java b/extensions/agroal/deployment/src/test/java/io/quarkus/agroal/test/ConfigActiveFalseDefaultDatasourceTest.java new file mode 100644 index 0000000000000..4e71a02d8503e --- /dev/null +++ b/extensions/agroal/deployment/src/test/java/io/quarkus/agroal/test/ConfigActiveFalseDefaultDatasourceTest.java @@ -0,0 +1,91 @@ +package io.quarkus.agroal.test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.sql.SQLException; + +import javax.sql.DataSource; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.CreationException; +import jakarta.inject.Inject; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.agroal.api.AgroalDataSource; +import io.quarkus.arc.Arc; +import io.quarkus.runtime.configuration.ConfigurationException; +import io.quarkus.test.QuarkusUnitTest; + +public class ConfigActiveFalseDefaultDatasourceTest { + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .overrideConfigKey("quarkus.datasource.active", "false"); + + @Inject + MyBean myBean; + + @Test + public void dataSource() { + DataSource ds = Arc.container().instance(DataSource.class).get(); + + // The bean is always available to be injected during static init + // since we don't know whether the datasource will be active at runtime. + // So the bean cannot be null. + assertThat(ds).isNotNull(); + // However, any attempt to use it at runtime will fail. + assertThatThrownBy(() -> ds.getConnection()) + .isInstanceOf(RuntimeException.class) + .cause() + .isInstanceOf(ConfigurationException.class) + .hasMessageContainingAll("Datasource '' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.active'" + + " to 'true' and configure datasource ''", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } + + @Test + public void agroalDataSource() { + AgroalDataSource ds = Arc.container().instance(AgroalDataSource.class).get(); + + // The bean is always available to be injected during static init + // since we don't know whether the datasource will be active at runtime. + // So the bean cannot be null. + assertThat(ds).isNotNull(); + // However, any attempt to use it at runtime will fail. + assertThatThrownBy(() -> ds.getConnection()) + .isInstanceOf(RuntimeException.class) + .cause() + .isInstanceOf(ConfigurationException.class) + .hasMessageContainingAll("Datasource '' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.active'" + + " to 'true' and configure datasource ''", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } + + @Test + public void injectedBean() { + assertThatThrownBy(() -> myBean.useDatasource()) + .isInstanceOf(CreationException.class) + .hasMessageContainingAll("Datasource '' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.active'" + + " to 'true' and configure datasource ''", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } + + @ApplicationScoped + public static class MyBean { + @Inject + DataSource ds; + + public void useDatasource() throws SQLException { + ds.getConnection(); + } + } +} diff --git a/extensions/agroal/deployment/src/test/java/io/quarkus/agroal/test/ConfigActiveFalseNamedDatasourceTest.java b/extensions/agroal/deployment/src/test/java/io/quarkus/agroal/test/ConfigActiveFalseNamedDatasourceTest.java new file mode 100644 index 0000000000000..812aeadd02514 --- /dev/null +++ b/extensions/agroal/deployment/src/test/java/io/quarkus/agroal/test/ConfigActiveFalseNamedDatasourceTest.java @@ -0,0 +1,96 @@ +package io.quarkus.agroal.test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.sql.SQLException; + +import javax.sql.DataSource; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.CreationException; +import jakarta.inject.Inject; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.arc.Arc; +import io.quarkus.runtime.configuration.ConfigurationException; +import io.quarkus.test.QuarkusUnitTest; + +public class ConfigActiveFalseNamedDatasourceTest { + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .overrideConfigKey("quarkus.datasource.users.active", "false") + // We need at least one build-time property for the datasource, + // otherwise it's considered unconfigured at build time... + .overrideConfigKey("quarkus.datasource.users.db-kind", "h2"); + + @Inject + MyBean myBean; + + @Test + public void dataSource() { + DataSource ds = Arc.container().instance(DataSource.class, + new io.quarkus.agroal.DataSource.DataSourceLiteral("users")).get(); + + // The bean is always available to be injected during static init + // since we don't know whether the datasource will be active at runtime. + // So the bean cannot be null. + assertThat(ds).isNotNull(); + // However, any attempt to use it at runtime will fail. + assertThatThrownBy(() -> ds.getConnection()) + .isInstanceOf(RuntimeException.class) + .cause() + .isInstanceOf(ConfigurationException.class) + .hasMessageContainingAll("Datasource 'users' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.\"users\".active'" + + " to 'true' and configure datasource 'users'", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } + + @Test + public void agroalDataSource() { + DataSource ds = Arc.container().instance(DataSource.class, + new io.quarkus.agroal.DataSource.DataSourceLiteral("users")).get(); + + // The bean is always available to be injected during static init + // since we don't know whether the datasource will be active at runtime. + // So the bean cannot be null. + assertThat(ds).isNotNull(); + // However, any attempt to use it at runtime will fail. + assertThatThrownBy(() -> ds.getConnection()) + .isInstanceOf(RuntimeException.class) + .cause() + .isInstanceOf(ConfigurationException.class) + .hasMessageContainingAll("Datasource 'users' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.\"users\".active'" + + " to 'true' and configure datasource 'users'", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } + + @Test + public void injectedBean() { + assertThatThrownBy(() -> myBean.useDatasource()) + .isInstanceOf(CreationException.class) + .hasMessageContainingAll("Datasource 'users' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.\"users\".active'" + + " to 'true' and configure datasource 'users'", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } + + @ApplicationScoped + public static class MyBean { + @Inject + @io.quarkus.agroal.DataSource("users") + DataSource ds; + + public void useDatasource() throws SQLException { + ds.getConnection(); + } + } +} diff --git a/extensions/agroal/deployment/src/test/java/io/quarkus/agroal/test/DataSourceHealthCheckConfigActiveFalseTest.java b/extensions/agroal/deployment/src/test/java/io/quarkus/agroal/test/DataSourceHealthCheckConfigActiveFalseTest.java new file mode 100644 index 0000000000000..a6a4fe8f5c03e --- /dev/null +++ b/extensions/agroal/deployment/src/test/java/io/quarkus/agroal/test/DataSourceHealthCheckConfigActiveFalseTest.java @@ -0,0 +1,30 @@ +package io.quarkus.agroal.test; + +import org.hamcrest.CoreMatchers; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.test.QuarkusUnitTest; +import io.restassured.RestAssured; + +public class DataSourceHealthCheckConfigActiveFalseTest { + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .withEmptyApplication() + .withConfigurationResource("application-default-datasource.properties") + .overrideConfigKey("quarkus.datasource.health.enabled", "true") + // this data source is broken, but will be deactivated, + // so the overall check should pass + .overrideConfigKey("quarkus.datasource.brokenDS.db-kind", "h2") + .overrideConfigKey("quarkus.datasource.brokenDS.jdbc.url", "BROKEN") + .overrideConfigKey("quarkus.datasource.brokenDS.active", "false"); + + @Test + public void testDataSourceHealthCheckExclusion() { + RestAssured.when().get("/q/health/ready") + .then() + .body("status", CoreMatchers.equalTo("UP")); + } + +} diff --git a/extensions/agroal/deployment/src/test/java/io/quarkus/agroal/test/MultipleDataSourcesAsAlternativesWithActiveDS1Test.java b/extensions/agroal/deployment/src/test/java/io/quarkus/agroal/test/MultipleDataSourcesAsAlternativesWithActiveDS1Test.java new file mode 100644 index 0000000000000..208241cef1d8c --- /dev/null +++ b/extensions/agroal/deployment/src/test/java/io/quarkus/agroal/test/MultipleDataSourcesAsAlternativesWithActiveDS1Test.java @@ -0,0 +1,98 @@ +package io.quarkus.agroal.test; + +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.Produces; +import jakarta.inject.Inject; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.agroal.api.AgroalDataSource; +import io.quarkus.agroal.DataSource; +import io.quarkus.datasource.runtime.DataSourceSupport; +import io.quarkus.test.QuarkusUnitTest; + +/** + * Tests a use case where multiple datasources are defined at build time, + * but only one is used at runtime. + *

+ * This is mostly useful when each datasource has a distinct db-kind, but in theory that shouldn't matter, + * so we use the h2 db-kind everywhere here to keep test dependencies simpler. + *

+ * See {@link MultipleDataSourcesAsAlternativesWithActiveDS1Test} for the counterpart where PU2 is used at runtime. + */ +public class MultipleDataSourcesAsAlternativesWithActiveDS1Test { + + @RegisterExtension + static QuarkusUnitTest runner = new QuarkusUnitTest() + .withApplicationRoot((jar) -> jar + .addClass(MyProducer.class)) + .overrideConfigKey("quarkus.datasource.ds-1.db-kind", "h2") + .overrideConfigKey("quarkus.datasource.ds-1.active", "false") + .overrideConfigKey("quarkus.datasource.ds-2.db-kind", "h2") + .overrideConfigKey("quarkus.datasource.ds-2.active", "false") + // This is where we select datasource 1 + .overrideRuntimeConfigKey("quarkus.datasource.ds-1.active", "true") + .overrideRuntimeConfigKey("quarkus.datasource.ds-1.jdbc.url", "jdbc:h2:mem:testds1"); + + @Inject + @DataSource("ds-1") + AgroalDataSource explicitDatasourceBean; + + @Inject + AgroalDataSource customIndirectDatasourceBean; + + @Inject + @DataSource("ds-2") + AgroalDataSource inactiveDatasourceBean; + + @Test + public void testExplicitDatasourceBeanUsable() { + doTestDatasource(explicitDatasourceBean); + } + + @Test + public void testCustomIndirectDatasourceBeanUsable() { + doTestDatasource(customIndirectDatasourceBean); + } + + @Test + public void testInactiveDatasourceBeanUnusable() { + assertThatThrownBy(() -> inactiveDatasourceBean.getConnection()) + .hasMessageContaining("Datasource 'ds-2' was deactivated through configuration properties."); + } + + private static void doTestDatasource(AgroalDataSource dataSource) { + assertThatCode(() -> { + try (var connection = dataSource.getConnection()) { + } + }) + .doesNotThrowAnyException(); + } + + private static class MyProducer { + @Inject + DataSourceSupport dataSourceSupport; + + @Inject + @DataSource("ds-1") + AgroalDataSource dataSource1Bean; + + @Inject + @DataSource("ds-2") + AgroalDataSource dataSource2Bean; + + @Produces + @ApplicationScoped + public AgroalDataSource dataSource() { + if (dataSourceSupport.getInactiveNames().contains("ds-1")) { + return dataSource2Bean; + } else { + return dataSource1Bean; + } + } + } +} diff --git a/extensions/agroal/deployment/src/test/java/io/quarkus/agroal/test/MultipleDataSourcesAsAlternativesWithActiveDS2Test.java b/extensions/agroal/deployment/src/test/java/io/quarkus/agroal/test/MultipleDataSourcesAsAlternativesWithActiveDS2Test.java new file mode 100644 index 0000000000000..7159381c15143 --- /dev/null +++ b/extensions/agroal/deployment/src/test/java/io/quarkus/agroal/test/MultipleDataSourcesAsAlternativesWithActiveDS2Test.java @@ -0,0 +1,98 @@ +package io.quarkus.agroal.test; + +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.Produces; +import jakarta.inject.Inject; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.agroal.api.AgroalDataSource; +import io.quarkus.agroal.DataSource; +import io.quarkus.datasource.runtime.DataSourceSupport; +import io.quarkus.test.QuarkusUnitTest; + +/** + * Tests a use case where multiple datasources are defined at build time, + * but only one is used at runtime. + *

+ * This is mostly useful when each datasource has a distinct db-kind, but in theory that shouldn't matter, + * so we use the h2 db-kind everywhere here to keep test dependencies simpler. + *

+ * See {@link MultipleDataSourcesAsAlternativesWithActiveDS1Test} for the counterpart where PU2 is used at runtime. + */ +public class MultipleDataSourcesAsAlternativesWithActiveDS2Test { + + @RegisterExtension + static QuarkusUnitTest runner = new QuarkusUnitTest() + .withApplicationRoot((jar) -> jar + .addClass(MyProducer.class)) + .overrideConfigKey("quarkus.datasource.ds-1.db-kind", "h2") + .overrideConfigKey("quarkus.datasource.ds-1.active", "false") + .overrideConfigKey("quarkus.datasource.ds-2.db-kind", "h2") + .overrideConfigKey("quarkus.datasource.ds-2.active", "false") + // This is where we select datasource 2 + .overrideRuntimeConfigKey("quarkus.datasource.ds-2.active", "true") + .overrideRuntimeConfigKey("quarkus.datasource.ds-2.jdbc.url", "jdbc:h2:mem:testds2"); + + @Inject + @DataSource("ds-2") + AgroalDataSource explicitDatasourceBean; + + @Inject + AgroalDataSource customIndirectDatasourceBean; + + @Inject + @DataSource("ds-1") + AgroalDataSource inactiveDatasourceBean; + + @Test + public void testExplicitDatasourceBeanUsable() { + doTestDatasource(explicitDatasourceBean); + } + + @Test + public void testCustomIndirectDatasourceBeanUsable() { + doTestDatasource(customIndirectDatasourceBean); + } + + @Test + public void testInactiveDatasourceBeanUnusable() { + assertThatThrownBy(() -> inactiveDatasourceBean.getConnection()) + .hasMessageContaining("Datasource 'ds-1' was deactivated through configuration properties."); + } + + private static void doTestDatasource(AgroalDataSource dataSource) { + assertThatCode(() -> { + try (var connection = dataSource.getConnection()) { + } + }) + .doesNotThrowAnyException(); + } + + private static class MyProducer { + @Inject + DataSourceSupport dataSourceSupport; + + @Inject + @DataSource("ds-1") + AgroalDataSource dataSource1Bean; + + @Inject + @DataSource("ds-2") + AgroalDataSource dataSource2Bean; + + @Produces + @ApplicationScoped + public AgroalDataSource dataSource() { + if (dataSourceSupport.getInactiveNames().contains("ds-1")) { + return dataSource2Bean; + } else { + return dataSource1Bean; + } + } + } +} diff --git a/extensions/flyway/deployment/src/test/java/io/quarkus/flyway/test/FlywayExtensionConfigActiveFalseDefaultDatasourceTest.java b/extensions/flyway/deployment/src/test/java/io/quarkus/flyway/test/FlywayExtensionConfigActiveFalseDefaultDatasourceTest.java new file mode 100644 index 0000000000000..79ff4aad04ff4 --- /dev/null +++ b/extensions/flyway/deployment/src/test/java/io/quarkus/flyway/test/FlywayExtensionConfigActiveFalseDefaultDatasourceTest.java @@ -0,0 +1,38 @@ +package io.quarkus.flyway.test; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import jakarta.enterprise.inject.CreationException; +import jakarta.enterprise.inject.Instance; +import jakarta.inject.Inject; + +import org.flywaydb.core.Flyway; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.test.QuarkusUnitTest; + +public class FlywayExtensionConfigActiveFalseDefaultDatasourceTest { + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .overrideConfigKey("quarkus.datasource.active", "false"); + + @Inject + Instance flywayForDefaultDatasource; + + @Test + @DisplayName("If the default datasource is deactivated, the application should boot, but Flyway should be deactivated for that datasource") + public void testBootSucceedsButFlywayDeactivated() { + assertThatThrownBy(flywayForDefaultDatasource::get) + .isInstanceOf(CreationException.class) + .cause() + .hasMessageContainingAll("Unable to find datasource '' for Flyway", + "Datasource '' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.active'" + + " to 'true' and configure datasource ''", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } +} diff --git a/extensions/flyway/deployment/src/test/java/io/quarkus/flyway/test/FlywayExtensionConfigActiveFalseNamedDataSourceTest.java b/extensions/flyway/deployment/src/test/java/io/quarkus/flyway/test/FlywayExtensionConfigActiveFalseNamedDataSourceTest.java new file mode 100644 index 0000000000000..a00dd3f237b13 --- /dev/null +++ b/extensions/flyway/deployment/src/test/java/io/quarkus/flyway/test/FlywayExtensionConfigActiveFalseNamedDataSourceTest.java @@ -0,0 +1,49 @@ +package io.quarkus.flyway.test; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import jakarta.enterprise.inject.CreationException; +import jakarta.enterprise.inject.Instance; +import jakarta.inject.Inject; + +import org.flywaydb.core.Flyway; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.flyway.FlywayDataSource; +import io.quarkus.test.QuarkusUnitTest; + +public class FlywayExtensionConfigActiveFalseNamedDataSourceTest { + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .overrideConfigKey("quarkus.datasource.users.active", "false") + // We need at least one build-time property for the datasource, + // otherwise it's considered unconfigured at build time... + .overrideConfigKey("quarkus.datasource.users.db-kind", "h2") + // We need this otherwise the *default* datasource may impact this test + .overrideConfigKey("quarkus.datasource.db-kind", "h2") + .overrideConfigKey("quarkus.datasource.username", "sa") + .overrideConfigKey("quarkus.datasource.password", "sa") + .overrideConfigKey("quarkus.datasource.jdbc.url", + "jdbc:h2:tcp://localhost/mem:test-quarkus-migrate-at-start;DB_CLOSE_DELAY=-1"); + + @Inject + @FlywayDataSource("users") + Instance flywayForNamedDatasource; + + @Test + @DisplayName("If a named datasource is deactivated, the application should boot, but Flyway should be deactivated for that datasource") + public void testBootSucceedsButFlywayDeactivated() { + assertThatThrownBy(flywayForNamedDatasource::get) + .isInstanceOf(CreationException.class) + .cause() + .hasMessageContainingAll("Unable to find datasource 'users' for Flyway", + "Datasource 'users' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.\"users\".active'" + + " to 'true' and configure datasource 'users'", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } +} diff --git a/extensions/flyway/deployment/src/test/java/io/quarkus/flyway/test/FlywayExtensionMigrateAtStartDefaultDatasourceConfigActiveFalseTest.java b/extensions/flyway/deployment/src/test/java/io/quarkus/flyway/test/FlywayExtensionMigrateAtStartDefaultDatasourceConfigActiveFalseTest.java new file mode 100644 index 0000000000000..240237ff5d727 --- /dev/null +++ b/extensions/flyway/deployment/src/test/java/io/quarkus/flyway/test/FlywayExtensionMigrateAtStartDefaultDatasourceConfigActiveFalseTest.java @@ -0,0 +1,42 @@ +package io.quarkus.flyway.test; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import jakarta.enterprise.inject.CreationException; +import jakarta.enterprise.inject.Instance; +import jakarta.inject.Inject; + +import org.flywaydb.core.Flyway; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.test.QuarkusUnitTest; + +public class FlywayExtensionMigrateAtStartDefaultDatasourceConfigActiveFalseTest { + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .withApplicationRoot((jar) -> jar + .addAsResource("db/migration/V1.0.0__Quarkus.sql")) + .overrideConfigKey("quarkus.datasource.active", "false") + .overrideConfigKey("quarkus.flyway.migrate-at-start", "true"); + + @Inject + Instance flywayForDefaultDatasource; + + @Test + @DisplayName("If the default datasource is deactivated, even if migrate-at-start is enabled, the application should boot, but Flyway should be deactivated for that datasource") + public void testBootSucceedsButFlywayDeactivated() { + assertThatThrownBy(flywayForDefaultDatasource::get) + .isInstanceOf(CreationException.class) + .cause() + .hasMessageContainingAll("Unable to find datasource '' for Flyway", + "Datasource '' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.active'" + + " to 'true' and configure datasource ''", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } + +} diff --git a/extensions/flyway/deployment/src/test/java/io/quarkus/flyway/test/FlywayExtensionMigrateAtStartNamedDatasourceConfigActiveFalseTest.java b/extensions/flyway/deployment/src/test/java/io/quarkus/flyway/test/FlywayExtensionMigrateAtStartNamedDatasourceConfigActiveFalseTest.java new file mode 100644 index 0000000000000..7c2e303c9d4ce --- /dev/null +++ b/extensions/flyway/deployment/src/test/java/io/quarkus/flyway/test/FlywayExtensionMigrateAtStartNamedDatasourceConfigActiveFalseTest.java @@ -0,0 +1,52 @@ +package io.quarkus.flyway.test; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import jakarta.enterprise.inject.CreationException; +import jakarta.enterprise.inject.Instance; +import jakarta.inject.Inject; + +import org.flywaydb.core.Flyway; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.flyway.FlywayDataSource; +import io.quarkus.test.QuarkusUnitTest; + +public class FlywayExtensionMigrateAtStartNamedDatasourceConfigActiveFalseTest { + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .withApplicationRoot((jar) -> jar + .addAsResource("db/migration/V1.0.0__Quarkus.sql")) + .overrideConfigKey("quarkus.datasource.users.active", "false") + .overrideConfigKey("quarkus.flyway.users.migrate-at-start", "true") + // We need at least one build-time property for the datasource, + // otherwise it's considered unconfigured at build time... + .overrideConfigKey("quarkus.datasource.users.db-kind", "h2") + // We need this otherwise the *default* datasource may impact this test + .overrideConfigKey("quarkus.datasource.db-kind", "h2") + .overrideConfigKey("quarkus.datasource.username", "sa") + .overrideConfigKey("quarkus.datasource.password", "sa") + .overrideConfigKey("quarkus.datasource.jdbc.url", + "jdbc:h2:tcp://localhost/mem:test-quarkus-migrate-at-start;DB_CLOSE_DELAY=-1"); + + @Inject + @FlywayDataSource("users") + Instance flywayForNamedDatasource; + + @Test + @DisplayName("If a named datasource is deactivated, even if migrate-at-start is enabled, the application should boot, but Flyway should be deactivated for that datasource") + public void testBootSucceedsButFlywayDeactivated() { + assertThatThrownBy(flywayForNamedDatasource::get) + .isInstanceOf(CreationException.class) + .cause() + .hasMessageContainingAll("Unable to find datasource 'users' for Flyway", + "Datasource 'users' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.\"users\".active'" + + " to 'true' and configure datasource 'users'", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } +} diff --git a/extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/config/datasource/EntitiesInDefaultPUWithExplicitDatasourceConfigActiveFalseTest.java b/extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/config/datasource/EntitiesInDefaultPUWithExplicitDatasourceConfigActiveFalseTest.java new file mode 100644 index 0000000000000..570fdd3e6368f --- /dev/null +++ b/extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/config/datasource/EntitiesInDefaultPUWithExplicitDatasourceConfigActiveFalseTest.java @@ -0,0 +1,41 @@ +package io.quarkus.hibernate.orm.config.datasource; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.hibernate.orm.config.MyEntity; +import io.quarkus.runtime.configuration.ConfigurationException; +import io.quarkus.test.QuarkusUnitTest; + +public class EntitiesInDefaultPUWithExplicitDatasourceConfigActiveFalseTest { + + @RegisterExtension + static QuarkusUnitTest runner = new QuarkusUnitTest() + .withApplicationRoot((jar) -> jar + .addClass(MyEntity.class)) + .overrideConfigKey("quarkus.hibernate-orm.datasource", "ds-1") + .overrideConfigKey("quarkus.hibernate-orm.database.generation", "drop-and-create") + .overrideConfigKey("quarkus.datasource.\"ds-1\".active", "false") + // We need at least one build-time property for the datasource, + // otherwise it's considered unconfigured at build time... + .overrideConfigKey("quarkus.datasource.\"ds-1\".db-kind", "h2") + .assertException(t -> assertThat(t) + .isInstanceOf(ConfigurationException.class) + .hasMessageContainingAll( + "Unable to find datasource 'ds-1' for persistence unit ''", + "Datasource 'ds-1' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.\"ds-1\".active'" + + " to 'true' and configure datasource 'ds-1'", + "Refer to https://quarkus.io/guides/datasource for guidance.")); + + @Test + public void testInvalidConfiguration() { + // deployment exception should happen first + Assertions.fail(); + } + +} diff --git a/extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/config/datasource/EntitiesInDefaultPUWithImplicitDatasourceConfigActiveFalseTest.java b/extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/config/datasource/EntitiesInDefaultPUWithImplicitDatasourceConfigActiveFalseTest.java new file mode 100644 index 0000000000000..04e0448723341 --- /dev/null +++ b/extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/config/datasource/EntitiesInDefaultPUWithImplicitDatasourceConfigActiveFalseTest.java @@ -0,0 +1,36 @@ +package io.quarkus.hibernate.orm.config.datasource; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.hibernate.orm.config.MyEntity; +import io.quarkus.runtime.configuration.ConfigurationException; +import io.quarkus.test.QuarkusUnitTest; + +public class EntitiesInDefaultPUWithImplicitDatasourceConfigActiveFalseTest { + + @RegisterExtension + static QuarkusUnitTest runner = new QuarkusUnitTest() + .withApplicationRoot((jar) -> jar + .addClass(MyEntity.class)) + .overrideConfigKey("quarkus.datasource.active", "false") + .assertException(t -> assertThat(t) + .isInstanceOf(ConfigurationException.class) + .hasMessageContainingAll( + "Unable to find datasource '' for persistence unit ''", + "Datasource '' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.active'" + + " to 'true' and configure datasource ''", + "Refer to https://quarkus.io/guides/datasource for guidance.")); + + @Test + public void testInvalidConfiguration() { + // deployment exception should happen first + Assertions.fail(); + } + +} diff --git a/extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/config/datasource/EntitiesInNamedPUWithExplicitDatasourceConfigActiveFalseTest.java b/extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/config/datasource/EntitiesInNamedPUWithExplicitDatasourceConfigActiveFalseTest.java new file mode 100644 index 0000000000000..8f5f8c6904fc5 --- /dev/null +++ b/extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/config/datasource/EntitiesInNamedPUWithExplicitDatasourceConfigActiveFalseTest.java @@ -0,0 +1,41 @@ +package io.quarkus.hibernate.orm.config.datasource; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.hibernate.orm.config.namedpu.MyEntity; +import io.quarkus.runtime.configuration.ConfigurationException; +import io.quarkus.test.QuarkusUnitTest; + +public class EntitiesInNamedPUWithExplicitDatasourceConfigActiveFalseTest { + + @RegisterExtension + static QuarkusUnitTest runner = new QuarkusUnitTest() + .withApplicationRoot((jar) -> jar + .addPackage(MyEntity.class.getPackage().getName())) + .overrideConfigKey("quarkus.hibernate-orm.pu-1.datasource", "ds-1") + .overrideConfigKey("quarkus.hibernate-orm.pu-1.database.generation", "drop-and-create") + .overrideConfigKey("quarkus.datasource.\"ds-1\".active", "false") + // We need at least one build-time property for the datasource, + // otherwise it's considered unconfigured at build time... + .overrideConfigKey("quarkus.datasource.\"ds-1\".db-kind", "h2") + .assertException(t -> assertThat(t) + .isInstanceOf(ConfigurationException.class) + .hasMessageContainingAll( + "Unable to find datasource 'ds-1' for persistence unit 'pu-1'", + "Datasource 'ds-1' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.\"ds-1\".active'" + + " to 'true' and configure datasource 'ds-1'", + "Refer to https://quarkus.io/guides/datasource for guidance.")); + + @Test + public void testInvalidConfiguration() { + // deployment exception should happen first + Assertions.fail(); + } + +} diff --git a/extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/config/datasource/MultiplePUAsAlternativesWithActivePU1Test.java b/extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/config/datasource/MultiplePUAsAlternativesWithActivePU1Test.java new file mode 100644 index 0000000000000..298c13516a675 --- /dev/null +++ b/extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/config/datasource/MultiplePUAsAlternativesWithActivePU1Test.java @@ -0,0 +1,119 @@ +package io.quarkus.hibernate.orm.config.datasource; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.Produces; +import jakarta.inject.Inject; + +import org.hibernate.Session; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.datasource.runtime.DataSourceSupport; +import io.quarkus.hibernate.orm.PersistenceUnit; +import io.quarkus.hibernate.orm.config.namedpu.MyEntity; +import io.quarkus.narayana.jta.QuarkusTransaction; +import io.quarkus.test.QuarkusUnitTest; + +/** + * Tests a use case where multiple PU/datasources are defined at build time, + * but only one is used at runtime. + *

+ * This is mostly useful when each datasource has a distinct db-kind, but in theory that shouldn't matter, + * so we use the h2 db-kind everywhere here to keep test dependencies simpler. + *

+ * See {@link MultiplePUAsAlternativesWithActivePU2Test} for the counterpart where PU2 is used at runtime. + */ +public class MultiplePUAsAlternativesWithActivePU1Test { + + @RegisterExtension + static QuarkusUnitTest runner = new QuarkusUnitTest() + .withApplicationRoot((jar) -> jar + .addPackage(MyEntity.class.getPackage().getName()) + .addClass(MyProducer.class)) + .overrideConfigKey("quarkus.hibernate-orm.pu-1.packages", MyEntity.class.getPackageName()) + .overrideConfigKey("quarkus.hibernate-orm.pu-1.datasource", "ds-1") + .overrideConfigKey("quarkus.hibernate-orm.pu-1.database.generation", "drop-and-create") + .overrideConfigKey("quarkus.hibernate-orm.pu-1.active", "false") + .overrideConfigKey("quarkus.datasource.ds-1.db-kind", "h2") + .overrideConfigKey("quarkus.datasource.ds-1.active", "false") + .overrideConfigKey("quarkus.hibernate-orm.pu-2.packages", MyEntity.class.getPackageName()) + .overrideConfigKey("quarkus.hibernate-orm.pu-2.datasource", "ds-2") + .overrideConfigKey("quarkus.hibernate-orm.pu-2.database.generation", "drop-and-create") + .overrideConfigKey("quarkus.hibernate-orm.pu-2.active", "false") + .overrideConfigKey("quarkus.datasource.ds-2.db-kind", "h2") + .overrideConfigKey("quarkus.datasource.ds-2.active", "false") + // This is where we select PU1 / datasource 1 + .overrideRuntimeConfigKey("quarkus.hibernate-orm.pu-1.active", "true") + .overrideRuntimeConfigKey("quarkus.datasource.ds-1.active", "true") + .overrideRuntimeConfigKey("quarkus.datasource.ds-1.jdbc.url", "jdbc:h2:mem:testds1"); + + @Inject + @PersistenceUnit("pu-1") + Session explicitSessionBean; + + @Inject + Session customIndirectSessionBean; + + @Inject + @PersistenceUnit("pu-2") + Session inactiveSessionBean; + + @Test + public void testExplicitSessionBeanUsable() { + doTestPersistRetrieve(explicitSessionBean, 1L); + } + + @Test + public void testCustomIndirectSessionBeanUsable() { + doTestPersistRetrieve(customIndirectSessionBean, 2L); + } + + @Test + public void testInactiveSessionBeanUnusable() { + QuarkusTransaction.requiringNew().run(() -> { + assertThatThrownBy(() -> inactiveSessionBean.find(MyEntity.class, 3L)) + .hasMessageContainingAll( + "Cannot retrieve the EntityManagerFactory/SessionFactory for persistence unit pu-2", + "Hibernate ORM was deactivated through configuration properties"); + }); + } + + private static void doTestPersistRetrieve(Session session, long id) { + QuarkusTransaction.requiringNew().run(() -> { + MyEntity entity = new MyEntity(); + entity.setId(id); + entity.setName("text" + id); + session.persist(entity); + }); + QuarkusTransaction.requiringNew().run(() -> { + MyEntity entity = session.get(MyEntity.class, id); + assertThat(entity.getName()).isEqualTo("text" + id); + }); + } + + private static class MyProducer { + @Inject + DataSourceSupport dataSourceSupport; + + @Inject + @PersistenceUnit("pu-1") + Session pu1SessionBean; + + @Inject + @PersistenceUnit("pu-2") + Session pu2SessionBean; + + @Produces + @ApplicationScoped + public Session session() { + if (dataSourceSupport.getInactiveNames().contains("ds-1")) { + return pu2SessionBean; + } else { + return pu1SessionBean; + } + } + } +} diff --git a/extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/config/datasource/MultiplePUAsAlternativesWithActivePU2Test.java b/extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/config/datasource/MultiplePUAsAlternativesWithActivePU2Test.java new file mode 100644 index 0000000000000..c9eb9d247962a --- /dev/null +++ b/extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/config/datasource/MultiplePUAsAlternativesWithActivePU2Test.java @@ -0,0 +1,119 @@ +package io.quarkus.hibernate.orm.config.datasource; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.Produces; +import jakarta.inject.Inject; + +import org.hibernate.Session; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.datasource.runtime.DataSourceSupport; +import io.quarkus.hibernate.orm.PersistenceUnit; +import io.quarkus.hibernate.orm.config.namedpu.MyEntity; +import io.quarkus.narayana.jta.QuarkusTransaction; +import io.quarkus.test.QuarkusUnitTest; + +/** + * Tests a use case where multiple PU/datasources are defined at build time, + * but only one is used at runtime. + *

+ * This is mostly useful when each datasource has a distinct db-kind, but in theory that shouldn't matter, + * so we use the h2 db-kind everywhere here to keep test dependencies simpler. + *

+ * See {@link MultiplePUAsAlternativesWithActivePU1Test} for the counterpart where PU1 is used at runtime. + */ +public class MultiplePUAsAlternativesWithActivePU2Test { + + @RegisterExtension + static QuarkusUnitTest runner = new QuarkusUnitTest() + .withApplicationRoot((jar) -> jar + .addPackage(MyEntity.class.getPackage().getName()) + .addClass(MyProducer.class)) + .overrideConfigKey("quarkus.hibernate-orm.pu-1.packages", MyEntity.class.getPackageName()) + .overrideConfigKey("quarkus.hibernate-orm.pu-1.datasource", "ds-1") + .overrideConfigKey("quarkus.hibernate-orm.pu-1.database.generation", "drop-and-create") + .overrideConfigKey("quarkus.hibernate-orm.pu-1.active", "false") + .overrideConfigKey("quarkus.datasource.ds-1.db-kind", "h2") + .overrideConfigKey("quarkus.datasource.ds-1.active", "false") + .overrideConfigKey("quarkus.hibernate-orm.pu-2.packages", MyEntity.class.getPackageName()) + .overrideConfigKey("quarkus.hibernate-orm.pu-2.datasource", "ds-2") + .overrideConfigKey("quarkus.hibernate-orm.pu-2.database.generation", "drop-and-create") + .overrideConfigKey("quarkus.hibernate-orm.pu-2.active", "false") + .overrideConfigKey("quarkus.datasource.ds-2.db-kind", "h2") + .overrideConfigKey("quarkus.datasource.ds-2.active", "false") + // This is where we select PU1 / datasource 2 + .overrideRuntimeConfigKey("quarkus.hibernate-orm.pu-2.active", "true") + .overrideRuntimeConfigKey("quarkus.datasource.ds-2.active", "true") + .overrideRuntimeConfigKey("quarkus.datasource.ds-2.jdbc.url", "jdbc:h2:mem:testds2"); + + @Inject + @PersistenceUnit("pu-2") + Session explicitSessionBean; + + @Inject + Session customIndirectSessionBean; + + @Inject + @PersistenceUnit("pu-1") + Session inactiveSessionBean; + + @Test + public void testExplicitSessionBeanUsable() { + doTestPersistRetrieve(explicitSessionBean, 1L); + } + + @Test + public void testCustomIndirectSessionBeanUsable() { + doTestPersistRetrieve(customIndirectSessionBean, 2L); + } + + @Test + public void testInactiveSessionBeanUnusable() { + QuarkusTransaction.requiringNew().run(() -> { + assertThatThrownBy(() -> inactiveSessionBean.find(MyEntity.class, 3L)) + .hasMessageContainingAll( + "Cannot retrieve the EntityManagerFactory/SessionFactory for persistence unit pu-1", + "Hibernate ORM was deactivated through configuration properties"); + }); + } + + private static void doTestPersistRetrieve(Session session, long id) { + QuarkusTransaction.requiringNew().run(() -> { + MyEntity entity = new MyEntity(); + entity.setId(id); + entity.setName("text" + id); + session.persist(entity); + }); + QuarkusTransaction.requiringNew().run(() -> { + MyEntity entity = session.get(MyEntity.class, id); + assertThat(entity.getName()).isEqualTo("text" + id); + }); + } + + private static class MyProducer { + @Inject + DataSourceSupport dataSourceSupport; + + @Inject + @PersistenceUnit("pu-1") + Session pu1SessionBean; + + @Inject + @PersistenceUnit("pu-2") + Session pu2SessionBean; + + @Produces + @ApplicationScoped + public Session session() { + if (dataSourceSupport.getInactiveNames().contains("ds-1")) { + return pu2SessionBean; + } else { + return pu1SessionBean; + } + } + } +} diff --git a/extensions/hibernate-reactive/deployment/src/test/java/io/quarkus/hibernate/reactive/config/datasource/EntitiesInDefaultPUWithImplicitDatasourceConfigActiveFalseTest.java b/extensions/hibernate-reactive/deployment/src/test/java/io/quarkus/hibernate/reactive/config/datasource/EntitiesInDefaultPUWithImplicitDatasourceConfigActiveFalseTest.java new file mode 100644 index 0000000000000..80ed019c91ce2 --- /dev/null +++ b/extensions/hibernate-reactive/deployment/src/test/java/io/quarkus/hibernate/reactive/config/datasource/EntitiesInDefaultPUWithImplicitDatasourceConfigActiveFalseTest.java @@ -0,0 +1,37 @@ +package io.quarkus.hibernate.reactive.config.datasource; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.hibernate.reactive.config.MyEntity; +import io.quarkus.runtime.configuration.ConfigurationException; +import io.quarkus.test.QuarkusUnitTest; + +public class EntitiesInDefaultPUWithImplicitDatasourceConfigActiveFalseTest { + + @RegisterExtension + static QuarkusUnitTest runner = new QuarkusUnitTest() + .withApplicationRoot((jar) -> jar + .addClass(MyEntity.class)) + .withConfigurationResource("application.properties") + .overrideConfigKey("quarkus.datasource.active", "false") + .assertException(t -> assertThat(t) + .isInstanceOf(ConfigurationException.class) + .hasMessageContainingAll( + "Unable to find datasource '' for persistence unit 'default-reactive'", + "Datasource '' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.active'" + + " to 'true' and configure datasource ''", + "Refer to https://quarkus.io/guides/datasource for guidance.")); + + @Test + public void testInvalidConfiguration() { + // deployment exception should happen first + Assertions.fail(); + } + +} diff --git a/extensions/liquibase/deployment/src/test/java/io/quarkus/liquibase/test/LiquibaseExtensionConfigActiveFalseDefaultDatasourceTest.java b/extensions/liquibase/deployment/src/test/java/io/quarkus/liquibase/test/LiquibaseExtensionConfigActiveFalseDefaultDatasourceTest.java new file mode 100644 index 0000000000000..ed35e12bfd237 --- /dev/null +++ b/extensions/liquibase/deployment/src/test/java/io/quarkus/liquibase/test/LiquibaseExtensionConfigActiveFalseDefaultDatasourceTest.java @@ -0,0 +1,39 @@ +package io.quarkus.liquibase.test; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import jakarta.enterprise.inject.CreationException; +import jakarta.enterprise.inject.Instance; +import jakarta.inject.Inject; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.liquibase.LiquibaseFactory; +import io.quarkus.test.QuarkusUnitTest; + +public class LiquibaseExtensionConfigActiveFalseDefaultDatasourceTest { + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .overrideConfigKey("quarkus.datasource.active", "false"); + + @Inject + Instance liquibaseForDefaultDatasource; + + @Test + @DisplayName("If the default datasource is deactivated, the application should boot, but Liquibase should be deactivated for that datasource") + public void testBootSucceedsButLiquibaseDeactivated() { + assertThatThrownBy(() -> liquibaseForDefaultDatasource.get().getConfiguration()) + .isInstanceOf(CreationException.class) + .cause() + .hasMessageContainingAll("Unable to find datasource '' for Liquibase", + "Datasource '' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.active'" + + " to 'true' and configure datasource ''", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } + +} diff --git a/extensions/liquibase/deployment/src/test/java/io/quarkus/liquibase/test/LiquibaseExtensionConfigActiveFalseNamedDatasourceTest.java b/extensions/liquibase/deployment/src/test/java/io/quarkus/liquibase/test/LiquibaseExtensionConfigActiveFalseNamedDatasourceTest.java new file mode 100644 index 0000000000000..583e2d934dadc --- /dev/null +++ b/extensions/liquibase/deployment/src/test/java/io/quarkus/liquibase/test/LiquibaseExtensionConfigActiveFalseNamedDatasourceTest.java @@ -0,0 +1,48 @@ +package io.quarkus.liquibase.test; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import jakarta.enterprise.inject.CreationException; +import jakarta.enterprise.inject.Instance; +import jakarta.inject.Inject; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.liquibase.LiquibaseDataSource; +import io.quarkus.liquibase.LiquibaseFactory; +import io.quarkus.test.QuarkusUnitTest; + +public class LiquibaseExtensionConfigActiveFalseNamedDatasourceTest { + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .overrideConfigKey("quarkus.datasource.users.active", "false") + // We need at least one build-time property for the datasource, + // otherwise it's considered unconfigured at build time... + .overrideConfigKey("quarkus.datasource.users.db-kind", "h2") + // We need this otherwise it's going to be the *default* datasource making everything fail + .overrideConfigKey("quarkus.datasource.db-kind", "h2") + .overrideConfigKey("quarkus.datasource.username", "sa") + .overrideConfigKey("quarkus.datasource.password", "sa") + .overrideConfigKey("quarkus.datasource.jdbc.url", + "jdbc:h2:tcp://localhost/mem:test-quarkus-migrate-at-start;DB_CLOSE_DELAY=-1"); + @Inject + @LiquibaseDataSource("users") + Instance liquibaseForNamedDatasource; + + @Test + @DisplayName("If a named datasource is deactivated, the application should boot, but Liquibase should be deactivated for that datasource") + public void testBootSucceedsButLiquibaseDeactivated() { + assertThatThrownBy(() -> liquibaseForNamedDatasource.get().getConfiguration()) + .isInstanceOf(CreationException.class) + .cause() + .hasMessageContainingAll("Unable to find datasource 'users' for Liquibase", + "Datasource 'users' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.\"users\".active'" + + " to 'true' and configure datasource 'users'", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } +} diff --git a/extensions/liquibase/deployment/src/test/java/io/quarkus/liquibase/test/LiquibaseExtensionMigrateAtStartDefaultDatasourceConfigActiveFalseTest.java b/extensions/liquibase/deployment/src/test/java/io/quarkus/liquibase/test/LiquibaseExtensionMigrateAtStartDefaultDatasourceConfigActiveFalseTest.java new file mode 100644 index 0000000000000..dccc77efe2e06 --- /dev/null +++ b/extensions/liquibase/deployment/src/test/java/io/quarkus/liquibase/test/LiquibaseExtensionMigrateAtStartDefaultDatasourceConfigActiveFalseTest.java @@ -0,0 +1,42 @@ +package io.quarkus.liquibase.test; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import jakarta.enterprise.inject.CreationException; +import jakarta.enterprise.inject.Instance; +import jakarta.inject.Inject; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.liquibase.LiquibaseFactory; +import io.quarkus.test.QuarkusUnitTest; + +public class LiquibaseExtensionMigrateAtStartDefaultDatasourceConfigActiveFalseTest { + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .withApplicationRoot((jar) -> jar + .addAsResource("db/changeLog.xml", "db/changeLog.xml")) + .overrideConfigKey("quarkus.datasource.active", "false") + .overrideConfigKey("quarkus.liquibase.migrate-at-start", "true"); + + @Inject + Instance liquibaseForDefaultDatasource; + + @Test + @DisplayName("If the default datasource is deactivated, even if migrate-at-start is enabled, the application should boot, but Liquibase should be deactivated for that datasource") + public void testBootSucceedsButLiquibaseDeactivated() { + assertThatThrownBy(() -> liquibaseForDefaultDatasource.get().getConfiguration()) + .isInstanceOf(CreationException.class) + .cause() + .hasMessageContainingAll("Unable to find datasource '' for Liquibase", + "Datasource '' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.active'" + + " to 'true' and configure datasource ''", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } + +} diff --git a/extensions/liquibase/deployment/src/test/java/io/quarkus/liquibase/test/LiquibaseExtensionMigrateAtStartNamedDatasourceConfigActiveFalseTest.java b/extensions/liquibase/deployment/src/test/java/io/quarkus/liquibase/test/LiquibaseExtensionMigrateAtStartNamedDatasourceConfigActiveFalseTest.java new file mode 100644 index 0000000000000..bfc68585954d6 --- /dev/null +++ b/extensions/liquibase/deployment/src/test/java/io/quarkus/liquibase/test/LiquibaseExtensionMigrateAtStartNamedDatasourceConfigActiveFalseTest.java @@ -0,0 +1,52 @@ +package io.quarkus.liquibase.test; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import jakarta.enterprise.inject.CreationException; +import jakarta.enterprise.inject.Instance; +import jakarta.inject.Inject; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.liquibase.LiquibaseDataSource; +import io.quarkus.liquibase.LiquibaseFactory; +import io.quarkus.test.QuarkusUnitTest; + +public class LiquibaseExtensionMigrateAtStartNamedDatasourceConfigActiveFalseTest { + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .withApplicationRoot((jar) -> jar + .addAsResource("db/changeLog.xml", "db/changeLog.xml")) + .overrideConfigKey("quarkus.datasource.users.active", "false") + .overrideConfigKey("quarkus.liquibase.users.migrate-at-start", "true") + // We need at least one build-time property for the datasource, + // otherwise it's considered unconfigured at build time... + .overrideConfigKey("quarkus.datasource.users.db-kind", "h2") + // We need this otherwise it's going to be the *default* datasource making everything fail + .overrideConfigKey("quarkus.datasource.db-kind", "h2") + .overrideConfigKey("quarkus.datasource.username", "sa") + .overrideConfigKey("quarkus.datasource.password", "sa") + .overrideConfigKey("quarkus.datasource.jdbc.url", + "jdbc:h2:tcp://localhost/mem:test-quarkus-migrate-at-start;DB_CLOSE_DELAY=-1"); + + @Inject + @LiquibaseDataSource("users") + Instance liquibaseForNamedDatasource; + + @Test + @DisplayName("If a named datasource is deactivated, even if migrate-at-start is enabled, the application should boot, but Liquibase should be deactivated for that datasource") + public void testBootSucceedsButLiquibaseDeactivated() { + assertThatThrownBy(() -> liquibaseForNamedDatasource.get().getConfiguration()) + .isInstanceOf(CreationException.class) + .cause() + .hasMessageContainingAll("Unable to find datasource 'users' for Liquibase", + "Datasource 'users' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.\"users\".active'" + + " to 'true' and configure datasource 'users'", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } +} diff --git a/extensions/reactive-mssql-client/deployment/src/test/java/io/quarkus/reactive/mssql/client/ConfigActiveFalseDefaultDatasourceTest.java b/extensions/reactive-mssql-client/deployment/src/test/java/io/quarkus/reactive/mssql/client/ConfigActiveFalseDefaultDatasourceTest.java new file mode 100644 index 0000000000000..8ad9fbeb363d6 --- /dev/null +++ b/extensions/reactive-mssql-client/deployment/src/test/java/io/quarkus/reactive/mssql/client/ConfigActiveFalseDefaultDatasourceTest.java @@ -0,0 +1,133 @@ +package io.quarkus.reactive.mssql.client; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.util.concurrent.CompletionStage; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.arc.Arc; +import io.quarkus.runtime.configuration.ConfigurationException; +import io.quarkus.test.QuarkusUnitTest; +import io.vertx.mssqlclient.MSSQLPool; +import io.vertx.sqlclient.Pool; + +public class ConfigActiveFalseDefaultDatasourceTest { + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .overrideConfigKey("quarkus.datasource.active", "false"); + + @Inject + MyBean myBean; + + @Test + public void pool() { + Pool pool = Arc.container().instance(Pool.class).get(); + + // The bean is always available to be injected during static init + // since we don't know whether the datasource will be active at runtime. + // So the bean cannot be null. + assertThat(pool).isNotNull(); + // However, any attempt to use it at runtime will fail. + assertThatThrownBy(() -> pool.getConnection()) + .isInstanceOf(RuntimeException.class) + .cause() + .isInstanceOf(ConfigurationException.class) + .hasMessageContainingAll("Datasource '' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.active'" + + " to 'true' and configure datasource ''", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } + + @Test + public void mutinyPool() { + io.vertx.mutiny.sqlclient.Pool pool = Arc.container().instance(io.vertx.mutiny.sqlclient.Pool.class).get(); + + // The bean is always available to be injected during static init + // since we don't know whether the datasource will be active at runtime. + // So the bean cannot be null. + assertThat(pool).isNotNull(); + // However, any attempt to use it at runtime will fail. + assertThatThrownBy(() -> pool.getConnection()) + .isInstanceOf(RuntimeException.class) + .cause() + .isInstanceOf(ConfigurationException.class) + .hasMessageContainingAll("Datasource '' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.active'" + + " to 'true' and configure datasource ''", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } + + @Test + public void vendorPool() { + MSSQLPool pool = Arc.container().instance(MSSQLPool.class).get(); + + // The bean is always available to be injected during static init + // since we don't know whether the datasource will be active at runtime. + // So the bean cannot be null. + assertThat(pool).isNotNull(); + // However, any attempt to use it at runtime will fail. + assertThatThrownBy(() -> pool.getConnection()) + .isInstanceOf(RuntimeException.class) + .cause() + .isInstanceOf(ConfigurationException.class) + .hasMessageContainingAll("Datasource '' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.active'" + + " to 'true' and configure datasource ''", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } + + @Test + public void mutinyVendorPool() { + io.vertx.mutiny.mssqlclient.MSSQLPool pool = Arc.container().instance(io.vertx.mutiny.mssqlclient.MSSQLPool.class) + .get(); + + // The bean is always available to be injected during static init + // since we don't know whether the datasource will be active at runtime. + // So the bean cannot be null. + assertThat(pool).isNotNull(); + // However, any attempt to use it at runtime will fail. + assertThatThrownBy(() -> pool.getConnection()) + .isInstanceOf(RuntimeException.class) + .cause() + .isInstanceOf(ConfigurationException.class) + .hasMessageContainingAll("Datasource '' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.active'" + + " to 'true' and configure datasource ''", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } + + @Test + public void injectedBean() { + // However, any attempt to use it at runtime will fail. + assertThatThrownBy(() -> myBean.usePool()) + .isInstanceOf(RuntimeException.class) + .cause() + .isInstanceOf(ConfigurationException.class) + .hasMessageContainingAll("Datasource '' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.active'" + + " to 'true' and configure datasource ''", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } + + @ApplicationScoped + public static class MyBean { + @Inject + Pool pool; + + public CompletionStage usePool() { + return pool.getConnection().toCompletionStage(); + } + } +} diff --git a/extensions/reactive-mssql-client/deployment/src/test/java/io/quarkus/reactive/mssql/client/ConfigActiveFalseNamedDatasourceTest.java b/extensions/reactive-mssql-client/deployment/src/test/java/io/quarkus/reactive/mssql/client/ConfigActiveFalseNamedDatasourceTest.java new file mode 100644 index 0000000000000..352e3bb17086f --- /dev/null +++ b/extensions/reactive-mssql-client/deployment/src/test/java/io/quarkus/reactive/mssql/client/ConfigActiveFalseNamedDatasourceTest.java @@ -0,0 +1,140 @@ +package io.quarkus.reactive.mssql.client; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.util.concurrent.CompletionStage; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.arc.Arc; +import io.quarkus.reactive.datasource.ReactiveDataSource; +import io.quarkus.runtime.configuration.ConfigurationException; +import io.quarkus.test.QuarkusUnitTest; +import io.vertx.mssqlclient.MSSQLPool; +import io.vertx.sqlclient.Pool; + +public class ConfigActiveFalseNamedDatasourceTest { + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .overrideConfigKey("quarkus.datasource.ds-1.active", "false") + // We need at least one build-time property for the datasource, + // otherwise it's considered unconfigured at build time... + .overrideConfigKey("quarkus.datasource.ds-1.db-kind", "mssql"); + + @Inject + MyBean myBean; + + @Test + public void pool() { + Pool pool = Arc.container().instance(Pool.class, + new ReactiveDataSource.ReactiveDataSourceLiteral("ds-1")).get(); + + // The bean is always available to be injected during static init + // since we don't know whether the datasource will be active at runtime. + // So the bean cannot be null. + assertThat(pool).isNotNull(); + // However, any attempt to use it at runtime will fail. + assertThatThrownBy(() -> pool.getConnection()) + .isInstanceOf(RuntimeException.class) + .cause() + .isInstanceOf(ConfigurationException.class) + .hasMessageContainingAll("Datasource 'ds-1' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.\"ds-1\".active'" + + " to 'true' and configure datasource 'ds-1'", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } + + @Test + public void mutinyPool() { + io.vertx.mutiny.sqlclient.Pool pool = Arc.container().instance(io.vertx.mutiny.sqlclient.Pool.class, + new ReactiveDataSource.ReactiveDataSourceLiteral("ds-1")).get(); + + // The bean is always available to be injected during static init + // since we don't know whether the datasource will be active at runtime. + // So the bean cannot be null. + assertThat(pool).isNotNull(); + // However, any attempt to use it at runtime will fail. + assertThatThrownBy(() -> pool.getConnection()) + .isInstanceOf(RuntimeException.class) + .cause() + .isInstanceOf(ConfigurationException.class) + .hasMessageContainingAll("Datasource 'ds-1' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.\"ds-1\".active'" + + " to 'true' and configure datasource 'ds-1'", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } + + @Test + public void vendorPool() { + MSSQLPool pool = Arc.container().instance(MSSQLPool.class, + new ReactiveDataSource.ReactiveDataSourceLiteral("ds-1")).get(); + + // The bean is always available to be injected during static init + // since we don't know whether the datasource will be active at runtime. + // So the bean cannot be null. + assertThat(pool).isNotNull(); + // However, any attempt to use it at runtime will fail. + assertThatThrownBy(() -> pool.getConnection()) + .isInstanceOf(RuntimeException.class) + .cause() + .isInstanceOf(ConfigurationException.class) + .hasMessageContainingAll("Datasource 'ds-1' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.\"ds-1\".active'" + + " to 'true' and configure datasource 'ds-1'", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } + + @Test + public void mutinyVendorPool() { + io.vertx.mutiny.mssqlclient.MSSQLPool pool = Arc.container().instance(io.vertx.mutiny.mssqlclient.MSSQLPool.class, + new ReactiveDataSource.ReactiveDataSourceLiteral("ds-1")).get(); + + // The bean is always available to be injected during static init + // since we don't know whether the datasource will be active at runtime. + // So the bean cannot be null. + assertThat(pool).isNotNull(); + // However, any attempt to use it at runtime will fail. + assertThatThrownBy(() -> pool.getConnection()) + .isInstanceOf(RuntimeException.class) + .cause() + .isInstanceOf(ConfigurationException.class) + .hasMessageContainingAll("Datasource 'ds-1' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.\"ds-1\".active'" + + " to 'true' and configure datasource 'ds-1'", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } + + @Test + public void injectedBean() { + assertThatThrownBy(() -> myBean.usePool()) + .isInstanceOf(RuntimeException.class) + .cause() + .isInstanceOf(ConfigurationException.class) + .hasMessageContainingAll("Datasource 'ds-1' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.\"ds-1\".active'" + + " to 'true' and configure datasource 'ds-1'", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } + + @ApplicationScoped + public static class MyBean { + @Inject + @ReactiveDataSource("ds-1") + Pool pool; + + public CompletionStage usePool() { + return pool.getConnection().toCompletionStage(); + } + } +} diff --git a/extensions/reactive-mssql-client/deployment/src/test/java/io/quarkus/reactive/mssql/client/DataSourceHealthCheckConfigActiveFalseTest.java b/extensions/reactive-mssql-client/deployment/src/test/java/io/quarkus/reactive/mssql/client/DataSourceHealthCheckConfigActiveFalseTest.java new file mode 100644 index 0000000000000..08f702e03f64d --- /dev/null +++ b/extensions/reactive-mssql-client/deployment/src/test/java/io/quarkus/reactive/mssql/client/DataSourceHealthCheckConfigActiveFalseTest.java @@ -0,0 +1,30 @@ +package io.quarkus.reactive.mssql.client; + +import org.hamcrest.CoreMatchers; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.test.QuarkusUnitTest; +import io.restassured.RestAssured; + +public class DataSourceHealthCheckConfigActiveFalseTest { + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .withEmptyApplication() + .withConfigurationResource("application-default-datasource.properties") + .overrideConfigKey("quarkus.datasource.health.enabled", "true") + // this data source is broken, but will be deactivated, + // so the overall check should pass + .overrideConfigKey("quarkus.datasource.brokenDS.db-kind", "mssql") + .overrideConfigKey("quarkus.datasource.brokenDS.reactive.url", "BROKEN") + .overrideConfigKey("quarkus.datasource.brokenDS.active", "false"); + + @Test + public void testDataSourceHealthCheckExclusion() { + RestAssured.when().get("/q/health/ready") + .then() + .body("status", CoreMatchers.equalTo("UP")); + } + +} diff --git a/extensions/reactive-mysql-client/deployment/src/test/java/io/quarkus/reactive/mysql/client/ConfigActiveFalseDefaultDatasourceTest.java b/extensions/reactive-mysql-client/deployment/src/test/java/io/quarkus/reactive/mysql/client/ConfigActiveFalseDefaultDatasourceTest.java new file mode 100644 index 0000000000000..0a7e67f1f6fe1 --- /dev/null +++ b/extensions/reactive-mysql-client/deployment/src/test/java/io/quarkus/reactive/mysql/client/ConfigActiveFalseDefaultDatasourceTest.java @@ -0,0 +1,133 @@ +package io.quarkus.reactive.mysql.client; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.util.concurrent.CompletionStage; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.arc.Arc; +import io.quarkus.runtime.configuration.ConfigurationException; +import io.quarkus.test.QuarkusUnitTest; +import io.vertx.mysqlclient.MySQLPool; +import io.vertx.sqlclient.Pool; + +public class ConfigActiveFalseDefaultDatasourceTest { + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .overrideConfigKey("quarkus.datasource.active", "false"); + + @Inject + MyBean myBean; + + @Test + public void pool() { + Pool pool = Arc.container().instance(Pool.class).get(); + + // The bean is always available to be injected during static init + // since we don't know whether the datasource will be active at runtime. + // So the bean cannot be null. + assertThat(pool).isNotNull(); + // However, any attempt to use it at runtime will fail. + assertThatThrownBy(() -> pool.getConnection()) + .isInstanceOf(RuntimeException.class) + .cause() + .isInstanceOf(ConfigurationException.class) + .hasMessageContainingAll("Datasource '' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.active'" + + " to 'true' and configure datasource ''", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } + + @Test + public void mutinyPool() { + io.vertx.mutiny.sqlclient.Pool pool = Arc.container().instance(io.vertx.mutiny.sqlclient.Pool.class).get(); + + // The bean is always available to be injected during static init + // since we don't know whether the datasource will be active at runtime. + // So the bean cannot be null. + assertThat(pool).isNotNull(); + // However, any attempt to use it at runtime will fail. + assertThatThrownBy(() -> pool.getConnection()) + .isInstanceOf(RuntimeException.class) + .cause() + .isInstanceOf(ConfigurationException.class) + .hasMessageContainingAll("Datasource '' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.active'" + + " to 'true' and configure datasource ''", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } + + @Test + public void vendorPool() { + MySQLPool pool = Arc.container().instance(MySQLPool.class).get(); + + // The bean is always available to be injected during static init + // since we don't know whether the datasource will be active at runtime. + // So the bean cannot be null. + assertThat(pool).isNotNull(); + // However, any attempt to use it at runtime will fail. + assertThatThrownBy(() -> pool.getConnection()) + .isInstanceOf(RuntimeException.class) + .cause() + .isInstanceOf(ConfigurationException.class) + .hasMessageContainingAll("Datasource '' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.active'" + + " to 'true' and configure datasource ''", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } + + @Test + public void mutinyVendorPool() { + io.vertx.mutiny.mysqlclient.MySQLPool pool = Arc.container().instance(io.vertx.mutiny.mysqlclient.MySQLPool.class) + .get(); + + // The bean is always available to be injected during static init + // since we don't know whether the datasource will be active at runtime. + // So the bean cannot be null. + assertThat(pool).isNotNull(); + // However, any attempt to use it at runtime will fail. + assertThatThrownBy(() -> pool.getConnection()) + .isInstanceOf(RuntimeException.class) + .cause() + .isInstanceOf(ConfigurationException.class) + .hasMessageContainingAll("Datasource '' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.active'" + + " to 'true' and configure datasource ''", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } + + @Test + public void injectedBean() { + // However, any attempt to use it at runtime will fail. + assertThatThrownBy(() -> myBean.usePool()) + .isInstanceOf(RuntimeException.class) + .cause() + .isInstanceOf(ConfigurationException.class) + .hasMessageContainingAll("Datasource '' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.active'" + + " to 'true' and configure datasource ''", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } + + @ApplicationScoped + public static class MyBean { + @Inject + Pool pool; + + public CompletionStage usePool() { + return pool.getConnection().toCompletionStage(); + } + } +} diff --git a/extensions/reactive-mysql-client/deployment/src/test/java/io/quarkus/reactive/mysql/client/ConfigActiveFalseNamedDatasourceTest.java b/extensions/reactive-mysql-client/deployment/src/test/java/io/quarkus/reactive/mysql/client/ConfigActiveFalseNamedDatasourceTest.java new file mode 100644 index 0000000000000..5a6ba912c67cd --- /dev/null +++ b/extensions/reactive-mysql-client/deployment/src/test/java/io/quarkus/reactive/mysql/client/ConfigActiveFalseNamedDatasourceTest.java @@ -0,0 +1,140 @@ +package io.quarkus.reactive.mysql.client; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.util.concurrent.CompletionStage; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.arc.Arc; +import io.quarkus.reactive.datasource.ReactiveDataSource; +import io.quarkus.runtime.configuration.ConfigurationException; +import io.quarkus.test.QuarkusUnitTest; +import io.vertx.mysqlclient.MySQLPool; +import io.vertx.sqlclient.Pool; + +public class ConfigActiveFalseNamedDatasourceTest { + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .overrideConfigKey("quarkus.datasource.ds-1.active", "false") + // We need at least one build-time property for the datasource, + // otherwise it's considered unconfigured at build time... + .overrideConfigKey("quarkus.datasource.ds-1.db-kind", "mysql"); + + @Inject + MyBean myBean; + + @Test + public void pool() { + Pool pool = Arc.container().instance(Pool.class, + new ReactiveDataSource.ReactiveDataSourceLiteral("ds-1")).get(); + + // The bean is always available to be injected during static init + // since we don't know whether the datasource will be active at runtime. + // So the bean cannot be null. + assertThat(pool).isNotNull(); + // However, any attempt to use it at runtime will fail. + assertThatThrownBy(() -> pool.getConnection()) + .isInstanceOf(RuntimeException.class) + .cause() + .isInstanceOf(ConfigurationException.class) + .hasMessageContainingAll("Datasource 'ds-1' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.\"ds-1\".active'" + + " to 'true' and configure datasource 'ds-1'", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } + + @Test + public void mutinyPool() { + io.vertx.mutiny.sqlclient.Pool pool = Arc.container().instance(io.vertx.mutiny.sqlclient.Pool.class, + new ReactiveDataSource.ReactiveDataSourceLiteral("ds-1")).get(); + + // The bean is always available to be injected during static init + // since we don't know whether the datasource will be active at runtime. + // So the bean cannot be null. + assertThat(pool).isNotNull(); + // However, any attempt to use it at runtime will fail. + assertThatThrownBy(() -> pool.getConnection()) + .isInstanceOf(RuntimeException.class) + .cause() + .isInstanceOf(ConfigurationException.class) + .hasMessageContainingAll("Datasource 'ds-1' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.\"ds-1\".active'" + + " to 'true' and configure datasource 'ds-1'", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } + + @Test + public void vendorPool() { + MySQLPool pool = Arc.container().instance(MySQLPool.class, + new ReactiveDataSource.ReactiveDataSourceLiteral("ds-1")).get(); + + // The bean is always available to be injected during static init + // since we don't know whether the datasource will be active at runtime. + // So the bean cannot be null. + assertThat(pool).isNotNull(); + // However, any attempt to use it at runtime will fail. + assertThatThrownBy(() -> pool.getConnection()) + .isInstanceOf(RuntimeException.class) + .cause() + .isInstanceOf(ConfigurationException.class) + .hasMessageContainingAll("Datasource 'ds-1' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.\"ds-1\".active'" + + " to 'true' and configure datasource 'ds-1'", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } + + @Test + public void mutinyVendorPool() { + io.vertx.mutiny.mysqlclient.MySQLPool pool = Arc.container().instance(io.vertx.mutiny.mysqlclient.MySQLPool.class, + new ReactiveDataSource.ReactiveDataSourceLiteral("ds-1")).get(); + + // The bean is always available to be injected during static init + // since we don't know whether the datasource will be active at runtime. + // So the bean cannot be null. + assertThat(pool).isNotNull(); + // However, any attempt to use it at runtime will fail. + assertThatThrownBy(() -> pool.getConnection()) + .isInstanceOf(RuntimeException.class) + .cause() + .isInstanceOf(ConfigurationException.class) + .hasMessageContainingAll("Datasource 'ds-1' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.\"ds-1\".active'" + + " to 'true' and configure datasource 'ds-1'", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } + + @Test + public void injectedBean() { + assertThatThrownBy(() -> myBean.usePool()) + .isInstanceOf(RuntimeException.class) + .cause() + .isInstanceOf(ConfigurationException.class) + .hasMessageContainingAll("Datasource 'ds-1' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.\"ds-1\".active'" + + " to 'true' and configure datasource 'ds-1'", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } + + @ApplicationScoped + public static class MyBean { + @Inject + @ReactiveDataSource("ds-1") + Pool pool; + + public CompletionStage usePool() { + return pool.getConnection().toCompletionStage(); + } + } +} diff --git a/extensions/reactive-mysql-client/deployment/src/test/java/io/quarkus/reactive/mysql/client/DataSourceHealthCheckConfigActiveFalseTest.java b/extensions/reactive-mysql-client/deployment/src/test/java/io/quarkus/reactive/mysql/client/DataSourceHealthCheckConfigActiveFalseTest.java new file mode 100644 index 0000000000000..40f9830df3787 --- /dev/null +++ b/extensions/reactive-mysql-client/deployment/src/test/java/io/quarkus/reactive/mysql/client/DataSourceHealthCheckConfigActiveFalseTest.java @@ -0,0 +1,30 @@ +package io.quarkus.reactive.mysql.client; + +import org.hamcrest.CoreMatchers; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.test.QuarkusUnitTest; +import io.restassured.RestAssured; + +public class DataSourceHealthCheckConfigActiveFalseTest { + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .withEmptyApplication() + .withConfigurationResource("application-default-datasource.properties") + .overrideConfigKey("quarkus.datasource.health.enabled", "true") + // this data source is broken, but will be deactivated, + // so the overall check should pass + .overrideConfigKey("quarkus.datasource.brokenDS.db-kind", "mysql") + .overrideConfigKey("quarkus.datasource.brokenDS.reactive.url", "BROKEN") + .overrideConfigKey("quarkus.datasource.brokenDS.active", "false"); + + @Test + public void testDataSourceHealthCheckExclusion() { + RestAssured.when().get("/q/health/ready") + .then() + .body("status", CoreMatchers.equalTo("UP")); + } + +} diff --git a/extensions/reactive-oracle-client/deployment/src/test/java/io/quarkus/reactive/oracle/client/ConfigActiveFalseDefaultDatasourceTest.java b/extensions/reactive-oracle-client/deployment/src/test/java/io/quarkus/reactive/oracle/client/ConfigActiveFalseDefaultDatasourceTest.java new file mode 100644 index 0000000000000..d71964ecbf67d --- /dev/null +++ b/extensions/reactive-oracle-client/deployment/src/test/java/io/quarkus/reactive/oracle/client/ConfigActiveFalseDefaultDatasourceTest.java @@ -0,0 +1,133 @@ +package io.quarkus.reactive.oracle.client; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.util.concurrent.CompletionStage; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.arc.Arc; +import io.quarkus.runtime.configuration.ConfigurationException; +import io.quarkus.test.QuarkusUnitTest; +import io.vertx.oracleclient.OraclePool; +import io.vertx.sqlclient.Pool; + +public class ConfigActiveFalseDefaultDatasourceTest { + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .overrideConfigKey("quarkus.datasource.active", "false"); + + @Inject + MyBean myBean; + + @Test + public void pool() { + Pool pool = Arc.container().instance(Pool.class).get(); + + // The bean is always available to be injected during static init + // since we don't know whether the datasource will be active at runtime. + // So the bean cannot be null. + assertThat(pool).isNotNull(); + // However, any attempt to use it at runtime will fail. + assertThatThrownBy(() -> pool.getConnection()) + .isInstanceOf(RuntimeException.class) + .cause() + .isInstanceOf(ConfigurationException.class) + .hasMessageContainingAll("Datasource '' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.active'" + + " to 'true' and configure datasource ''", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } + + @Test + public void mutinyPool() { + io.vertx.mutiny.sqlclient.Pool pool = Arc.container().instance(io.vertx.mutiny.sqlclient.Pool.class).get(); + + // The bean is always available to be injected during static init + // since we don't know whether the datasource will be active at runtime. + // So the bean cannot be null. + assertThat(pool).isNotNull(); + // However, any attempt to use it at runtime will fail. + assertThatThrownBy(() -> pool.getConnection()) + .isInstanceOf(RuntimeException.class) + .cause() + .isInstanceOf(ConfigurationException.class) + .hasMessageContainingAll("Datasource '' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.active'" + + " to 'true' and configure datasource ''", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } + + @Test + public void vendorPool() { + OraclePool pool = Arc.container().instance(OraclePool.class).get(); + + // The bean is always available to be injected during static init + // since we don't know whether the datasource will be active at runtime. + // So the bean cannot be null. + assertThat(pool).isNotNull(); + // However, any attempt to use it at runtime will fail. + assertThatThrownBy(() -> pool.getConnection()) + .isInstanceOf(RuntimeException.class) + .cause() + .isInstanceOf(ConfigurationException.class) + .hasMessageContainingAll("Datasource '' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.active'" + + " to 'true' and configure datasource ''", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } + + @Test + public void mutinyVendorPool() { + io.vertx.mutiny.oracleclient.OraclePool pool = Arc.container().instance(io.vertx.mutiny.oracleclient.OraclePool.class) + .get(); + + // The bean is always available to be injected during static init + // since we don't know whether the datasource will be active at runtime. + // So the bean cannot be null. + assertThat(pool).isNotNull(); + // However, any attempt to use it at runtime will fail. + assertThatThrownBy(() -> pool.getConnection()) + .isInstanceOf(RuntimeException.class) + .cause() + .isInstanceOf(ConfigurationException.class) + .hasMessageContainingAll("Datasource '' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.active'" + + " to 'true' and configure datasource ''", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } + + @Test + public void injectedBean() { + // However, any attempt to use it at runtime will fail. + assertThatThrownBy(() -> myBean.usePool()) + .isInstanceOf(RuntimeException.class) + .cause() + .isInstanceOf(ConfigurationException.class) + .hasMessageContainingAll("Datasource '' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.active'" + + " to 'true' and configure datasource ''", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } + + @ApplicationScoped + public static class MyBean { + @Inject + Pool pool; + + public CompletionStage usePool() { + return pool.getConnection().toCompletionStage(); + } + } +} diff --git a/extensions/reactive-oracle-client/deployment/src/test/java/io/quarkus/reactive/oracle/client/ConfigActiveFalseNamedDatasourceTest.java b/extensions/reactive-oracle-client/deployment/src/test/java/io/quarkus/reactive/oracle/client/ConfigActiveFalseNamedDatasourceTest.java new file mode 100644 index 0000000000000..546c7179e563a --- /dev/null +++ b/extensions/reactive-oracle-client/deployment/src/test/java/io/quarkus/reactive/oracle/client/ConfigActiveFalseNamedDatasourceTest.java @@ -0,0 +1,140 @@ +package io.quarkus.reactive.oracle.client; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.util.concurrent.CompletionStage; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.arc.Arc; +import io.quarkus.reactive.datasource.ReactiveDataSource; +import io.quarkus.runtime.configuration.ConfigurationException; +import io.quarkus.test.QuarkusUnitTest; +import io.vertx.oracleclient.OraclePool; +import io.vertx.sqlclient.Pool; + +public class ConfigActiveFalseNamedDatasourceTest { + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .overrideConfigKey("quarkus.datasource.ds-1.active", "false") + // We need at least one build-time property for the datasource, + // otherwise it's considered unconfigured at build time... + .overrideConfigKey("quarkus.datasource.ds-1.db-kind", "oracle"); + + @Inject + MyBean myBean; + + @Test + public void pool() { + Pool pool = Arc.container().instance(Pool.class, + new ReactiveDataSource.ReactiveDataSourceLiteral("ds-1")).get(); + + // The bean is always available to be injected during static init + // since we don't know whether the datasource will be active at runtime. + // So the bean cannot be null. + assertThat(pool).isNotNull(); + // However, any attempt to use it at runtime will fail. + assertThatThrownBy(() -> pool.getConnection()) + .isInstanceOf(RuntimeException.class) + .cause() + .isInstanceOf(ConfigurationException.class) + .hasMessageContainingAll("Datasource 'ds-1' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.\"ds-1\".active'" + + " to 'true' and configure datasource 'ds-1'", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } + + @Test + public void mutinyPool() { + io.vertx.mutiny.sqlclient.Pool pool = Arc.container().instance(io.vertx.mutiny.sqlclient.Pool.class, + new ReactiveDataSource.ReactiveDataSourceLiteral("ds-1")).get(); + + // The bean is always available to be injected during static init + // since we don't know whether the datasource will be active at runtime. + // So the bean cannot be null. + assertThat(pool).isNotNull(); + // However, any attempt to use it at runtime will fail. + assertThatThrownBy(() -> pool.getConnection()) + .isInstanceOf(RuntimeException.class) + .cause() + .isInstanceOf(ConfigurationException.class) + .hasMessageContainingAll("Datasource 'ds-1' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.\"ds-1\".active'" + + " to 'true' and configure datasource 'ds-1'", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } + + @Test + public void vendorPool() { + OraclePool pool = Arc.container().instance(OraclePool.class, + new ReactiveDataSource.ReactiveDataSourceLiteral("ds-1")).get(); + + // The bean is always available to be injected during static init + // since we don't know whether the datasource will be active at runtime. + // So the bean cannot be null. + assertThat(pool).isNotNull(); + // However, any attempt to use it at runtime will fail. + assertThatThrownBy(() -> pool.getConnection()) + .isInstanceOf(RuntimeException.class) + .cause() + .isInstanceOf(ConfigurationException.class) + .hasMessageContainingAll("Datasource 'ds-1' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.\"ds-1\".active'" + + " to 'true' and configure datasource 'ds-1'", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } + + @Test + public void mutinyVendorPool() { + io.vertx.mutiny.oracleclient.OraclePool pool = Arc.container().instance(io.vertx.mutiny.oracleclient.OraclePool.class, + new ReactiveDataSource.ReactiveDataSourceLiteral("ds-1")).get(); + + // The bean is always available to be injected during static init + // since we don't know whether the datasource will be active at runtime. + // So the bean cannot be null. + assertThat(pool).isNotNull(); + // However, any attempt to use it at runtime will fail. + assertThatThrownBy(() -> pool.getConnection()) + .isInstanceOf(RuntimeException.class) + .cause() + .isInstanceOf(ConfigurationException.class) + .hasMessageContainingAll("Datasource 'ds-1' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.\"ds-1\".active'" + + " to 'true' and configure datasource 'ds-1'", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } + + @Test + public void injectedBean() { + assertThatThrownBy(() -> myBean.usePool()) + .isInstanceOf(RuntimeException.class) + .cause() + .isInstanceOf(ConfigurationException.class) + .hasMessageContainingAll("Datasource 'ds-1' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.\"ds-1\".active'" + + " to 'true' and configure datasource 'ds-1'", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } + + @ApplicationScoped + public static class MyBean { + @Inject + @ReactiveDataSource("ds-1") + Pool pool; + + public CompletionStage usePool() { + return pool.getConnection().toCompletionStage(); + } + } +} diff --git a/extensions/reactive-oracle-client/deployment/src/test/java/io/quarkus/reactive/oracle/client/DataSourceHealthCheckConfigActiveFalseTest.java b/extensions/reactive-oracle-client/deployment/src/test/java/io/quarkus/reactive/oracle/client/DataSourceHealthCheckConfigActiveFalseTest.java new file mode 100644 index 0000000000000..7791728100211 --- /dev/null +++ b/extensions/reactive-oracle-client/deployment/src/test/java/io/quarkus/reactive/oracle/client/DataSourceHealthCheckConfigActiveFalseTest.java @@ -0,0 +1,30 @@ +package io.quarkus.reactive.oracle.client; + +import org.hamcrest.CoreMatchers; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.test.QuarkusUnitTest; +import io.restassured.RestAssured; + +public class DataSourceHealthCheckConfigActiveFalseTest { + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .withEmptyApplication() + .withConfigurationResource("application-default-datasource.properties") + .overrideConfigKey("quarkus.datasource.health.enabled", "true") + // this data source is broken, but will be deactivated, + // so the overall check should pass + .overrideConfigKey("quarkus.datasource.brokenDS.db-kind", "oracle") + .overrideConfigKey("quarkus.datasource.brokenDS.reactive.url", "BROKEN") + .overrideConfigKey("quarkus.datasource.brokenDS.active", "false"); + + @Test + public void testDataSourceHealthCheckExclusion() { + RestAssured.when().get("/q/health/ready") + .then() + .body("status", CoreMatchers.equalTo("UP")); + } + +} diff --git a/extensions/reactive-pg-client/deployment/src/test/java/io/quarkus/reactive/pg/client/ConfigActiveFalseDefaultDatasourceTest.java b/extensions/reactive-pg-client/deployment/src/test/java/io/quarkus/reactive/pg/client/ConfigActiveFalseDefaultDatasourceTest.java new file mode 100644 index 0000000000000..8dbb1f8094e8a --- /dev/null +++ b/extensions/reactive-pg-client/deployment/src/test/java/io/quarkus/reactive/pg/client/ConfigActiveFalseDefaultDatasourceTest.java @@ -0,0 +1,133 @@ +package io.quarkus.reactive.pg.client; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.util.concurrent.CompletionStage; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.arc.Arc; +import io.quarkus.runtime.configuration.ConfigurationException; +import io.quarkus.test.QuarkusUnitTest; +import io.vertx.pgclient.PgPool; +import io.vertx.sqlclient.Pool; + +public class ConfigActiveFalseDefaultDatasourceTest { + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .overrideConfigKey("quarkus.datasource.active", "false"); + + @Inject + MyBean myBean; + + @Test + public void pool() { + Pool pool = Arc.container().instance(Pool.class).get(); + + // The bean is always available to be injected during static init + // since we don't know whether the datasource will be active at runtime. + // So the bean cannot be null. + assertThat(pool).isNotNull(); + // However, any attempt to use it at runtime will fail. + assertThatThrownBy(() -> pool.getConnection()) + .isInstanceOf(RuntimeException.class) + .cause() + .isInstanceOf(ConfigurationException.class) + .hasMessageContainingAll("Datasource '' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.active'" + + " to 'true' and configure datasource ''", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } + + @Test + public void mutinyPool() { + io.vertx.mutiny.sqlclient.Pool pool = Arc.container().instance(io.vertx.mutiny.sqlclient.Pool.class).get(); + + // The bean is always available to be injected during static init + // since we don't know whether the datasource will be active at runtime. + // So the bean cannot be null. + assertThat(pool).isNotNull(); + // However, any attempt to use it at runtime will fail. + assertThatThrownBy(() -> pool.getConnection()) + .isInstanceOf(RuntimeException.class) + .cause() + .isInstanceOf(ConfigurationException.class) + .hasMessageContainingAll("Datasource '' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.active'" + + " to 'true' and configure datasource ''", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } + + @Test + public void vendorPool() { + PgPool pool = Arc.container().instance(PgPool.class).get(); + + // The bean is always available to be injected during static init + // since we don't know whether the datasource will be active at runtime. + // So the bean cannot be null. + assertThat(pool).isNotNull(); + // However, any attempt to use it at runtime will fail. + assertThatThrownBy(() -> pool.getConnection()) + .isInstanceOf(RuntimeException.class) + .cause() + .isInstanceOf(ConfigurationException.class) + .hasMessageContainingAll("Datasource '' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.active'" + + " to 'true' and configure datasource ''", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } + + @Test + public void mutinyVendorPool() { + io.vertx.mutiny.pgclient.PgPool pool = Arc.container().instance(io.vertx.mutiny.pgclient.PgPool.class) + .get(); + + // The bean is always available to be injected during static init + // since we don't know whether the datasource will be active at runtime. + // So the bean cannot be null. + assertThat(pool).isNotNull(); + // However, any attempt to use it at runtime will fail. + assertThatThrownBy(() -> pool.getConnection()) + .isInstanceOf(RuntimeException.class) + .cause() + .isInstanceOf(ConfigurationException.class) + .hasMessageContainingAll("Datasource '' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.active'" + + " to 'true' and configure datasource ''", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } + + @Test + public void injectedBean() { + // However, any attempt to use it at runtime will fail. + assertThatThrownBy(() -> myBean.usePool()) + .isInstanceOf(RuntimeException.class) + .cause() + .isInstanceOf(ConfigurationException.class) + .hasMessageContainingAll("Datasource '' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.active'" + + " to 'true' and configure datasource ''", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } + + @ApplicationScoped + public static class MyBean { + @Inject + Pool pool; + + public CompletionStage usePool() { + return pool.getConnection().toCompletionStage(); + } + } +} diff --git a/extensions/reactive-pg-client/deployment/src/test/java/io/quarkus/reactive/pg/client/ConfigActiveFalseNamedDatasourceTest.java b/extensions/reactive-pg-client/deployment/src/test/java/io/quarkus/reactive/pg/client/ConfigActiveFalseNamedDatasourceTest.java new file mode 100644 index 0000000000000..e40b129e6cabd --- /dev/null +++ b/extensions/reactive-pg-client/deployment/src/test/java/io/quarkus/reactive/pg/client/ConfigActiveFalseNamedDatasourceTest.java @@ -0,0 +1,140 @@ +package io.quarkus.reactive.pg.client; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.util.concurrent.CompletionStage; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.arc.Arc; +import io.quarkus.reactive.datasource.ReactiveDataSource; +import io.quarkus.runtime.configuration.ConfigurationException; +import io.quarkus.test.QuarkusUnitTest; +import io.vertx.pgclient.PgPool; +import io.vertx.sqlclient.Pool; + +public class ConfigActiveFalseNamedDatasourceTest { + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .overrideConfigKey("quarkus.datasource.ds-1.active", "false") + // We need at least one build-time property for the datasource, + // otherwise it's considered unconfigured at build time... + .overrideConfigKey("quarkus.datasource.ds-1.db-kind", "postgresql"); + + @Inject + MyBean myBean; + + @Test + public void pool() { + Pool pool = Arc.container().instance(Pool.class, + new ReactiveDataSource.ReactiveDataSourceLiteral("ds-1")).get(); + + // The bean is always available to be injected during static init + // since we don't know whether the datasource will be active at runtime. + // So the bean cannot be null. + assertThat(pool).isNotNull(); + // However, any attempt to use it at runtime will fail. + assertThatThrownBy(() -> pool.getConnection()) + .isInstanceOf(RuntimeException.class) + .cause() + .isInstanceOf(ConfigurationException.class) + .hasMessageContainingAll("Datasource 'ds-1' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.\"ds-1\".active'" + + " to 'true' and configure datasource 'ds-1'", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } + + @Test + public void mutinyPool() { + io.vertx.mutiny.sqlclient.Pool pool = Arc.container().instance(io.vertx.mutiny.sqlclient.Pool.class, + new ReactiveDataSource.ReactiveDataSourceLiteral("ds-1")).get(); + + // The bean is always available to be injected during static init + // since we don't know whether the datasource will be active at runtime. + // So the bean cannot be null. + assertThat(pool).isNotNull(); + // However, any attempt to use it at runtime will fail. + assertThatThrownBy(() -> pool.getConnection()) + .isInstanceOf(RuntimeException.class) + .cause() + .isInstanceOf(ConfigurationException.class) + .hasMessageContainingAll("Datasource 'ds-1' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.\"ds-1\".active'" + + " to 'true' and configure datasource 'ds-1'", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } + + @Test + public void vendorPool() { + PgPool pool = Arc.container().instance(PgPool.class, + new ReactiveDataSource.ReactiveDataSourceLiteral("ds-1")).get(); + + // The bean is always available to be injected during static init + // since we don't know whether the datasource will be active at runtime. + // So the bean cannot be null. + assertThat(pool).isNotNull(); + // However, any attempt to use it at runtime will fail. + assertThatThrownBy(() -> pool.getConnection()) + .isInstanceOf(RuntimeException.class) + .cause() + .isInstanceOf(ConfigurationException.class) + .hasMessageContainingAll("Datasource 'ds-1' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.\"ds-1\".active'" + + " to 'true' and configure datasource 'ds-1'", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } + + @Test + public void mutinyVendorPool() { + io.vertx.mutiny.pgclient.PgPool pool = Arc.container().instance(io.vertx.mutiny.pgclient.PgPool.class, + new ReactiveDataSource.ReactiveDataSourceLiteral("ds-1")).get(); + + // The bean is always available to be injected during static init + // since we don't know whether the datasource will be active at runtime. + // So the bean cannot be null. + assertThat(pool).isNotNull(); + // However, any attempt to use it at runtime will fail. + assertThatThrownBy(() -> pool.getConnection()) + .isInstanceOf(RuntimeException.class) + .cause() + .isInstanceOf(ConfigurationException.class) + .hasMessageContainingAll("Datasource 'ds-1' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.\"ds-1\".active'" + + " to 'true' and configure datasource 'ds-1'", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } + + @Test + public void injectedBean() { + assertThatThrownBy(() -> myBean.usePool()) + .isInstanceOf(RuntimeException.class) + .cause() + .isInstanceOf(ConfigurationException.class) + .hasMessageContainingAll("Datasource 'ds-1' was deactivated through configuration properties.", + "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", + "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.\"ds-1\".active'" + + " to 'true' and configure datasource 'ds-1'", + "Refer to https://quarkus.io/guides/datasource for guidance."); + } + + @ApplicationScoped + public static class MyBean { + @Inject + @ReactiveDataSource("ds-1") + Pool pool; + + public CompletionStage usePool() { + return pool.getConnection().toCompletionStage(); + } + } +} diff --git a/extensions/reactive-pg-client/deployment/src/test/java/io/quarkus/reactive/pg/client/DataSourceHealthCheckConfigActiveFalseTest.java b/extensions/reactive-pg-client/deployment/src/test/java/io/quarkus/reactive/pg/client/DataSourceHealthCheckConfigActiveFalseTest.java new file mode 100644 index 0000000000000..1b9c7d61639ff --- /dev/null +++ b/extensions/reactive-pg-client/deployment/src/test/java/io/quarkus/reactive/pg/client/DataSourceHealthCheckConfigActiveFalseTest.java @@ -0,0 +1,30 @@ +package io.quarkus.reactive.pg.client; + +import org.hamcrest.CoreMatchers; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.test.QuarkusUnitTest; +import io.restassured.RestAssured; + +public class DataSourceHealthCheckConfigActiveFalseTest { + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .withEmptyApplication() + .withConfigurationResource("application-default-datasource.properties") + .overrideConfigKey("quarkus.datasource.health.enabled", "true") + // this data source is broken, but will be deactivated, + // so the overall check should pass + .overrideConfigKey("quarkus.datasource.brokenDS.db-kind", "postgresql") + .overrideConfigKey("quarkus.datasource.brokenDS.reactive.url", "BROKEN") + .overrideConfigKey("quarkus.datasource.brokenDS.active", "false"); + + @Test + public void testDataSourceHealthCheckExclusion() { + RestAssured.when().get("/q/health/ready") + .then() + .body("status", CoreMatchers.equalTo("UP")); + } + +}