2

I am using Quarkus version 2.11.1.Final. With the following `io.quarkus dependencies:

  1. smallrye-mutiny-vertx-web-client
  2. quarkus-resteasy-reactive
  3. quarkus-hibernate-reactive

In a long rest process, I am trying to persist several entities but I get the following error while doing one of the validations.

The current operation requires a safe (isolated) Vert.x sub-context, but the current context hasn't been flagged as such.
You can still use Hibernate Reactive, you just need to avoid using the methods which implicitly require accessing the stateful context, such as MutinySessionFactory#withTransaction and #withSession.

In order to persist a Collection of entities I am using:

@Inject
Mutiny.SessionFactory sf;

public Uni<List<T>> createAll(List<T> t) {
  if (LOGGER.isDebugEnabled()) {
    LOGGER.debug("#createAll(T)...  {}", t);
  }
    
  return sf.withTransaction(
      (s, t) -> s.persistAll((Object[]) t.toArray(new T[0]))
          .replaceWith(t));
}

I have already try to change the previous return to:


return sf.withStatelessTransaction((s, t) ->s.insertAll((Object[]) t.toArray(new T[0]))
    .replaceWith(t));

But I still getting the same error. Anyone knows how can I handle the vertx context inside Quarkus or anyway of persisting the entities without getting this error?

A.Casanova
  • 555
  • 4
  • 16
  • What REST library are you use? resteasy? resteasy-reactive? other? I suspect that maybe thread, used in REST layer, is not compatible with VertX threading – Sławomir Siudek Aug 18 '22 at 20:00
  • @SławomirSiudek I am using resteasy-reactive – A.Casanova Aug 19 '22 at 09:20
  • I cloned https://github.com/quarkusio/quarkus-quickstarts/tree/main/hibernate-reactive-panache-quickstart, changed from Panache to using session, and can't reproduce such issue. May you share an example how to reproduce such issue? – Sławomir Siudek Aug 21 '22 at 22:16
  • From where is `public Uni> createAll(List t) {` called? You need to be on a Vert.x context. – Clement Aug 24 '22 at 12:32
  • @Clement, Do you know if there is any documentation about how to manage the vert.x contexts within Quarkus? The service I want to develop consists of two main parts. Validate the data and persist it. If I split the service into two services (two rest calls), it works. I think that the method works since each rest call has its own vert.x context. – A.Casanova Aug 25 '22 at 14:05
  • 1
    You can find more details on https://groups.google.com/g/quarkus-dev/c/lBmQkCi_VK0. – Clement Aug 28 '22 at 08:23
  • @Clement I try `((ContextInternal) Vertx.currentContext()).duplicate()` but it is not possible to cast `Context` with `ContextInternal`. May you handle and example of how to duplicate a context and run any `Uni foo()` function on that context. – A.Casanova Sep 09 '22 at 08:17
  • Look at the VertxContext class: https://github.com/smallrye/smallrye-common/blob/main/vertx-context/src/main/java/io/smallrye/common/vertx/VertxContext.java – Clement Sep 14 '22 at 08:47

1 Answers1

0

Hibernate Reactive does NOT work even if you duplicate the context for calling sf.withTrasaction.

So the only feasible way to make it work is by manually marking the context as safe with the function io.quarkus.vertx.core.runtime.context.VertxContextSafetyToggle.setContextSafe

import io.vertx.core.Vertx;
import io.quarkus.vertx.core.runtime.context.VertxContextSafetyToggle;

...

public final class MyClass {

  @Inject
  private Vertx vertx;

  @Inject
  private RepoT repoT;

  public Uni<Void> cleanContext() {
    final io.vertx.core.Context newContext = vertx.getOrCreateContext();
    VertxContextSafetyToggle.setContextSafe(newContext, true);
    return Uni.createFrom().voidItem();
  }

  public Uni<T> create(T t) {

    return this.cleanContext()
        .flatMap( repoT.createAll(t) ) // Method which call hibernate
        ...
}

A.Casanova
  • 555
  • 4
  • 16