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 deleted file mode 100644 index d37178ddf1d9a..0000000000000 --- a/extensions/agroal/deployment/src/test/java/io/quarkus/agroal/test/MultipleDataSourcesAsAlternativesWithActiveDS1Test.java +++ /dev/null @@ -1,95 +0,0 @@ -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.arc.Arc; -import io.quarkus.arc.InjectableInstance; -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; - - @Test - public void testExplicitDatasourceBeanUsable() { - doTestDatasource(explicitDatasourceBean); - } - - @Test - public void testCustomIndirectDatasourceBeanUsable() { - doTestDatasource(customIndirectDatasourceBean); - } - - @Test - public void testInactiveDatasourceBeanUnusable() { - assertThatThrownBy(() -> Arc.container().select(AgroalDataSource.class, new DataSource.DataSourceLiteral("ds-2")).get() - .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 - @DataSource("ds-1") - InjectableInstance dataSource1Bean; - - @Inject - @DataSource("ds-2") - InjectableInstance dataSource2Bean; - - @Produces - @ApplicationScoped - public AgroalDataSource dataSource() { - if (dataSource1Bean.getHandle().getBean().isActive()) { - return dataSource1Bean.get(); - } else if (dataSource2Bean.getHandle().getBean().isActive()) { - return dataSource2Bean.get(); - } else { - throw new RuntimeException("No active datasource!"); - } - } - } -} 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 deleted file mode 100644 index 497953764b919..0000000000000 --- a/extensions/agroal/deployment/src/test/java/io/quarkus/agroal/test/MultipleDataSourcesAsAlternativesWithActiveDS2Test.java +++ /dev/null @@ -1,95 +0,0 @@ -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.arc.Arc; -import io.quarkus.arc.InjectableInstance; -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; - - @Test - public void testExplicitDatasourceBeanUsable() { - doTestDatasource(explicitDatasourceBean); - } - - @Test - public void testCustomIndirectDatasourceBeanUsable() { - doTestDatasource(customIndirectDatasourceBean); - } - - @Test - public void testInactiveDatasourceBeanUnusable() { - assertThatThrownBy(() -> Arc.container().select(AgroalDataSource.class, new DataSource.DataSourceLiteral("ds-1")).get() - .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 - @DataSource("ds-1") - InjectableInstance dataSource1Bean; - - @Inject - @DataSource("ds-2") - InjectableInstance dataSource2Bean; - - @Produces - @ApplicationScoped - public AgroalDataSource dataSource() { - if (dataSource1Bean.getHandle().getBean().isActive()) { - return dataSource1Bean.get(); - } else if (dataSource2Bean.getHandle().getBean().isActive()) { - return dataSource2Bean.get(); - } else { - throw new RuntimeException("No active datasource!"); - } - } - } -} diff --git a/extensions/agroal/deployment/src/test/java/io/quarkus/agroal/test/MultipleDataSourcesAsAlternativesWithBeanProducerTest.java b/extensions/agroal/deployment/src/test/java/io/quarkus/agroal/test/MultipleDataSourcesAsAlternativesWithBeanProducerTest.java new file mode 100644 index 0000000000000..6c36a5e2a55bb --- /dev/null +++ b/extensions/agroal/deployment/src/test/java/io/quarkus/agroal/test/MultipleDataSourcesAsAlternativesWithBeanProducerTest.java @@ -0,0 +1,119 @@ +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.arc.Arc; +import io.quarkus.arc.InjectableInstance; +import io.quarkus.test.QuarkusUnitTest; + +/** + * Tests a use case where multiple datasources are defined at build time, + * but only one is used at runtime, + * and a custom bean producer is used to retrieve the active datasource. + *

+ * 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. + */ +public abstract class MultipleDataSourcesAsAlternativesWithBeanProducerTest { + + public static class Ds1ActiveTest extends MultipleDataSourcesAsAlternativesWithBeanProducerTest { + @RegisterExtension + static QuarkusUnitTest runner = runner("ds-1"); + + public Ds1ActiveTest() { + super("ds-1", "ds-2"); + } + } + + public static class Ds2ActiveTest extends MultipleDataSourcesAsAlternativesWithBeanProducerTest { + @RegisterExtension + static QuarkusUnitTest runner = runner("ds-2"); + + public Ds2ActiveTest() { + super("ds-2", "ds-1"); + } + } + + static QuarkusUnitTest runner(String activeDsName) { + return 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 the active datasource + .overrideRuntimeConfigKey("quarkus.datasource." + activeDsName + ".active", "true") + .overrideRuntimeConfigKey("quarkus.datasource." + activeDsName + ".jdbc.url", "jdbc:h2:mem:testds1"); + } + + private final String activeDsName; + private final String inactiveDsName; + + protected MultipleDataSourcesAsAlternativesWithBeanProducerTest(String activeDsName, String inactiveDsName) { + this.activeDsName = activeDsName; + this.inactiveDsName = inactiveDsName; + } + + @Inject + AgroalDataSource customIndirectDatasourceBean; + + @Test + public void testExplicitDatasourceBeanUsable() { + doTestDatasource(Arc.container().select(AgroalDataSource.class, new DataSource.DataSourceLiteral(activeDsName)).get()); + } + + @Test + public void testCustomIndirectDatasourceBeanUsable() { + doTestDatasource(customIndirectDatasourceBean); + } + + @Test + public void testInactiveDatasourceBeanUnusable() { + assertThatThrownBy( + () -> Arc.container().select(AgroalDataSource.class, new DataSource.DataSourceLiteral(inactiveDsName)).get() + .getConnection()) + .hasMessageContaining( + "Datasource '" + inactiveDsName + "' was deactivated through configuration properties."); + } + + private static void doTestDatasource(AgroalDataSource dataSource) { + assertThatCode(() -> { + try (var connection = dataSource.getConnection()) { + } + }) + .doesNotThrowAnyException(); + } + + private static class MyProducer { + @Inject + @DataSource("ds-1") + InjectableInstance dataSource1Bean; + + @Inject + @DataSource("ds-2") + InjectableInstance dataSource2Bean; + + @Produces + @ApplicationScoped + public AgroalDataSource dataSource() { + if (dataSource1Bean.getHandle().getBean().isActive()) { + return dataSource1Bean.get(); + } else if (dataSource2Bean.getHandle().getBean().isActive()) { + return dataSource2Bean.get(); + } else { + throw new RuntimeException("No active datasource!"); + } + } + } +} 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 deleted file mode 100644 index 00e75da7c2723..0000000000000 --- a/extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/config/datasource/MultiplePUAsAlternativesWithActivePU1Test.java +++ /dev/null @@ -1,128 +0,0 @@ -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.agroal.api.AgroalDataSource; -import io.quarkus.agroal.DataSource; -import io.quarkus.arc.InjectableInstance; -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 - @DataSource("ds-1") - InjectableInstance dataSource1Bean; - - @Inject - @DataSource("ds-2") - InjectableInstance dataSource2Bean; - - @Inject - @PersistenceUnit("pu-1") - Session pu1SessionBean; - - @Inject - @PersistenceUnit("pu-2") - Session pu2SessionBean; - - @Produces - @ApplicationScoped - public Session session() { - if (dataSource1Bean.getHandle().getBean().isActive()) { - return pu1SessionBean; - } else if (dataSource2Bean.getHandle().getBean().isActive()) { - return pu2SessionBean; - } else { - throw new RuntimeException("No active datasource!"); - } - } - } -} 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 deleted file mode 100644 index 333354627274e..0000000000000 --- a/extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/config/datasource/MultiplePUAsAlternativesWithActivePU2Test.java +++ /dev/null @@ -1,128 +0,0 @@ -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.agroal.api.AgroalDataSource; -import io.quarkus.agroal.DataSource; -import io.quarkus.arc.InjectableInstance; -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 - @DataSource("ds-1") - InjectableInstance dataSource1Bean; - - @Inject - @DataSource("ds-2") - InjectableInstance dataSource2Bean; - - @Inject - @PersistenceUnit("pu-1") - Session pu1SessionBean; - - @Inject - @PersistenceUnit("pu-2") - Session pu2SessionBean; - - @Produces - @ApplicationScoped - public Session session() { - if (dataSource1Bean.getHandle().getBean().isActive()) { - return pu1SessionBean; - } else if (dataSource2Bean.getHandle().getBean().isActive()) { - return pu2SessionBean; - } else { - throw new RuntimeException("No active datasource!"); - } - } - } -} diff --git a/extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/config/datasource/MultiplePUAsAlternativesWithBeanProducerTest.java b/extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/config/datasource/MultiplePUAsAlternativesWithBeanProducerTest.java new file mode 100644 index 0000000000000..b35d5c80c987b --- /dev/null +++ b/extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/config/datasource/MultiplePUAsAlternativesWithBeanProducerTest.java @@ -0,0 +1,150 @@ +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.agroal.api.AgroalDataSource; +import io.quarkus.agroal.DataSource; +import io.quarkus.arc.Arc; +import io.quarkus.arc.InjectableInstance; +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. + */ +public class MultiplePUAsAlternativesWithBeanProducerTest { + + public static class Pu1ActiveTest extends MultiplePUAsAlternativesWithBeanProducerTest { + @RegisterExtension + static QuarkusUnitTest runner = runner("pu-1", "ds-1"); + + public Pu1ActiveTest() { + super("pu-1", "pu-2"); + } + } + + public static class Pu2ActiveTest extends MultiplePUAsAlternativesWithBeanProducerTest { + @RegisterExtension + static QuarkusUnitTest runner = runner("pu-2", "ds-2"); + + public Pu2ActiveTest() { + super("pu-2", "pu-1"); + } + } + + static QuarkusUnitTest runner(String activePuName, String activeDsName) { + return 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 the active PU / datasource + .overrideRuntimeConfigKey("quarkus.hibernate-orm." + activePuName + ".active", "true") + .overrideRuntimeConfigKey("quarkus.datasource." + activeDsName + ".active", "true") + .overrideRuntimeConfigKey("quarkus.datasource." + activeDsName + ".jdbc.url", "jdbc:h2:mem:testds1"); + } + + private final String activePuName; + private final String inactivePuName; + + public MultiplePUAsAlternativesWithBeanProducerTest(String activePuName, String inactivePuName) { + this.activePuName = activePuName; + this.inactivePuName = inactivePuName; + } + + @Inject + Session customIndirectSessionBean; + + @Test + public void testExplicitSessionBeanUsable() { + doTestPersistRetrieve(Arc.container() + .select(Session.class, new PersistenceUnit.PersistenceUnitLiteral(activePuName)).get(), + 1L); + } + + @Test + public void testCustomIndirectSessionBeanUsable() { + doTestPersistRetrieve(customIndirectSessionBean, 2L); + } + + @Test + public void testInactiveSessionBeanUnusable() { + QuarkusTransaction.requiringNew().run(() -> { + assertThatThrownBy(() -> Arc.container() + .select(Session.class, new PersistenceUnit.PersistenceUnitLiteral(inactivePuName)).get() + .find(MyEntity.class, 3L)) + .hasMessageContainingAll( + "Cannot retrieve the EntityManagerFactory/SessionFactory for persistence unit " + inactivePuName, + "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 + @DataSource("ds-1") + InjectableInstance dataSource1Bean; + + @Inject + @DataSource("ds-2") + InjectableInstance dataSource2Bean; + + @Inject + @PersistenceUnit("pu-1") + Session pu1SessionBean; + + @Inject + @PersistenceUnit("pu-2") + Session pu2SessionBean; + + @Produces + @ApplicationScoped + public Session session() { + if (dataSource1Bean.getHandle().getBean().isActive()) { + return pu1SessionBean; + } else if (dataSource2Bean.getHandle().getBean().isActive()) { + return pu2SessionBean; + } else { + throw new RuntimeException("No active datasource!"); + } + } + } +}