亲爱的,我想根据Kafka主题收到的消息来更新我的域实体。我在Kafka中使用Quarkus最新消息和Smallrye反应消息。 Pub-sub模型对我来说很好用,但是在使用者方法下,我无法使用entityManager或HibernatePanache更新我的实体。
每当我尝试在使用者消息中使用EntityManager代码时,都会引发异常并以静默方式处理异常。这是我的消费者代码:
@Transactional
@Incoming("new-payment")
public CompletionStage<Void> updateTotalBuyers(String paymentEvent) {
return CompletableFuture.runAsync(() -> {
PaymentEvent event = jsonb.fromJson(paymentEvent, PaymentEvent.class);
TypedQuery<Book> query = em.createQuery("SELECT b FROM Book b where b.isbn=:isbn", Book.class);
query.setParameter("isbn", event.getIsbn());
Book book = query.getSingleResult();
book.setTotalBuyers(book.getTotalBuyers() + 1);
em.merge(book);
});
}
如果有人有适合我的问题的代码段,那就太好了。另外,如何打印该静默异常以进行进一步调试?
更新: 我用try / catch块包围了代码,并抛出了以下异常:
javax.enterprise.context.ContextNotActiveException:接口javax.enterprise.context.RequestScoped 在io.quarkus.hibernate.orm.runtime.RequestScopedEntityManagerHolder_ClientProxy.arc $ delegate(RequestScopedEntityManagerHolder_ClientProxy.zig:83) 在io.quarkus.hibernate.orm.runtime.RequestScopedEntityManagerHolder_ClientProxy.getOrCreateEntityManager(RequestScopedEntityManagerHolder_ClientProxy.zig:191) 在io.quarkus.hibernate.orm.runtime.entitymanager.TransactionScopedEntityManager.getEntityManager(TransactionScopedEntityManager.java:78) 在io.quarkus.hibernate.orm.runtime.entitymanager.TransactionScopedEntityManager.createQuery(TransactionScopedEntityManager.java:317) 在io.quarkus.hibernate.orm.runtime.entitymanager.ForwardingEntityManager.createQuery(ForwardingEntityManager.java:142) 在io.quarkus.hibernate.orm.panache.runtime.JpaOperations.find(JpaOperations.java:208) 在io.quarkus.hibernate.orm.panache.runtime.JpaOperations.find(JpaOperations.java:200) 在org.ibra.ebs.book.model.Book.find(Book.java) 在org.ibra.ebs.book.service.BookService.lambda $ updateTotalBuyers $ 0(BookService.java:106) 在java.util.concurrent.CompletableFuture $ AsyncRun.run(CompletableFuture.java:1626) 在java.util.concurrent.CompletableFuture $ AsyncRun.exec(CompletableFuture.java:1618) 在java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289) 在java.util.concurrent.ForkJoinPool $ WorkQueue.runTask(ForkJoinPool.java:1056) 在java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692) 在java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
我在类和方法上都添加了注释@ActivateRequestContext
,但是没有运气。
致谢。
答案 0 :(得分:2)
最后它起作用了:),是的,答案是关于上下文传播的,这就是我所做的:
@Transactional
@Incoming("new-payment")
public CompletionStage<?> updateTotalBuyers(Message<String> paymentEvent) {
//TODO: move to CDI producer
ManagedExecutor executor = ManagedExecutor.builder()
.maxAsync(5)
.propagated(ThreadContext.CDI,
ThreadContext.TRANSACTION)
.build();
//TODO: move to CDI producer
ThreadContext threadContext = ThreadContext.builder()
.propagated(ThreadContext.CDI,
ThreadContext.TRANSACTION)
.build();
return executor.runAsync(threadContext.contextualRunnable(() -> {
try {
log.info("Into update total buyers");
PaymentEvent event = jsonb.fromJson(paymentEvent.getPayload(), PaymentEvent.class);
Book book = Book.find("isbn", event.getIsbn()).singleResult();
book.totalBuyers++;
book.persist();
log.info("Total books {}", book.totalBuyers);
} catch(Exception e) {
log.error("Something wrong happened !!!", e);
} finally {
paymentEvent.ack();
}
}));
}
我将尝试使其更加标准化。
答案 1 :(得分:2)
我在使用Quarkus +一个线程执行程序来收集AWS SQS消息时遇到了类似的问题。
private final ExecutorService scheduler = Executors.newSingleThreadExecutor();
scheduler.submit(/*MyRunnable*/)
@Inject
ManagedExecutor managedExecutor;
managedExecutor.submit(/*MyRunnable*/);
在特定情况下,您可以通过注入 ManagedExecutor 来替换以下代码。
ManagedExecutor executor = ManagedExecutor.builder()
.maxAsync(5)
.propagated(ThreadContext.CDI,
ThreadContext.TRANSACTION)
.build();
//TODO: move to CDI producer
ThreadContext threadContext = ThreadContext.builder()
.propagated(ThreadContext.CDI,
ThreadContext.TRANSACTION)
.build();
答案 2 :(得分:0)
在类上添加@ApplicationScoped
和@ActivateRequestContext
这两个注释,并在@Transactional
方法上添加updateTotalBuyers
注释。
干杯!