Spring Batch combined with Atomikos not working - spring

I’m having trouble configuring an Tomcat – Spring Batch – Atomikos combination.
I have configured the following (I’m not mentioning the JMS configuration)
Atomikos DataSource (proxy) based on
com.atomikos.tomcat.EnhancedTomcatAtomikosBeanFactory for Oracle XA datasource.
JtaTransactionManager based on
transactionManager based on com.atomikos.icatch.jta.J2eeTransactionManager
userTransaction based on
com.atomikos.icatch.jta.J2eeUserTransaction
When executing a batch job I receive the following error:
Caused by: java.lang.RuntimeException: Transaction Service Not Running?
at com.atomikos.icatch.jta.J2eeUserTransaction.checkSetup(J2eeUserTransaction.java:70)
at com.atomikos.icatch.jta.J2eeUserTransaction.getStatus(J2eeUserTransaction.java:125)
at org.springframework.transaction.jta.JtaTransactionManager.
isExistingTransaction(JtaTransactionManager.java:797)
Debugging revealed the following:
Spring Batch makes use of TaskletStep. This class uses a PlatformTransactionManager that is instantiated with a DataSourceTransactionManager? The datasource is referring to a AtomikosDataSourceBean, that seems ok.
I have several questions:
Where is this DataSourceTransactionManager coming from? I have defined a JtaTransactionManager!
I thought the AtomikosDataSourceBean acts like a proxy to connect to JtaTransactionManager. Why is Atomikos given the error “Transaction Service Not Running?”
Spring Batch: 2.1.8
Atomikos: 3.9.3

Related

Can't deploy Spring Boot (v2.6.6) project to Weblogic (v12.2.1.3) , due to javax.naming.NameNotFoundException

I'm trying to deploy a Spring boot application to weblogic, and connect the app to a Gridlink datasource using this method in #configuration to get the data source.
#Bean(name = "dataSourceA",destroyMethod = "")
public DataSource dataSourceA() throws NamingException {
JndiTemplate jndiTemplate = new JndiTemplate();
InitialContext ctx = (InitialContext) jndiTemplate.getContext();
return (DataSource) ctx.lookup(env.getProperty("DatabaseAGridLink"));
}
On Weblogic, the JNDI name for the data source is "DatabaseAGridLink", which I am hardcoding in the creation of the bean.
However, when I compile my project into a .war file and host on Weblogic- it runs into an error when searching for the data source:
javax.naming.NameNotFoundException: Unable to resolve 'DatabaseAGridLink'. Resolved ''; remaining
name 'DatabaseAGridLink'
If I restart my Weblogic, it no longer errors and the Spring Boot application can connect to the datasource on Weblogic, run db queries- functioning without issues. Problem is, this isn't a real solution- as any time the project is updated the Weblogic needs to be restarted and there are other applications running which makes this impossible irrespective of being a bad solution in the first place.
Thinking it's an issue with how the datasource is initialized in Spring boot, I have tried other methods of connection such as:
#Bean
public DataSource dataSourceA() throws Exception{
JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
return dataSourceLookup.getDataSource("DatabaseAGridLink");
}
Or different ways of specifying the JNDI name on both data source initialization beans:
ctx.lookup(env.getProperty("java:jdbc/DatabaseAGridLink"));
ctx.lookup(env.getProperty("jdbc/DatabaseAGridLink"));
ctx.lookup(env.getProperty("java:comp/jdbc/DatabaseAGridLink"));
dataSourceLookup.getDataSource("java:jdbc/DatabaseAGridLink");
etc..
These changes has had no effect, other than the name no longer being found as none of these other naming schemes are valid.
What could be causing this failure of datasource connection between Spring Boot and a Weblogic instance? (Especially considering that it succeeds after weblogic is restarted, which seems to imply that the Spring boot app is indeed looking for the correct JNDI name with it's bean and this isn't a naming problem)

TypeMismatchNamingException in spring boot with IBM MQ

I am trying to create a Spring boot project to read messages from a queue and do some processing.
I have defined the Jndi ConnectionFactory in application.properties
spring.jms.jndi-name=java:/MyConnectionFactory
On starting the application I am getting the following exception:
Caused by: org.springframework.jndi.TypeMismatchNamingException: Object of type [class com.ibm.mq.connector.outbound.ConnectionFactoryImpl] available at JNDI location [java:/MyConnectionFactory] is not assignable to [javax.jms.ConnectionFactory]
I am deploying the code on a jboss server with the given jndi.
Not sure if in this scenario some different implementation is needed for the ConnectionFactory.
#Bean public DefaultMessageListenerContainer orderMessageListenerContainer() {
DefaultMessageListenerContainer endpoint = new DefaultMessageListenerContainer();
endpoint.setMessageListener(new YourMessageListener());
endpoint.setDestination("yourDestination");
endpoint.setConnectionFactory(connectionFactory());
return orderDefaultJmsListenerContainerFactory().createListenerContainer(endpoint);
}
Solved manually with DefaultMessageListenerContainer.

With spring boot, how does it detect a JTA environment?

I'm trying to enable JTA with spring boot so that JPA and JMS will roll back together. All docs point to http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-jta.html and it states
When a JTA environment is detected, Spring’s JtaTransactionManager
will be used to manage transactions.
What is meant by "JTA environment is detected"?
I ask because I think that is what is tripping me up. I added dependencies for Atomikos, but jmsTemplate.isSessionTransacted() returns false. I am assuming I haven't properly marked my environment as JTA. I'm running with embedded tomcat.
What I am experiencing is the database changes are being rolledback with the transaction, but not the JMS messages.
UPDATE:
The part about sessionTransacted was not related. It was my misunderstanding.
A JTA environment is detected when a supported transaction manager is on the classpath (Atomikos or Bitronix in 1.3, and also Narayana in 1.4) or because a javax.transaction.TransactionManager is available in JNDI (typically because you've deployed your Boot app to a Java EE container).
I think you have misunderstood the purpose of the sessionTransacted flag on JmsTemplate. It's used when creating a new session (Connection.createSession), however the transacted value that's passed to createSession is ignored when you're running in a JTA environment.
You can see it in the class org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration:
#ConditionalOnClass(javax.transaction.Transaction.class)
#ConditionalOnProperty(prefix = "spring.jta", value = "enabled", matchIfMissing = true)
#AutoConfigureBefore({ XADataSourceAutoConfiguration.class,
ActiveMQAutoConfiguration.class, HornetQAutoConfiguration.class,
HibernateJpaAutoConfiguration.class })
#Import({ JndiJtaConfiguration.class, BitronixJtaConfiguration.class,
AtomikosJtaConfiguration.class, NarayanaJtaConfiguration.class })
#EnableConfigurationProperties(JtaProperties.class)
public class JtaAutoConfiguration {
}
Basically you have to have the JTA API on the classpath, and at least one JTA provider (Bitronix or Atomikos, if you're not using an application server).

MySQL and Infinispan - JTA implementation

We have an web application under Tomcat, integrated with Hibernate 4X, Spring 4X and HibernateTransactionManager as our transaction manager (currently one MySQL resource).
As part of our configuration distribution, we should integrate with Infinispan as our cache manager to store configuration with other format than in the MySQL. Meaning, not as Hibernate second level cache integration!
I managed to integrate Infinispan with Spring but now I'm facing a big problem due to the fact the MySql transaction and Infinispan must be on the same #Transactional.
I read about Spring JTA and how to integrate with Atomikos (e.g.) as our Global Transaction manager but I'm not sure if we can combine the whole entities to work together and how :(
I need to know if there's an option to work with Atomikos Spring JTA so the Infinispan will recognize this JTA implementation and will handle the MySql and Infinispan as one global transaction! (2PC)
Thanks!
At first I would suggest to configure Spring + Hibernate + JTA together. Here is a very nice tutorial. If you configured everything correctly - you should have one bean of a type TransactionManager. In above tutorial it is configured inside this block:
#Bean(initMethod = "init", destroyMethod = "close")
public TransactionManager transactionManager() throws Throwable {
UserTransactionManager userTransactionManager = new UserTransactionManager();
userTransactionManager.setForceShutdown(false);
return userTransactionManager;
}
Now you may configure Infinispan to use this transaction manager. The easiest way to achieve this, is to implement your own TransactionManagerLookup. This should return the transaction manager, which was created above.
Finally you have to create transactional cache, like this:
<local-cache name="transactional">
<transaction mode="FULL_XA"/>
</local-cache>
After that everything should work with the same Transaction Manager and Spring should handle everything within single #Transactional annotation.

Transaction in Spring with datasources create in runtime

I have a problem with transaction in spring, because in my project datasources are created in runtime from side files and according to documentation:
I should inject to TransactionManager dataSource and made it visible for annotation #Transactional using <tx:annotation-driven transaction-manager="txManager"/>.
So my question is how can I do it when I want to use annotation?
First of all how are you creating the datasources at runtime.
if directly as Datasource=new datasource... I will suges use BeanDefinitionBuilder in Spring 3.2 to Create the Datasourcebean and then register it via BeanDefinitionRegistry.
and then get the bean from Spring context and it will be considered using the transaction.

Resources