首页 > 解决方案 > 使用 TransactionInterceptor 抛出 java.lang.IllegalStateException:无法将反应式事务应用于非反应式返回类型:void

问题描述

我的代码是:

  @Bean(R2DBC_TRANSACTION_INTERCEPTOR)
    public TransactionInterceptor R2DBCTransactionInterceptor(ReactiveTransactionManager reactiveTransactionManager) {
        return new TransactionInterceptorBuilder(true)
                .transactionManager(reactiveTransactionManager)
                .isolation(Isolation.READ_COMMITTED)
                .propagation(Propagation.REQUIRES_NEW)
                .build();
    }

    @ServiceActivator(inputChannel = "create invoice",
            adviceChain = {IntegrationConfiguration.R2DBC_TRANSACTION_INTERCEPTOR})
    public Mono<Invoice> createInvoice(Invoice invoice) {
        return invoiceRepository.save(invoice);
    }

我得到了一个异常 java.lang.IllegalStateException: Cannot apply reactive transaction to non-reactive return type: void at org.springframework.transaction.interceptor.TransactionAspectSupport.lambda$invokeWithinTransaction$0(TransactionAspectSupport.java:348) ~[spring-tx- 5.2.8.RELEASE.jar:5.2.8.RELEASE]

即使在消息传递过程中没有异常,createInvoice 方法也会以该异常调用。

有针对这种情况提供的演示吗?我的配置错了吗?

标签: spring-integration

解决方案


new TransactionInterceptorBuilder(true)

查看它的 JavaDocs:

* When the {@code handleMessageAdvice} option is in use, this builder produces
* {@link TransactionHandleMessageAdvice} instance.

然后我们去提到的TransactionHandleMessageAdvice

 * When this {@link org.aopalliance.aop.Advice}
 * is used from the {@code request-handler-advice-chain}, it is applied
 * to the {@link org.springframework.messaging.MessageHandler#handleMessage}
 * (not to the
 * {@link org.springframework.integration.handler.AbstractReplyProducingMessageHandler.RequestHandler#handleRequestMessage}),
 * therefore the entire downstream process is wrapped to the transaction.

现在,如果我们看一下MessageHandler#handleMessage,我们会看到:

void handleMessage(Message<?> message) throws MessagingException;

因此,这就是该事务拦截器被注入的地方,这就是您的解决方案由于void来自handleMessage().

你真的需要考虑你是否确实需要一个事务(尤其是反应性的)来处理整个子流程@ServiceActivator......

我的意思是你可能只是new TransactionInterceptorBuilder()可以让你的@ServiceActivator事务处理并且已经使用那个反应式 TX 管理器,因为你确实返回了一个Mono.


推荐阅读