首页 > 解决方案 > 进行 JMS 调用时出现 Spring Boot JTA 异常

问题描述

我在运行 Pro Spring 5 书中的示例时遇到 JTA 异常(12. Using Spring Remote, boot-jms project)。这是整个代码(不包括导入)。它只有一个文件Application.java:

@SpringBootApplication
public class Application {

    private static Logger logger = LoggerFactory.getLogger(Application.class);

    @Bean
    public JmsListenerContainerFactory<DefaultMessageListenerContainer> connectionFactory(ConnectionFactory connectionFactory,
            DefaultJmsListenerContainerFactoryConfigurer configurer) {
        DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
        // This provides all boot's default to this factory, including the message converter
        configurer.configure(factory, connectionFactory);
        // You could still override some of Boot's default if necessary.
        return factory;
    }

    public static void main(String... args) throws Exception {
        ConfigurableApplicationContext ctx = SpringApplication.run(Application.class, args);
        JmsTemplate jmsTemplate = ctx.getBean(JmsTemplate.class);
        jmsTemplate.setDeliveryDelay(5000L);
        for (int i = 0; i < 10; ++i) {
            logger.info(">>> Sending: Test message: " + i);
            jmsTemplate.convertAndSend("prospring5", "Test message: " + i);
        }

        System.in.read();
        ctx.close();
    }

    @JmsListener(destination = "prospring5", containerFactory = "connectionFactory")
    public void onMessage(Message message) {
        TextMessage textMessage = (TextMessage) message;

        try {
            logger.info(">>> Received: " + textMessage.getText());
        } catch (JMSException ex) {
            logger.error("JMS error", ex);
        }
    }
}

首先,我收到以下错误:

org.springframework.jms.core.JmsTemplate.doSend(JmsTemplate.java:628) 处 org.springframework.jms 处的线程“主”java.lang.AbstractMethodError 中的异常:com.atomikos.jms.AtomikosJmsMessageProducerProxy.setDeliveryDelay(J)V .core.JmsTemplate.doSend(JmsTemplate.java:608) at org.springframework.jms.core.JmsTemplate.lambda$send$3(JmsTemplate.java:586) at org.springframework.jms.core.JmsTemplate.execute(JmsTemplate. java:504) 在 org.springframework.jms.core.JmsTemplate.send(JmsTemplate.java:584) 在 org.springframework.jms.core.JmsTemplate.convertAndSend(JmsTemplate.java:661) 在 com.apress.prospring5.ch12 .Application.main(Application.java:54)

然后我注释掉“jmsTemplate.setDeliveryDelay(5000L);”。所以我能够通过这个错误,但最终会出现 JTA 异常。

线程“主”org.springframework.jms.UncategorizedJmsException中的异常:JMS处理期间发生未分类异常;嵌套异常是 com.atomikos.jms.AtomikosTransactionRequiredJMSException:您使用的 JMS 会话需要调用线程的 JTA 事务上下文,但没有找到。请更正您的代码以执行以下操作之一:

  1. 如果您希望 JMS 操作服从 JTA 提交/回滚,则启动 JTA 事务,或者
  2. 增加 AtomikosConnectionFactoryBean 的 maxPoolSize 以避免等待连接时事务超时,或者
  3. 创建一个非事务会话并自己进行会话确认,或者
  4. 将 localTransactionMode 设置为 true 以便启用连接级提交/回滚。在 org.springframework.jms.support.JmsUtils.convertJmsAccessException(JmsUtils.java:311) 在 org.springframework.jms.support.JmsAccessor.convertJmsAccessException(JmsAccessor.java:185) 在 org.springframework.jms.core.JmsTemplate.execute (JmsTemplate.java:507) 在 org.springframework.jms.core.JmsTemplate.send(JmsTemplate.java:584) 在 org.springframework.jms.core.JmsTemplate.convertAndSend(JmsTemplate.java:661) 在 com.apress。 prospring5.ch12.Application.main(Application.java:54) 原因:com.atomikos.jms.AtomikosTransactionRequiredJMSException:您使用的 JMS 会话需要调用线程的 JTA 事务上下文,但没有找到。请更正您的代码以执行以下操作之一:
  5. 如果您希望 JMS 操作服从 JTA 提交/回滚,则启动 JTA 事务,或者
  6. 增加 AtomikosConnectionFactoryBean 的 maxPoolSize 以避免等待连接时事务超时,或者
  7. 创建一个非事务会话并自己进行会话确认,或者
  8. 将 localTransactionMode 设置为 true 以便启用连接级提交/回滚。在 com.atomikos.jms.AtomikosTransactionRequiredJMSException.throwAtomikosTransactionRequiredJMSException(AtomikosTransactionRequiredJMSException.java:23) 在 com.atomikos.jms.ConsumerProducerSupport.enlist(ConsumerProducerSupport.java:90) 在 com.atomikos.jms.AtomikosJmsMessageProducerProxy.send(AtomikosJmsMessageProducerProxy.java:34 ) 在 org.springframework.jms.core.JmsTemplate 的 org.springframework.jms.core.JmsTemplate.doSend(JmsTemplate.java:608) 的 org.springframework.jms.core.JmsTemplate.doSend(JmsTemplate.java:634)。 org.springframework.jms.core.JmsTemplate.execute(JmsTemplate.java:504) 上的 lambda$send$3(JmsTemplate.java:586) ... 还有 3 个

我的项目包括spring-boot-starter-artemis和spring-boot-starter-jta-atomikos的依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-artemis</artifactId>
    <version>2.0.6.RELEASE</version>            
</dependency>
<dependency>
    <groupId>org.apache.activemq</groupId>
    <artifactId>artemis-jms-server</artifactId>
    <version>2.4.0</version>            
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jta-atomikos</artifactId>
    <version>2.0.6.RELEASE</version>            
</dependency>
<dependency>
    <groupId>com.atomikos</groupId>
    <artifactId>transactions-hibernate4</artifactId>
    <version>4.0.4</version>            
</dependency>

该错误消息似乎表明缺少事务,因此我@Transactional在侦听器和 jmsTemplate 处添加了注释,但同样的问题仍然存在。

标签: spring-bootspring-jmsjtaactivemq-artemisatomikos

解决方案


问题似乎是我在依赖项中包含了 spring-boot-starter-jta-atomikos 和 transactions-hibernate4。一旦我删除了这两个依赖项,代码就可以工作了。这个例子的目的不是做事务,而是演示 spring-boot 在 artemis 上做 JMS。但是由于我在类路径中有这两个与事务相关的文件,所以 spring-boot 会自动要求事务。


推荐阅读