quarkusio / quarkus

Quarkus: Supersonic Subatomic Java.
https://quarkus.io
Apache License 2.0
13.81k stars 2.68k forks source link

@ConsumeEvent() method has no request context #6059

Closed willr3 closed 4 years ago

willr3 commented 4 years ago

Describe the bug I have an @Entity that extends PanacheEntityBase with String, Integer, Boolean member variable and when I try and call Entity.find("attr = ?1",value) from a method with @ConsumeEvent(blocking=true) I get the following excpetion:

javax.enterprise.context.ContextNotActiveException: interface javax.enterprise.context.RequestScoped
    at io.quarkus.hibernate.orm.runtime.RequestScopedEntityManagerHolder_ClientProxy.arc$delegate(RequestScopedEntityManagerHolder_ClientProxy.zig:83)
    at io.quarkus.hibernate.orm.runtime.RequestScopedEntityManagerHolder_ClientProxy.getOrCreateEntityManager(RequestScopedEntityManagerHolder_ClientProxy.zig:191)
    at io.quarkus.hibernate.orm.runtime.entitymanager.TransactionScopedEntityManager.getEntityManager(TransactionScopedEntityManager.java:78)
    at io.quarkus.hibernate.orm.runtime.entitymanager.TransactionScopedEntityManager.createQuery(TransactionScopedEntityManager.java:317)
    at io.quarkus.hibernate.orm.runtime.entitymanager.ForwardingEntityManager.createQuery(ForwardingEntityManager.java:142)
    at io.quarkus.hibernate.orm.panache.runtime.JpaOperations.find(JpaOperations.java:208)
    at io.quarkus.hibernate.orm.panache.runtime.JpaOperations.find(JpaOperations.java:200)
    at io.hyperfoil.tools.repo.entity.json.Hook.find(Hook.java)
    at io.hyperfoil.tools.repo.api.HookService.getEventHooks(HookService.java:142)
    at io.hyperfoil.tools.repo.api.HookService.tellHooks(HookService.java:70)
    at io.hyperfoil.tools.repo.api.HookService.newTest(HookService.java:104)
    at io.hyperfoil.tools.repo.api.HookService_ClientProxy.newTest(HookService_ClientProxy.zig:99)
    at io.hyperfoil.tools.repo.api.HookService_VertxInvoker_newTest_f2dc88ef28a38d97b8721d82bde1c1424d137260$$function$$140.handle(HookService_VertxInvoker_newTest_f2dc88ef28a38d97b8721d82bde1c1424d137260$$function$$140.zig:67)
    at io.vertx.core.impl.ContextImpl.lambda$executeBlocking$2(ContextImpl.java:316)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
    at java.base/java.lang.Thread.run(Thread.java:834)

(Describe the problem clearly and concisely.)

Expected behavior I expect I would be able to use the Panache find() from anywhere I could access the Entity class

Actual behavior Calling find() throws an exception

To Reproduce Steps to reproduce the behavior:

  1. Create an @Entity
  2. Create a method with @ConsumeEvent(blocking = true) that calls Entity.find(...)
  3. Send a message to the event consumer

Environment (please complete the following information):

Additional context Adding @Transactional to the event comsumer method is a workaround

FroMage commented 4 years ago

We should think about adding a request context for those methods @cescoffier @mkouba, no?

mkouba commented 4 years ago

Hm, I think so - it's a kind of "request". Currently, you can add the javax.enterprise.context.control.ActivateRequestContext annotation as a workaround.

Adding @Transactional to the event comsumer method is a workaround

This is a little bit odd. @Transactional itself should not activate the context unless I'm mistaken...

mkouba commented 4 years ago

For the record: the @Transactional fixes the problem because if a transaction is active the RequestScopedEntityManagerHolder is not used and so the request context does not have to active. See https://github.com/quarkusio/quarkus/blob/master/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/entitymanager/TransactionScopedEntityManager.java#L52-L72.

mkouba commented 4 years ago

@cescoffier I wonder 1) if we should only activate the request context for @ConsumeEvent(blocking=true) 2) if we should do the same for reactive routes?

cescoffier commented 4 years ago

For reactive routes yes, For @ConsumeEvent, it may not come from an HTTP request, what would be in the request scope in this case?

mkouba commented 4 years ago

For @ConsumeEvent, it may not come from an HTTP request, what would be in the request scope in this case?

The request context is not tied to an HTTP request. The "request" could be anything. In this particular case, the request may represent an event notification. Even in the CDI spec, the request context is activated during @PostConstruct callback of a bean and during notification of an asynchronous observer method (no HTTP request).

And it would be empty by default - it's only used if a @RequestScoped bean is used during notification.

cescoffier commented 4 years ago

ok, then we can enable the RequestScope on ConsumeEvent