Skip to content

Commit

Permalink
Hibernate reactive - remove the Mutiny.Session bean
Browse files Browse the repository at this point in the history
- resolves #30717
  • Loading branch information
mkouba committed Feb 13, 2023
1 parent ffb4f3f commit bcb99d5
Show file tree
Hide file tree
Showing 12 changed files with 93 additions and 237 deletions.
8 changes: 1 addition & 7 deletions docs/src/main/asciidoc/hibernate-reactive.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -208,13 +208,7 @@ Mutiny.SessionFactory sessionFactory;

This will inject the `Mutiny.SessionFactory` of the default persistence unit.

You can also inject an instance of `Uni<Mutiny.Session>` using the exact same mechanism:

[source,java]
----
@Inject
Uni<Mutiny.Session> session;
----
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.

[[testing]]
=== Testing
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@
import io.quarkus.hibernate.reactive.runtime.HibernateReactive;
import io.quarkus.hibernate.reactive.runtime.HibernateReactiveRecorder;
import io.quarkus.hibernate.reactive.runtime.ReactiveSessionFactoryProducer;
import io.quarkus.hibernate.reactive.runtime.ReactiveSessionProducer;
import io.quarkus.reactive.datasource.deployment.VertxPoolBuildItem;
import io.quarkus.runtime.LaunchMode;
import io.quarkus.runtime.configuration.ConfigurationException;
Expand All @@ -87,13 +86,12 @@ void registerBeans(BuildProducer<AdditionalBeanBuildItem> additionalBeans, Combi
List<PersistenceUnitDescriptorBuildItem> descriptors,
JpaModelBuildItem jpaModel) {
if (descriptors.size() == 1) {
// Only register those beans if their EMF dependency is also available, so use the same guard as the ORM extension
// Only register the bean if their EMF dependency is also available, so use the same guard as the ORM extension
additionalBeans.produce(new AdditionalBeanBuildItem(ReactiveSessionFactoryProducer.class));
additionalBeans.produce(new AdditionalBeanBuildItem(ReactiveSessionProducer.class));
} else {
LOG.warnf(
"Skipping registration of %s and %s because exactly one persistence unit is required for their registration",
ReactiveSessionFactoryProducer.class.getSimpleName(), ReactiveSessionProducer.class.getSimpleName());
"Skipping registration of %s bean because exactly one persistence unit is required for their registration",
ReactiveSessionFactoryProducer.class.getSimpleName());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

import java.util.concurrent.CompletableFuture;
import java.util.function.Supplier;

import jakarta.persistence.EntityManagerFactory;

import org.hibernate.SessionFactory;
Expand All @@ -15,8 +12,6 @@

import io.quarkus.arc.Arc;
import io.quarkus.test.QuarkusUnitTest;
import io.vertx.core.Vertx;
import io.vertx.core.impl.ContextInternal;

public class ConfigActiveFalseAndEntityTest {

Expand Down Expand Up @@ -74,48 +69,4 @@ public void mutinySessionFactory() {
"Hibernate Reactive was deactivated through configuration properties");
}

@Test
public void mutinySession() {
Mutiny.Session session = Arc.container().instance(Mutiny.Session.class).get();

// The bean is always available to be injected during static init
// since we don't know whether Hibernate Reactive will be active at runtime.
// So the bean cannot be null.
assertThat(session).isNotNull();
// However, any attempt to use it at runtime will fail.
assertThatThrownBy(() -> runInVertxAndJoin(() -> {
try {
Arc.container().requestContext().activate();
return session.find(MyEntity.class, 0L);
} finally {
Arc.container().requestContext().deactivate();
}
}))
.cause()
.isInstanceOf(IllegalStateException.class)
.hasMessageContainingAll("Cannot retrieve the Mutiny.SessionFactory for persistence unit default-reactive",
"Hibernate Reactive was deactivated through configuration properties");
}

private <T> T runInVertxAndJoin(Supplier<T> action) {
CompletableFuture<T> future = new CompletableFuture<>();
runInVertx(() -> {
try {
future.complete(action.get());
} catch (Throwable t) {
future.completeExceptionally(t);
}
});
return future.join();
}

// Copied from org.hibernate.reactive.context.impl.VertxContext.execute.
// Unfortunately we can't use that class here, so we need to duplicate a few lines of code.
// This seems to be the simplest way to run code in Vertx from a test...
private void runInVertx(Runnable action) {
final io.vertx.core.Context newContext = Arc.container().instance(Vertx.class).get().getOrCreateContext();
ContextInternal newContextInternal = (ContextInternal) newContext;
final ContextInternal duplicate = newContextInternal.duplicate();
duplicate.runOnContext(ignored -> action.run());
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
public class HibernateReactiveDB2AlternativeTestEndpoint {

@Inject
Mutiny.Session mutinySession;
Mutiny.SessionFactory sessionFactory;

// Injecting a Vert.x Pool is not required, it us only used to
// independently validate the contents of the database for the test
Expand All @@ -28,14 +28,13 @@ public class HibernateReactiveDB2AlternativeTestEndpoint {
public Uni<GuineaPig> reactiveFindMutiny() {
final GuineaPig expectedPig = new GuineaPig(5, "Aloi");
return populateDB()
.chain(() -> mutinySession.find(GuineaPig.class, expectedPig.getId()));
.chain(() -> sessionFactory.withSession(s -> s.find(GuineaPig.class, expectedPig.getId())));
}

@GET
@Path("/reactivePersist")
public Uni<String> reactivePersist() {
return mutinySession.persist(new GuineaPig(10, "Tulip"))
.chain(() -> mutinySession.flush())
return sessionFactory.withTransaction(s -> s.persist(new GuineaPig(10, "Tulip")))
.chain(() -> selectNameFromId(10));
}

Expand All @@ -50,9 +49,8 @@ public Uni<String> reactiveRemoveTransientEntity() {
}
return name;
})
.chain(() -> mutinySession.merge(new GuineaPig(5, "Aloi")))
.chain(aloi -> mutinySession.remove(aloi))
.chain(() -> mutinySession.flush())
.chain(() -> sessionFactory
.withTransaction(s -> s.merge(new GuineaPig(5, "Aloi")).chain(s::remove)))
.chain(() -> selectNameFromId(5))
.onItem().ifNotNull().transform(result -> result)
.onItem().ifNull().continueWith("OK");
Expand All @@ -62,9 +60,8 @@ public Uni<String> reactiveRemoveTransientEntity() {
@Path("/reactiveRemoveManagedEntity")
public Uni<String> reactiveRemoveManagedEntity() {
return populateDB()
.chain(() -> mutinySession.find(GuineaPig.class, 5))
.chain(aloi -> mutinySession.remove(aloi))
.chain(() -> mutinySession.flush())
.chain(() -> sessionFactory
.withTransaction(s -> s.find(GuineaPig.class, 5).chain(s::remove)))
.chain(() -> selectNameFromId(5))
.onItem().ifNotNull().transform(result -> result)
.onItem().ifNull().continueWith("OK");
Expand All @@ -75,15 +72,13 @@ public Uni<String> reactiveRemoveManagedEntity() {
public Uni<String> reactiveUpdate() {
final String NEW_NAME = "Tina";
return populateDB()
.chain(() -> mutinySession.find(GuineaPig.class, 5))
.onItem().transform(pig -> {
if (NEW_NAME.equals(pig.getName())) {
throw new AssertionError("Pig already had name " + NEW_NAME);
}
pig.setName(NEW_NAME);
return pig;
})
.chain(() -> mutinySession.flush())
.chain(() -> sessionFactory.withTransaction(s -> s.find(GuineaPig.class, 5)
.invoke(pig -> {
if (NEW_NAME.equals(pig.getName())) {
throw new AssertionError("Pig already had name " + NEW_NAME);
}
pig.setName(NEW_NAME);
})))
.chain(() -> selectNameFromId(5));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
public class HibernateReactiveDB2TestEndpoint {

@Inject
Mutiny.Session mutinySession;
Mutiny.SessionFactory sessionFactory;

// Injecting a Vert.x Pool is not required, it us only used to
// independently validate the contents of the database for the test
Expand All @@ -28,14 +28,13 @@ public class HibernateReactiveDB2TestEndpoint {
public Uni<GuineaPig> reactiveFindMutiny() {
final GuineaPig expectedPig = new GuineaPig(5, "Aloi");
return populateDB()
.chain(() -> mutinySession.find(GuineaPig.class, expectedPig.getId()));
.chain(() -> sessionFactory.withSession(s -> s.find(GuineaPig.class, expectedPig.getId())));
}

@GET
@Path("/reactivePersist")
public Uni<String> reactivePersist() {
return mutinySession.persist(new GuineaPig(10, "Tulip"))
.chain(() -> mutinySession.flush())
return sessionFactory.withTransaction(s -> s.persist(new GuineaPig(10, "Tulip")))
.chain(() -> selectNameFromId(10));
}

Expand All @@ -50,9 +49,8 @@ public Uni<String> reactiveRemoveTransientEntity() {
}
return name;
})
.chain(() -> mutinySession.merge(new GuineaPig(5, "Aloi")))
.chain(aloi -> mutinySession.remove(aloi))
.chain(() -> mutinySession.flush())
.chain(() -> sessionFactory
.withTransaction(s -> s.merge(new GuineaPig(5, "Aloi")).chain(s::remove)))
.chain(() -> selectNameFromId(5))
.onItem().ifNotNull().transform(result -> result)
.onItem().ifNull().continueWith("OK");
Expand All @@ -62,9 +60,8 @@ public Uni<String> reactiveRemoveTransientEntity() {
@Path("/reactiveRemoveManagedEntity")
public Uni<String> reactiveRemoveManagedEntity() {
return populateDB()
.chain(() -> mutinySession.find(GuineaPig.class, 5))
.chain(aloi -> mutinySession.remove(aloi))
.chain(() -> mutinySession.flush())
.chain(() -> sessionFactory
.withTransaction(s -> s.find(GuineaPig.class, 5).chain(s::remove)))
.chain(() -> selectNameFromId(5))
.onItem().ifNotNull().transform(result -> result)
.onItem().ifNull().continueWith("OK");
Expand All @@ -75,15 +72,13 @@ public Uni<String> reactiveRemoveManagedEntity() {
public Uni<String> reactiveUpdate() {
final String NEW_NAME = "Tina";
return populateDB()
.chain(() -> mutinySession.find(GuineaPig.class, 5))
.map(pig -> {
if (NEW_NAME.equals(pig.getName())) {
throw new AssertionError("Pig already had name " + NEW_NAME);
}
pig.setName(NEW_NAME);
return pig;
})
.chain(() -> mutinySession.flush())
.chain(() -> sessionFactory.withTransaction(s -> s.find(GuineaPig.class, 5)
.invoke(pig -> {
if (NEW_NAME.equals(pig.getName())) {
throw new AssertionError("Pig already had name " + NEW_NAME);
}
pig.setName(NEW_NAME);
})))
.chain(() -> selectNameFromId(5));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
public class HibernateReactiveMySQLAlternativeTestEndpoint {

@Inject
Mutiny.Session mutinySession;
Mutiny.SessionFactory sessionFactory;

// Injecting a Vert.x Pool is not required, it us only used to
// independently validate the contents of the database for the test
Expand All @@ -28,14 +28,13 @@ public class HibernateReactiveMySQLAlternativeTestEndpoint {
public Uni<GuineaPig> reactiveFindMutiny() {
final GuineaPig expectedPig = new GuineaPig(5, "Aloi");
return populateDB()
.chain(() -> mutinySession.find(GuineaPig.class, expectedPig.getId()));
.chain(() -> sessionFactory.withSession(s -> s.find(GuineaPig.class, expectedPig.getId())));
}

@GET
@Path("/reactivePersist")
public Uni<String> reactivePersist() {
return mutinySession.persist(new GuineaPig(10, "Tulip"))
.chain(() -> mutinySession.flush())
return sessionFactory.withTransaction(s -> s.persist(new GuineaPig(10, "Tulip")))
.chain(() -> selectNameFromId(10));
}

Expand All @@ -50,9 +49,8 @@ public Uni<String> reactiveRemoveTransientEntity() {
}
return name;
})
.chain(() -> mutinySession.merge(new GuineaPig(5, "Aloi")))
.chain(aloi -> mutinySession.remove(aloi))
.chain(() -> mutinySession.flush())
.chain(() -> sessionFactory.withTransaction(
s -> s.merge(new GuineaPig(5, "Aloi")).chain(s::remove)))
.chain(() -> selectNameFromId(5))
.onItem().ifNotNull().transform(result -> result)
.onItem().ifNull().continueWith("OK");
Expand All @@ -62,9 +60,8 @@ public Uni<String> reactiveRemoveTransientEntity() {
@Path("/reactiveRemoveManagedEntity")
public Uni<String> reactiveRemoveManagedEntity() {
return populateDB()
.chain(() -> mutinySession.find(GuineaPig.class, 5))
.chain(aloi -> mutinySession.remove(aloi))
.chain(() -> mutinySession.flush())
.chain(() -> sessionFactory
.withTransaction(s -> s.find(GuineaPig.class, 5).chain(s::remove)))
.chain(() -> selectNameFromId(5))
.onItem().ifNotNull().transform(result -> result)
.onItem().ifNull().continueWith("OK");
Expand All @@ -75,15 +72,13 @@ public Uni<String> reactiveRemoveManagedEntity() {
public Uni<String> reactiveUpdate() {
final String NEW_NAME = "Tina";
return populateDB()
.chain(() -> mutinySession.find(GuineaPig.class, 5))
.map(pig -> {
if (NEW_NAME.equals(pig.getName())) {
throw new AssertionError("Pig already had name " + NEW_NAME);
}
pig.setName(NEW_NAME);
return pig;
})
.chain(() -> mutinySession.flush())
.chain(() -> sessionFactory.withTransaction(s -> s.find(GuineaPig.class, 5)
.invoke(pig -> {
if (NEW_NAME.equals(pig.getName())) {
throw new AssertionError("Pig already had name " + NEW_NAME);
}
pig.setName(NEW_NAME);
})))
.chain(() -> selectNameFromId(5));
}

Expand Down
Loading

0 comments on commit bcb99d5

Please sign in to comment.