I'm getting JTA exception while running an example from the Pro Spring 5 book (12. Using Spring Remote, boot-jms project). Here is the entirety of the code (exclude the imports). It only has one file 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);
}
}
}
First, I got the following error:
Exception in thread "main" java.lang.AbstractMethodError: com.atomikos.jms.AtomikosJmsMessageProducerProxy.setDeliveryDelay(J)V at org.springframework.jms.core.JmsTemplate.doSend(JmsTemplate.java:628) at org.springframework.jms.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) at org.springframework.jms.core.JmsTemplate.send(JmsTemplate.java:584) at org.springframework.jms.core.JmsTemplate.convertAndSend(JmsTemplate.java:661) at com.apress.prospring5.ch12.Application.main(Application.java:54)
Then I commented out "jmsTemplate.setDeliveryDelay(5000L);". So I was able to get pass this error but only end up with the JTA exception.
Exception in thread "main" org.springframework.jms.UncategorizedJmsException: Uncategorized exception occurred during JMS processing; nested exception is com.atomikos.jms.AtomikosTransactionRequiredJMSException: The JMS session you are using requires a JTA transaction context for the calling thread and none was found. Please correct your code to do one of the following:
- start a JTA transaction if you want your JMS operations to be subject to JTA commit/rollback, or
- increase the maxPoolSize of the AtomikosConnectionFactoryBean to avoid transaction timeout while waiting for a connection, or
- create a non-transacted session and do session acknowledgment yourself, or
- set localTransactionMode to true so connection-level commit/rollback are enabled. at org.springframework.jms.support.JmsUtils.convertJmsAccessException(JmsUtils.java:311) at org.springframework.jms.support.JmsAccessor.convertJmsAccessException(JmsAccessor.java:185) at org.springframework.jms.core.JmsTemplate.execute(JmsTemplate.java:507) at org.springframework.jms.core.JmsTemplate.send(JmsTemplate.java:584) at org.springframework.jms.core.JmsTemplate.convertAndSend(JmsTemplate.java:661) at com.apress.prospring5.ch12.Application.main(Application.java:54) Caused by: com.atomikos.jms.AtomikosTransactionRequiredJMSException: The JMS session you are using requires a JTA transaction context for the calling thread and none was found. Please correct your code to do one of the following:
- start a JTA transaction if you want your JMS operations to be subject to JTA commit/rollback, or
- increase the maxPoolSize of the AtomikosConnectionFactoryBean to avoid transaction timeout while waiting for a connection, or
- create a non-transacted session and do session acknowledgment yourself, or
- set localTransactionMode to true so connection-level commit/rollback are enabled. at com.atomikos.jms.AtomikosTransactionRequiredJMSException.throwAtomikosTransactionRequiredJMSException(AtomikosTransactionRequiredJMSException.java:23) at com.atomikos.jms.ConsumerProducerSupport.enlist(ConsumerProducerSupport.java:90) at com.atomikos.jms.AtomikosJmsMessageProducerProxy.send(AtomikosJmsMessageProducerProxy.java:34) at org.springframework.jms.core.JmsTemplate.doSend(JmsTemplate.java:634) at org.springframework.jms.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) ... 3 more
My project includes the dependency of spring-boot-starter-artemis and 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>
The error message seems suggesting the Transaction is missing, so I had added @Transactional
annotation at the listener and jmsTemplate, but the same problem still persists.