Spring JTA transaction with JPA and jndi datasource for Websphere - spring

I am having multiple datasource and one one database configured with JPA. I am using websphere 7. I want all these datasouces to be configured as global transactions. I am using below spring configurations but the transactions are not working as expected global transaction. If one db is failing then the other db is getting commited which is not expected as single global transactions. Can you please help me where i m doing incorrect,
I am having 2 datasouce one as configured below with id="us_icfs_datasource" and another using JPA
<jee:jndi-lookup id="entityManagerFactory" jndi-name="persistence/persistenceUnit"/>
<bean id="pabpp" class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager" />
<!-- Needed for #Transactional annotation -->
<tx:annotation-driven/>
<jee:jndi-lookup id="US_ICFS_DATASORCE"
jndi-name="jdbc/financing_tools_docgen_txtmgr"
cache="true"
resource-ref="true"
proxy-interface="javax.sql.DataSource" />
also I have added below code in web.xml
<persistence-unit-ref>
<persistence-unit-ref-name>persistence/persistenceUnit</persistence-unit-ref-name>
<persistence-unit-name>persistenceUnit</persistence-unit-name>
</persistence-unit-ref>
<persistence-context-ref>
<persistence-context-ref-name>persistence/persistenceUnit</persistence-context-ref-name>
<persistence-unit-name>persistenceUnit</persistence-unit-name>
</persistence-context-ref>
below is my code where i m using transaction
> #Transactional public TemplateMapping addTemplateMapping(User user,
> TemplateMapping templateMapping) throws
> TemplateMappingServiceException { .... }

On Websphere you should use this bean to hook into the Websphere transaction manager:
<bean id="transactionManager"
class="org.springframework.transaction.jta.WebSphereUowTransactionManager"/>
See also this article
EDIT:
In order to use 2-phase commit (i.e. ensuring consistency across multiple resources), you will need to use XA data sources. See this article for details.

First of all your data sources that participate in global transaction must be of javax.sql.XADataSource type.
You also have to set transaction type in your persistence unit to JTA (not RESOURCE_LOCAL).
And you need to inform your JPA implementation that you want to do global transactions.

Related

Multiple Transaction managers in Spring JPA

I want to use two transaction managers as follows
<bean id="transactionManagerReadOnly" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactoryReadOnly" />
</bean>
<bean id="transactionManagerReadWrite" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactoryReadWrite" />
</bean>
and in my code there are tx:annotation-driven tags are present such as follows
<tx:annotation-driven mode="aspectj" transaction-manager="transactionManagerReadWrite"/>
<tx:annotation-driven mode="aspectj" transaction-manager="transactionManagerReadOnly"/>
but I read somewhere that there should be only one tx:annotation-driven present and refer another transaction manager by specifying in #Transaction tag such as folows
#Transactional("transactionManagerReadWrite")
#Transactional("transactionManagerReadOnly")
Following are my questions and queries
Which transaction manager is considered as a valid candidate for #Transactional if there are two transaction managers present and two tx:annotation-driven tags present in configuration file if we don't specify the name of transaction manager explicitly in #Transactional annotation ?
What would be the mode of second transaction manager if it is recommended to have only one tx:annotation-driven tag in application and we specify the mode in tx:annotation-driven tag only ?
i.e. springs default mode is proxy mode and I want to use two transaction manager's with aspectj mode
How to specify aspectj mode for second transaction manager if we can use only one tx:annotation-driven tag and default mode is proxy mode in spring ?
You can only have a single <tx:annotation-driven /> as that configured how #Transactional annotations are handled. You specify the mode (proxy or aspectj) and the default transaction manager to associate with #Transactional annotations.
The aspect is thus either applied through proxies (mode proxy) or load or compile time weaving (mode aspectj). There is just 1 aspect and that aspect either uses the default transaction manager or the one defined in the #Transactional annotation.
Given you specify the aspectj mode and transactionManagerReadWrite as the default transaction manager
<tx:annotation-driven mode="aspectj" transaction-manager="transactionManagerReadWrite"/>
Now when using a plain #Transactional it will use transactionManagerReadWrite, when using #Transactional("transactionManagerReadOnly") it will use the transactionManagerReadOnly. Either one will be weaved in as aspectj is used as the mode to apply transactions.

Unit Testing based on JNDI , ejb and spring

In my application I am injecting some of services based on EJB with use of Spring IOC through JndiObjectFactoryBean like below mentioned so during run the junit I am getting this exception "java.lang.IllegalArgumentException: This JNDI operation is not implemented by the JNDI provider."
Could some please let me know how I'll configure for Junit.
<bean id="xxxMenuItemService" class="xxxMenuItemServiceyyy">
<property name="xxxMenuItemDelegator" ref="xxxMenuItemDelegator" />
</bean>
<bean id="approveMenuItemServiceRemote"
class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName"
value="ejb/XXXXXXXX" />
have a look at the SimpleNamingContextBuilder from org.springframework.mock as it provides a full context builder where you can bind mock or other objects for use by Spring's JNDI lookup.
One thing to do though is to make sure you build the SimpleNamingContextBuilder in the static #BeforeClass of JUnit 4. this means that it is all initialized and waiting before the Spring Application Context is started and you won't have any JNDI lookup failures.

How do I access TomEE's JTA transaction manager?

I have an application that uses Spring's declarative transaction management. How can I deploy this in a TomEE+ container so that the application uses TomEE's JTA transaction manager?
More specifically, how can I refer to the built-in transaction manager from within Spring's "application-context.xml" file?
Spring's transaction management configuration seems to want to look up the transaction manager either by a bean reference or by JNDI lookup; I have spent a day researching this and looking at source code; I have found a lot of discussion of the issue (references below) but no definitive how-to.
What I have in the application's META-INF/persistence.xml is this:
<persistence-unit name="myPersistenceUnit" transaction-type="JTA">
<provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
<jta-data-source>myDs-managed</jta-data-source>
<non-jta-data-source>myDs-unmanaged</non-jta-data-source>
<properties>
<property name="openjpa.jdbc.DBDictionary"
value="org.apache.openjpa.jdbc.sql.PostgresDictionary"/>
<property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema"/>
<property name="openjpa.Run
<property name="openjpa.Log" value="slf4j" />
</properties>
</persistence-unit>
And, in the applications META-INF/spring/applicationContext.xml file I have this: (I have tried various values for transactionManagerName as suggested in various discussions of the topic, as it appears to be non-standard across application servers
<tx:annotation-driven mode="aspectj" transaction-manager="txManager" />
<bean class="org.springframework.transaction.jta.JtaTransactionManager"
id="txManager">
<property name="transactionManagerName"
value=" java:comp/TransactionManager"/>
</bean>
Here's an example that is claimed to work for JBoss: Spring JTA configuration - how to set TransactionManager?
Here's a near miss that won't work in an xml configuration file: https://issues.apache.org/jira/browse/TOMEE-38
Here's how to do it within java code if you have your hands on initialContext: http://osdir.com/ml/users.openejb.apache.org/2012-11/msg00110.html
[Edit: The Tomee documentation talks about how to declare a transaction manager, but it says to do it in Tomee.xml, which belongs to the server and not to the individual webapp; I want to configure the transaction manager for a single app and not for the whole server: http://tomee.apache.org/containers-and-resources.html]
Have you tried java:comp/env/TransactionManager for the transactionManagerName?
,
Also have you declared the TransactionManager and DataSource as described here: http://tomee.apache.org/containers-and-resources.html?

Using Spring Transactions in MyBatis API

We have developed a data persistence framework using Mybatis. The framework uses plain MyBatis APIs. (We were prohibited from using any mybatis-spring, do not ask… why?)
Now we have to integrate this persistence framework with another framework developed by other teams. This other framework heavily uses spring transactions for everything. Our persistent framework DAOs will be used by this framework within its own API ….that means the spring managed transactions will be propagated to MyBatis DAO. It is expected that our MyBatis based persistence framework should participate in spring managed transactions without any issues.
There are two options for us to make this work
(1)Change our persistent framework to use mybatis-spring module. Change DAOs to use mappers directly injected using spring and spring’s SqlSessionFactoryBean. I did build a small example simulating both the frameworks and everything works without any issue. The problem is with this approach that it requires changing almost all the DAOs to use spring injected mapper, extensively test the framework again. We simply do not have time available due to delivery timeline.
(2)Use mybatis-spring, define SqlSeeionFactory using spring – set the datasource and transaction manager used by other framework. Something like
<bean id="smpDataSource" class="oracle.jdbc.pool.OracleDataSource" destroy-method="close">
<property name="connectionCachingEnabled" value="true" />
<property name="URL"> <value>${db.thin.url}</value></property>
<property name="user"> <value>${db.user}</value></property>
<property name="password"><value>${db.password}</value>
</property>
</bean>
<bean id="dbTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="smpDataSource" />
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="smpDataSource" />
<property name="typeAliasesPackage" value="spike.smp51.domain" />
<property name="mapperLocations" value="classpath*:spike/smp51/mappers/*.xml" </bean>
Then in applicataion code MyBatis DAO gets the sqlseesionfactory from spring like
public static SqlSessionFactory getSqlSessionFactory() throws Exception
{
DefaultSqlSessionFactory sessionFactory = (DefaultSqlSessionFactory)ctx.getBean("sqlSessionFactory");
return sessionFactory;
}
All DAOs already use SqlSeesionFactory to open and close sessions. Just replace that mybatis created sqlseeionfactory with spring created sqlseeionfactory. That way we will have only few lines of changes.
This approach is outlined here
http://mybatis.github.io/spring/using-api.html
The mybatis documentation warns about this approach – specifically that it will not participate in spring transactions.
When I tried the 2nd approach, our framework was able to participate in spring transactions. This is strange. Is the MyBatis documentation incorrect then? I did verify it extensively by creating various transaction boundaries using spring transactions + AOP . MyBatis DAOs are able to participate in spring managed transactions every time. Since this second approach will save us 90% of the development time – we really like to use it – but worried since MyBatis warns following this approach. Has anyone tried this approach? Any feedback is greatly appreciated.
Did you have any return on that ?
I'm wondering if in the doc they're talking about org.apache.ibatis.session.SqlSessionFactory from Mybatis-api while the SqlSessionFactory you're using is from the mybatis-spring lib : org.mybatis.spring.SqlSessionFactoryBean

Spring JNDI Configuration

We are using Spring to do JNDI look-up for our data access requirements. We are making calls to multiple stored procedures (in Sybase). I wanted a way to control the auto-commit property of the transactions while calling these stored procs. I was able to achieve it with BasicDataSource (property name="defaultAutoCommit").
But I got stuck when we moved to doing JNDI look-up (from Weblogic).
<jee:jndi-lookup jndi-name="WL_data_source" id="dataSource" />
<bean id="procedureHandlerBean" class="myclass">
<property name="procDataSource" ref="dataSource"/>
</bean>
After researching for a few days, it appears to me that I can use JtaTransactionManager. However, I am not sure if I can use the transaction manager to configure auto-commit on a per procedure call basis (due to different chained/unchained mode requirements of different procs). Is there a clean way to achieve this? Thanks

Resources