Spring jta-transaction-manager - java

Using Spring:
can jta-transaction-manager use id as name so that I can pass it as REF to my service layer like below?
is tx:jta-transaction-manager can only be used for je22 container? I mean for Tomcat, I need to do it manually, like below:
<tx:jta-transaction-manager id="name_transactionmanager"/>
<bean id="projectService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager"
ref="name_transactionmanager"/>
<property name="target">
<bean
class="com.company.project.company.services.ServiceImpl"
init-method="init">
<property
name="HRappsdao"
ref="HRappsdao"/>
<property
name="projectdao"
ref="projectdao"/>
</bean>
</property>
<property name="transactionAttributes">
<props>
<prop key="store*">PROPAGATION_REQUIRED</prop>
<prop key="update*">PROPAGATION_REQUIRED</prop>
<prop key="remove*">PROPAGATION_REQUIRED</prop>
<prop key="bulkUpdate*">PROPAGATION_REQUIRED</prop>
<prop key="*">PROPAGATION_SUPPORTS,readOnly</prop>
</props>
</property>
</bean>
For question 2
<bean id="transactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="userTransaction">
<bean class="org.springframework.transaction.jta.JotmFactoryBean"/>
</property>
</bean>

Can tx:jta-transaction-manager use id as name so that I can pass it as REF to my service layer like below?
The <tx:jta-transaction-manager> exposes the transaction manager as a Bean in the Spring context with the name "transactionManager".
Can tx:jta-transaction-manager only be used with a J2EE container?
Quoting the Chapter 9. Transaction management from the Spring documentation:
Is an application server needed for transaction management?
The Spring Framework's transaction
management support significantly
changes traditional thinking as to
when a J2EE application requires an
application server.
In particular, you don't need an
application server just to have
declarative transactions via EJB. In
fact, even if you have an application
server with powerful JTA capabilities,
you may well decide that the Spring
Framework's declarative transactions
offer more power and a much more
productive programming model than EJB
CMT.
Typically you need an application
server's JTA capability only if you
need to enlist multiple transactional
resources, and for many applications
being able to handle transactions
across multiple resources isn't a
requirement. For example, many
high-end applications use a single,
highly scalable database (such as
Oracle 9i RAC). Standalone transaction
managers such as Atomikos Transactions
and JOTM are other options. (Of course
you may need other application server
capabilities such as JMS and JCA.)
The most important point is that with
the Spring Framework you can choose
when to scale your application up to a
full-blown application server. Gone
are the days when the only alternative
to using EJB CMT or JTA was to write
code using local transactions such as
those on JDBC connections, and face a
hefty rework if you ever needed that
code to run within global,
container-managed transactions. With
the Spring Framework, only
configuration needs to change so that
your code doesn't have to.
So, as explained in the third paragraph, if you want to work with multiple transactional resources, you'll need global transactions which involve a JTA capable application server. And JTA capable application server means a real J2EE container or a non J2EE container (like Tomcat) with a standalone transaction manager like Atomikos, JOTM, Bitronix, SimpleJTA, JBossTS or GeronimoTM/Jencks.
FWIW, I've seen lots of complains about JOTM, I think that GeronimoTM/Jencks lacks of documentation, I can't really say anything about JBossTSArjunaTS (except that it's a rock solid product), SimpleJTA and Bitronix have both good documentation and Atomikos is an impressive product greatly documented too. Personally, I'd choose Bitronix or Atomikos.
PS: Honestly, if this sounds like Chinese to you, you should maybe consider using a single database (if this is an option, go for it!) or consider using a real J2EE container like JBoss or GlassFish as I wrote in a previous answer. No offense but all this JTA stuff is not trivial and taking the JOTM path is not that simple if you don't really understand why you need it.

Related

Spring transaction management using JDBC and Hibernate 4 together

We are using JPA (Hibernate 4) with Spring 4 managing the JTA transactions. Since there are parts of the application using JDBC to access the database as well, we need to make sure JDBC and JPA join the same transaction to see what the other changed before commit.
You can find a test case for these questions on GitHub https://github.com/abenneke/sandbox/tree/master/spring-hibernate4-transaction
To have JDBC and JPA join the same transaction and see the changes the other made, we had to use the TransactionAwareDataSourceProxy for Hibernate/JPA as well. With all the other transaction configuration around, this however seems to be redundant. Did we miss something? Or is this the suggested way to achieve the requirement?
Thank you!
I think you can achieve the same outcome with much less configuration hassle if you stock to Hibernate and your JTA DataSource while you use the Session.doWork for your JDBC code.
You don't need TransactionAwareDataSourceProxy, since you want to use Transaction services anyway and not call DAO classes outside of a transactional service.
You need to add:
<bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>
and make sure you supply it to testEntityManager
<bean id="testEntityManager" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="testDataSource">
...
<property name="jpaDialect" ref="jpaDialect"/>
</bean>
Update
In one application we developed recently we too mixed JPA and JDBCTemplate and it worked nicely because Bitronix PoolingDataSource was instructed to always return the same connection for the current running thread.
For this you have to set the following Bitronix property:
shareTransactionConnections=true

Using spring as configurator

I have a server application. Now I'm using Spring not only to inject dependencies, but also to config my application. Something like this:
<bean id="server" class="foo.bar.Server">
<property name="host" value="${config.host}"/>
<property name="someBean">
<ref bean="someBean"/>
</property>
</bean>
My colleague sad that configuring application in Spring is not obvious and we should avoid this. I see logic in his words, because Spring is for dependence injection and server port is not dependency, isn't it? But for me configuring application is Spring is very convenient and obvious. Is my colleague right?
Configuring in Spring is simple, clear and maintainable.
This way you can easily create several instances with different properties.

TransactionProxyFactoryBean when switching from configuration-based Service beans to annotation based service beans

I read about using
<context:component-scan base-package="tld.mydomain.business">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
</context:component-scan>
and annotate my service beans with #Service("myService"), and thought great, I'll do that, since I'm already doing that with my controllers. My usual service bean configuration looks like
<bean id="userService" parent="txProxyTemplate">
<property name="target">
<bean class="tld.mydomain.business.UserServiceImpl"/>
</property>
<property name="proxyInterfaces" value="tld.mydomain.business.UserService"/>
</bean>
so now that I generate them, how do I wrap them in a Hibernate proxy such as TransactionProxyFactoryBean? Or is there a better way to do that as well?
I have not yet gone all the way and used #Repository as well, is that required?
Cheers
Nik
Using TransactionProxyFactoryBean is not encouraged in modern Spring applications, although it still works. The typical approach nowadays is to annotate classes with #Transactional, and then stick this element in your application context file:
<tx:annotation-driven transaction-manager="txManager"/>
This and other strategies are discussed in great depth in the reference document, and there's even a side note about TransactionProxyFactoryBean.
There's no need for
<context:include-filter type="annotation"expression="org.springframework.stereotype.Service"/>
Spring will register #Service, #Repository, #Component... once they are found in the base package.
Like #Rob said either use #Transactional or <aop:config>...</aop:config> to handle your transactions at the service level.
If you have two different resources that need to be in the same transaction, then you will need to use JTA. See my answer to an earlier question here. Your config would need to look something like:
<tx:annotation-driven transaction-manager="txManager"/>
<bean id="txManager"
class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManagerName" value="appserver/jndi/path" />
</bean>
Where appserver/jndi/path would need to be replaced with the JNDI path of the JTA transaction manager that comes with your application server (although you can use a standalone JTA transaction manager such as JOTM as well). Typical paths as mentioned in the 2.5.x API are:
"java:comp/UserTransaction" for Resin 2.x, Oracle OC4J (Orion), JOnAS (JOTM), BEA WebLogic
"java:comp/TransactionManager" for Resin 3.x
"java:appserver/TransactionManager" for GlassFish
"java:pm/TransactionManager" for Borland Enterprise Server and Sun Application Server (Sun ONE 7 and later)
"java:/TransactionManager" for JBoss Application Server

Problem managing session with multiple data sources

I am working on a project where we each service refers four separate data-source. Until now, we have been using ProxyFactoryBean to refer to the Dao target and the Transaction Intereceptor - something like this..
<bean id="readOnlyUserProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="readOnlyDao"/>
<property name="interceptorNames">
<list>
<value>readOnlyTransactionInterceptor</value>
</list>
</property>
</bean>
There are 3 other similar proxies for the different DAOs . All these refer to different transaction interceptors which in turn connect to different transaction managers. In short, each service connects to 4 dao proxies each of which refer a separate transaction interceptor, each of which in turn refer to a separate transaction manager connecting to 4 different data sources. All work fine till now with lazy="false".
Now, In order to optimize the performance, we wish to enable 'Lazy loading' and carry the hibernate session to the handler layer. We think that the best way for this would be through the 'TransactionProxyFactoryBean' as we do not want to use the OpenSessionInView approach .
We have tried some approaches but are stuck because we connect to 4 separate data sources through each service and in now way can we connect the four separate transaction managers to the 'TransactionProxyFactoryBean'. Therefore, we are not able to find a way to manage the transactions from different data sources in the handler/service layer.
I have just started on this work and do not have much experience in Spring transaction management. Kindly guide me on any possible approach I could take.
Managing transactions across multiple datasources is the job of the application server. The appserver will expose those transactions via the JTA API, and Spring can bridge from the JPA API to the Spring API using JtaTransactionManager.
As for how to configure the app server itself, that depends on what app server it is, you should do some research into that documention. It can be quite a complex operation, especially if the data sources are spread across different database servers (in which case you get into needing an XA Transaction Monitor, and it all gets very complicated).

JPA Multiple Transaction Managers

I have one applicationContext.xml file, and it has two org.springframework.orm.jpa.JpaTransactionManager (each with its own persistence unit, different databases) configured in a Spring middleware custom application.
I want to use annotation based transactions (#Transactional), to not mess around with TransactionStatus commit, save, and rollback.
A coworker mentioned that something gets confused doing this when there are multiple transaction managers, even though the context file is set configured correctly (the references go to the correct persistence unit.
Anyone ever see an issue?
In your config, would you have two transaction managers?
Would you have txManager1 and txManager2?
That's what I have with JPA, two different Spring beans that are transaction managers.
I guess you have 2 choices
If your use-cases never require updates to both databases within the same transaction, then you can use two JpaTransactionManagers, but I'm not sure you will be able to use the #Transactional approach? In this case, you would need to fallback on the older mechanism of using a simple TransactionProxyFactoryBean to define transaction boundaries, eg:
<bean id="firstRealService" class="com.acme.FirstServiceImpl"/>
<bean id="firstService"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="firstJpaTm"/>
<property name="target" ref="firstRealService"/>
<property name="transactionAttributes">
<props>
<prop key="insert*">PROPAGATION_REQUIRED</prop>
<prop key="update*">PROPAGATION_REQUIRED</prop>
<prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>
<!-- similar for your second service -->
If you are require a transaction spanning both databases, then you will need to use a JTA transaction manager. The API states:
This transaction manager is appropriate for applications that use a single JPA EntityManagerFactory for transactional data access. JTA (usually through JtaTransactionManager) is necessary for accessing multiple transactional resources within the same transaction. Note that you need to configure your JPA provider accordingly in order to make it participate in JTA transactions.
What this means is that you will need to provide a JTA transaction manager. In our application, we use config similar to the following:
<tx:annotation-driven transaction-manager="txManager"/>
<bean id="txManager"
class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManagerName" value="appserver/jndi/path" />
</bean>
If you are deploying within an appserver, then the spring JtaTransactionManager needs to do a lookup to the real XA-compliant JTA transaction manager provided by the appserver. However, you can also use a standalone JTA transaction manager (but I haven't tried this myself yet)
As for configuring the Jpa persistence provider, I'm not that familiar. What JPA persistence provider are you using?
The code above is based on our approach, where we were using native Hibernate as opposed to Hibernate's JPA implementation. In this case, we were able to get rid of the two HibernateTransactionManager beans, and simply ensure that both SessionFactories were injected with the same JTA TM, and then use the tx:annotation-driven element.
Hope this helps
The only situation in which you can have two Spring transaction managers is if you never have both transactions open at one time. This is not intrinsically to do with distributed transactions - the same restrictions apply even if you want the two datasources to have completely separate (but potentially overlapping in time) transaction lifecyles.
Internally Spring's transaction managers all use Spring's TransactionSynchronizationManager which keeps a bunch of critical state in static ThreadLocal variables, so transaction managers are guaranteed to stomp all over each other's state.

Categories

Resources