Skip to content

Commit a106bc4

Browse files
committed
Document and test that persistence units can be deactivated with Hibernate Reactive too
1 parent d97291e commit a106bc4

File tree

3 files changed

+171
-0
lines changed

3 files changed

+171
-0
lines changed

docs/src/main/asciidoc/hibernate-reactive.adoc

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,24 @@ This will inject the `Mutiny.SessionFactory` of the default persistence unit.
280280

281281
NOTE: Prior to Quarkus 3.0 it was also possible to inject a `@RequestScoped` bean for `Mutiny.Session`. However, the lifecycle of a reactive session does not fit the lifecycle of the CDI request context. Therefore, this bean is removed in Quarkus 3.0.
282282

283+
[[persistence-unit-active]]
284+
=== Activate/deactivate persistence units
285+
286+
When a persistence unit is configured at build time, the persistence unit is active by default.
287+
Quarkus starts the corresponding Hibernate Reactive `SessionFactory` when the application starts.
288+
289+
To deactivate a persistence unit at runtime, see xref:hibernate-orm.adoc#persistence-unit-active[the corresponding section of the Hibernate ORM guide].
290+
291+
[NOTE]
292+
====
293+
If you decide to follow the example from the Hibernate ORM guide to declare a custom CDI bean for the active persistence unit,
294+
but you use Hibernate Reactive,
295+
make sure to work with the `Mutiny.SessionFactory` type instead of `Session`:
296+
this is one way Hibernate Reactive's API entrypoint differs from Hibernate ORM's.
297+
298+
See <<hr-cdi-integration>> for details.
299+
====
300+
283301
[[flyway]]
284302
== Automatically transitioning to Flyway to Manage Schemas
285303

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
package io.quarkus.hibernate.reactive.config.datasource;
2+
3+
import static org.assertj.core.api.Assertions.assertThat;
4+
5+
import jakarta.enterprise.context.ApplicationScoped;
6+
import jakarta.enterprise.inject.Produces;
7+
import jakarta.inject.Inject;
8+
9+
import org.hibernate.reactive.mutiny.Mutiny;
10+
import org.junit.jupiter.api.Test;
11+
import org.junit.jupiter.api.extension.RegisterExtension;
12+
13+
import io.quarkus.arc.Arc;
14+
import io.quarkus.arc.InjectableInstance;
15+
import io.quarkus.hibernate.orm.PersistenceUnit;
16+
import io.quarkus.hibernate.reactive.config.MyEntity;
17+
import io.quarkus.test.QuarkusUnitTest;
18+
import io.quarkus.test.vertx.RunOnVertxContext;
19+
import io.quarkus.test.vertx.UniAsserter;
20+
21+
/**
22+
* Tests a use case where multiple PU/datasources are defined at build time,
23+
* but only one is used at runtime.
24+
* <p>
25+
* This is mostly useful when each datasource has a distinct db-kind, but in theory that shouldn't matter,
26+
* so we use the h2 db-kind everywhere here to keep test dependencies simpler.
27+
*/
28+
public abstract class MultiplePUAsAlternativesWithBeanProducerTest {
29+
30+
public static class Pu1ActiveTest extends MultiplePUAsAlternativesWithBeanProducerTest {
31+
@RegisterExtension
32+
static QuarkusUnitTest runner = runner("pu-1", "ds-1");
33+
34+
public Pu1ActiveTest() {
35+
super("pu-1", "pu-2", "ds-2");
36+
}
37+
}
38+
39+
public static class Pu2ActiveTest extends MultiplePUAsAlternativesWithBeanProducerTest {
40+
@RegisterExtension
41+
static QuarkusUnitTest runner = runner("pu-2", "ds-2");
42+
43+
public Pu2ActiveTest() {
44+
super("pu-2", "pu-1", "ds-1");
45+
}
46+
}
47+
48+
static QuarkusUnitTest runner(String activePuName, String activeDsName) {
49+
return new QuarkusUnitTest()
50+
.withApplicationRoot((jar) -> jar
51+
.addPackage(MyEntity.class.getPackage().getName())
52+
.addClass(MyProducer.class))
53+
.withConfigurationResource("application-postgres-reactive-url-only.properties")
54+
.overrideConfigKey("quarkus.hibernate-orm.pu-1.packages", MyEntity.class.getPackageName())
55+
.overrideConfigKey("quarkus.hibernate-orm.pu-1.datasource", "ds-1")
56+
.overrideConfigKey("quarkus.hibernate-orm.pu-1.schema-management.strategy", "drop-and-create")
57+
.overrideConfigKey("quarkus.hibernate-orm.pu-1.active", "false")
58+
.overrideConfigKey("quarkus.datasource.ds-1.db-kind", "postgresql")
59+
.overrideConfigKey("quarkus.datasource.ds-1.active", "false")
60+
.overrideConfigKey("quarkus.hibernate-orm.pu-2.packages", MyEntity.class.getPackageName())
61+
.overrideConfigKey("quarkus.hibernate-orm.pu-2.datasource", "ds-2")
62+
.overrideConfigKey("quarkus.hibernate-orm.pu-2.schema-management.strategy", "drop-and-create")
63+
.overrideConfigKey("quarkus.hibernate-orm.pu-2.active", "false")
64+
.overrideConfigKey("quarkus.datasource.ds-2.db-kind", "postgresql")
65+
.overrideConfigKey("quarkus.datasource.ds-2.active", "false")
66+
// This is where we select the active PU / datasource
67+
.overrideRuntimeConfigKey("quarkus.hibernate-orm." + activePuName + ".active", "true")
68+
.overrideRuntimeConfigKey("quarkus.datasource." + activeDsName + ".active", "true")
69+
.overrideRuntimeConfigKey("quarkus.datasource." + activeDsName + ".reactive.url", "${postgres.reactive.url}");
70+
}
71+
72+
private final String activePuName;
73+
private final String inactivePuName;
74+
private final String inactiveDsName;
75+
76+
protected MultiplePUAsAlternativesWithBeanProducerTest(String activePuName, String inactivePuName, String inactiveDsName) {
77+
this.activePuName = activePuName;
78+
this.inactivePuName = inactivePuName;
79+
this.inactiveDsName = inactiveDsName;
80+
}
81+
82+
@Inject
83+
Mutiny.SessionFactory customIndirectSessionFactoryBean;
84+
85+
@Test
86+
@RunOnVertxContext
87+
public void testExplicitSessionFactoryBeanUsable(UniAsserter asserter) {
88+
doTestPersistRetrieve(asserter, Arc.container()
89+
.select(Mutiny.SessionFactory.class, new PersistenceUnit.PersistenceUnitLiteral(activePuName)).get(),
90+
1L);
91+
}
92+
93+
@Test
94+
@RunOnVertxContext
95+
public void testCustomIndirectSessionFactoryBeanUsable(UniAsserter asserter) {
96+
doTestPersistRetrieve(asserter, customIndirectSessionFactoryBean, 2L);
97+
}
98+
99+
@Test
100+
@RunOnVertxContext
101+
public void testInactiveSessionFactoryBeanUnusable(UniAsserter asserter) {
102+
asserter.assertFailedWith(() -> Arc.container()
103+
.select(Mutiny.SessionFactory.class, new PersistenceUnit.PersistenceUnitLiteral(inactivePuName)).get()
104+
.withTransaction(session -> null),
105+
failure -> assertThat(failure)
106+
.hasMessageContainingAll(
107+
"Persistence unit '" + inactivePuName + "' was deactivated through configuration properties",
108+
"To activate the persistence unit, set configuration property 'quarkus.hibernate-orm.\""
109+
+ inactivePuName
110+
+ "\".active'"
111+
+ " to 'true' and configure datasource '" + inactiveDsName + "'",
112+
"Refer to https://quarkus.io/guides/datasource for guidance."));
113+
}
114+
115+
private static void doTestPersistRetrieve(UniAsserter asserter, Mutiny.SessionFactory sessionFactory, long id) {
116+
asserter.execute(() -> sessionFactory.withTransaction(session -> {
117+
MyEntity entity = new MyEntity();
118+
entity.setId(id);
119+
entity.setName("text" + id);
120+
return session.persist(entity);
121+
}));
122+
123+
asserter.assertThat(
124+
() -> sessionFactory.withTransaction(session -> session.find(MyEntity.class, id)),
125+
entity -> assertThat(entity.getName()).isEqualTo("text" + id));
126+
}
127+
128+
private static class MyProducer {
129+
@Inject
130+
@PersistenceUnit("pu-1")
131+
InjectableInstance<Mutiny.SessionFactory> pu1SessionFactoryBean;
132+
133+
@Inject
134+
@PersistenceUnit("pu-2")
135+
InjectableInstance<Mutiny.SessionFactory> pu2SessionFactoryBean;
136+
137+
@Produces
138+
@ApplicationScoped
139+
public Mutiny.SessionFactory sessionFactory() {
140+
if (pu1SessionFactoryBean.getHandle().getBean().isActive()) {
141+
return pu1SessionFactoryBean.get();
142+
} else if (pu2SessionFactoryBean.getHandle().getBean().isActive()) {
143+
return pu2SessionFactoryBean.get();
144+
} else {
145+
throw new RuntimeException("No active persistence unit!");
146+
}
147+
}
148+
}
149+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# This is not mapped to a Quarkus configuration property directly.
2+
# It's only a way to inject Maven-provided URLs into tests,
3+
# which will refer to this property in other properties.
4+
postgres.reactive.url=${postgres.reactive.url}

0 commit comments

Comments
 (0)