spring-boot - 进行 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 事务上下文,但没有找到。请更正您的代码以执行以下操作之一:
- 如果您希望 JMS 操作服从 JTA 提交/回滚,则启动 JTA 事务,或者
- 增加 AtomikosConnectionFactoryBean 的 maxPoolSize 以避免等待连接时事务超时,或者
- 创建一个非事务会话并自己进行会话确认,或者
- 将 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 事务上下文,但没有找到。请更正您的代码以执行以下操作之一:
- 如果您希望 JMS 操作服从 JTA 提交/回滚,则启动 JTA 事务,或者
- 增加 AtomikosConnectionFactoryBean 的 maxPoolSize 以避免等待连接时事务超时,或者
- 创建一个非事务会话并自己进行会话确认,或者
- 将 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-boot-starter-jta-atomikos 和 transactions-hibernate4。一旦我删除了这两个依赖项,代码就可以工作了。这个例子的目的不是做事务,而是演示 spring-boot 在 artemis 上做 JMS。但是由于我在类路径中有这两个与事务相关的文件,所以 spring-boot 会自动要求事务。
推荐阅读
- reactjs - 如何使用expo读取文本文件
- javascript - Typescript Universal 方法装饰器返回 Promise 作为值
- shell - 我看到 1>testfile.xml 2>&1 与 1>testfile.xml 2>testfile.xml 非常不同——但为什么呢?
- javascript - 我们可以使用javascript控制chrome中的打印对话框吗
- python - struct.unpack 串行流
- configuration - WO服务地址:手动细化XY而不取消服务地址?
- python - Python尝试...除了命令行
- c - 将 Ruby 解释器链接到 C 程序中
- windows - 使用 packer powershell provisioner 将 Azure 文件共享映射到服务帐户
- qt - Golang与Qt在paintEvent中的绘画问题