Struts actions and declarative transactions
Hi,
The question is: What is the simplest way to define declarative transaction demarcation for all my Struts actions?
If I try to explain further:
Our project currently uses Struts and Castor. We want to move to Spring and Hibernate (with Struts still present for the moment).
The architecture we came up with is like this (giving example class names):
OfferDAO (interface)
OfferDAOHibernate (implements OfferDAO)
OfferManager (interface)
OfferManagerImpl (implements OfferManager) (calls methods of OfferDAO)
These are all set up now. Relevant parts in the applicationContext.xml looks like this:
Code:
<bean id="transactionManager" class="org.springframework.orm.hibernate.HibernateTransactionManager">
<property name="sessionFactory"><ref local="sessionFactory"/></property>
</bean>
<bean id="offerDAO" class="dao.hibernate.OfferDAOHibernate">
<property name="sessionFactory"><ref local="sessionFactory"/></property>
</bean>
<bean id="offerManager"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager">
<ref local="transactionManager"/>
</property>
<property name="target">
<ref local="offerManagerTarget"/>
</property>
<property name="transactionAttributes">
<props>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="remove*">PROPAGATION_REQUIRED</prop>
<prop key="*">PROPAGATION_SUPPORTS,readOnly</prop>
</props>
</property>
</bean>
<bean id="offerManagerTarget"
class="offer.OfferManagerImpl">
<property name="offerDAO"><ref local="offerDAO"/></property>
</bean>
I have written unit tests and it works beautifully. However, all the methods in the managers are the methods present in the DAOs... Which means that the managers are not real managers at the moment, but a facade to call the DAO methods instead.
Now I want to adapt my Struts actions to use this setup. Unfortunately, at the moment in our Struts actions, what we do is this:
1. Get a transaction context, and begin transaction
2. Get necessary parameters from request object
3. Do lots of business logic
4. At the end, commit or rollback the transaction.
With the new Struts+Hibernate setup, I understand that I have to move lots of the code in my Struts actions to the Managers... As an example, we have a "CreateOfferAction" Struts action. I already refactored it to call the methods from OfferManager, which in turn calls methods of OfferDAO. However, since I defined declarative transactions for the OfferManager, each call from the Struts action takes its own transaction. But of course what I want is, that in a single Struts action, all calls to the OfferManager methods to share a single transaction.
So, let me repeat the question again: I have lots of Struts actions, which obviously have their own "execute" methods. How can I define in the applicationContext.xml file so that all "execute" methods of all Struts actions to have "PROPAGATION_REQUIRED" declarative transaction?
To illustrate, I want to have:
Code:
<for all classes that extend from a particular class (org.apache.struts.action.Action here)>
<property name="transactionAttributes">
<props>
<prop key="execute*">PROPAGATION_REQUIRED</prop>
<prop key="*">PROPAGATION_SUPPORTS,readOnly</prop>
</props>
</property>
</for all>
Of course, ideally, I'll refactor the actions to call the managers only, sending request parameters, and accepting parameters to be put into the response object. All transactons will take place in the manager methods. But at the moment, I don't have that time, so I'd like to learn if there is any simple way to make all "execute" methods of Struts actions to have their own transactions, using Spring AOP support...
Thanks in advance,
Regards,
Turgay Zengin
Re: Struts actions and declarative transactions
Quote:
Originally Posted by turgayz
With the new Struts+Hibernate setup, I understand that I have to move lots of the code in my Struts actions to the Managers...
Yes :).
Quote:
[...] have a "CreateOfferAction" Struts action. I already refactored it to call the methods from OfferManager, which in turn calls methods of OfferDAO. However, since I defined declarative transactions for the OfferManager, each call from the Struts action takes its own transaction. But of course what I want is, that in a single Struts action, all calls to the OfferManager methods to share a single transaction.
Consider rewriting Your Service layer in such a way, so You would be able to declare transaction on one "service level". Just delegate your "buisness logic" from actions into service layer.
Quote:
So, let me repeat the question again: I have lots of Struts actions, which obviously have their own "execute" methods. How can I define in the applicationContext.xml file so that all "execute" methods of all Struts actions to have "PROPAGATION_REQUIRED" declarative
[...]
Of course, ideally, I'll refactor the actions to call the managers only, sending request parameters, and accepting parameters to be put into the response object. All transactons will take place in the manager methods. But at the moment, I don't have that time, so I'd like to learn if there is any simple way to make all "execute" methods of Struts actions to have their own transactions, using Spring AOP support...
You have two options:
* org.springframework.web.struts.DelegatingRequestPr ocessor
or
* org.springframework.web.struts.DelegatingActionPro xy
Remember that struts actions are classes, so You have to use cglib instead of jdk Proxies.
Artur
Transactions / thread do not appear to work
Set up declarative transactions and in struts action make multiple calls to service layer. It seems that each call to the service layer results in a commit. I thought the transaction was tied to the local thread so it would only commit once per request. What am I missing here?
Re: Transactions / thread do not appear to work
Quote:
Originally Posted by garpinc2
Set up declarative transactions and in struts action make multiple calls to service layer. It seems that each call to the service layer results in a commit. I thought the transaction was tied to the local thread so it would only commit once per request. What am I missing here?
No, the transaction is wrapped around the service method call. For this reason I like to make a single service call per action (which returns a composite view object).
Please send an example...
Please send an example...
Re: Please send an example...
Quote:
Originally Posted by garpinc2
Please send an example...
Just have a look at Matt Raible's "Spring Live" e-book, in particular his free Chapter #2 at http://www.sourcebeat.com/docs/Sprin...pleChapter.pdf.