Multiple Transaction managers in Spring JPA - spring

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.

Related

When does spring use AOP without Aspectj.jar?

I can use annotation #Transactional at the top of my service PersonServiceBean and config transactionManager like below. After that, my service can execute db operations under transaction control through AOP.
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
.........
</bean>
<tx:annotation-driven transaction-manager="txManager"/>
<bean id="personService" class="cn.itcast.service.impl.PersonServiceBean">
<property name="dataSource" ref="dataSource"/>
</bean>
But i didn't include aspectj.jar into my project. How does it work? I heard spring implements AOP through aspectj.
It doesn't use AspectJ by default, but uses proxies (either JDK interface proxies or CGLIB proxies). So, when you inject a transactional bean into another bean, what you get injected is in fact a proxy to your actual bean instance, which intercepts the method calls and starts/commits/rollbacks transactions.
More in the documentation, of course.

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?

Setting property reference for a bean programmatically

Right now i am using the following bean entry
<bean id="Service" >
<property name="target">
<bean class="someClass" lazy-init="false">
<property name="SessionFactory1"><ref bean="SessionFactory1"/></property>
<property name="SessionFactory2"><ref bean="SessionFactory2"/></property>
<property name="SessionFactory3"><ref bean="SessionFactory3"/></property>
</bean>
</property>
</bean>
Now the requirement is to first check which all session factories have an active datasource and include those only in the above bean definition. So that the application does not break if we try to initialize a session factory with inactive datasource.
sessionfactory initialization will be take care by using seperate config xml for session factories and loading only the ones with active datasources.
Please help on how can this be achieved.
You can use Spring InitializingBean interface, which makes you implement an afterPropertiesSet() method. This method will be executed after Spring instantiates your class, and you could check if your session factories are available or not.
InitializingBean: Interface to be implemented by beans that need to react once all their properties have been set by a BeanFactory: for example, to perform custom initialization, or merely to check that all mandatory properties have been set.
link: Spring InitializingBean

Spring JTA transaction with JPA and jndi datasource for Websphere

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.

Wicket with Spring declarative transaction

It is possible to use the Spring Framework's #Transactional support outside of a Spring container. In reference documentation is chapter about AspectJ aspect. I'm trying to use it in my wicket application, but with no positive result.
application-context.xml:
<tx:annotation-driven transaction-manager="transactionManager" mode="aspectj" />
<context:annotation-config />
<context:component-scan base-package="com.wicket.app"/>
<context:spring-configured />
<bean id="annotationTransactionAspect" factory-method="aspectOf"
class="org.springframework.transaction.aspectj.AnnotationTransactionAspect">
<property name="transactionManager" ref="transactionManager"></property>
</bean>
In my form class annotated by #Configurable, I have:
#Transactional
public void process(IFormSubmittingComponent submittingComponent) {
super.process(submittingComponent);
getDao().getEntityManager().flush();
}
Stack trace:
org.apache.openjpa.persistence.TransactionRequiredException: Can only perform operation while a transaction is active.
You might be able to get this working using AspectJ load-time-weaving, but that's a very complex solution for a simple problem.
If you need declarative transactions, then I suggest you move the transactional logic from the wicket component down into a Spring bean, and invoke the Spring bean from the wicket object. The Spring bean would have the transactional annotations, and would be proxied correctly by the Spring container.
I have no experience with Wicket. But is your 'form class' (the one that contains method annotated with #Transactional) Spring managed code? i.e. Who creates the instances of the class?
If it's not, that Spring will not provide #Transactional support (neither will #Autowired work, etc).

Resources