Hello,
I'm currently having a problem having a transaction span over two Dao method calls. Allow me to post relevant parts of the application context XML and code to illustrate what I have going on right now.
The Datasource:
The Session Factory:Code:<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiName"><value>java:comp/env/jdbc/BrewerfanDB</value></property> </bean>
The Transaction Manager:Code:<bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean"> <property name="dataSource"><ref local="dataSource"/></property> <property name="mappingResources"> <list> <value>net/brewerfan/bizmodel/article/LinkedArticle.hbm.xml</value> <value>net/brewerfan/bizmodel/common/Player.hbm.xml</value> </list> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">net.sf.hibernate.dialect.MySQLDialect</prop> </props> </property> </bean>
The transaction properties I wish to use:Code:<bean id="transactionManager" class="org.springframework.orm.hibernate.HibernateTransactionManager"> <property name="sessionFactory"><ref local="sessionFactory"/></property> </bean>
My Transaction Interceptor:Code:<bean id="matchAllWithPropReq" class="org.springframework.transaction.interceptor.MatchAlwaysTransactionAttributeSource"> <property name="transactionAttribute"><value>PROPAGATION_REQUIRED</value></property> </bean>
My AutoProxyCreator, since I wish to have ALL method calls on all Service and Dao objects use the same transaction given a particular client call:Code:<bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor"> <property name="transactionManager"><ref local="transactionManager"/></property> <property name="transactionAttributeSource"> <ref bean="matchAllWithPropReq"/> </property> </bean>
My Daos:Code:<bean id="autoProxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> <property name="interceptorNames"> <list> <idref local="transactionInterceptor"/> </list> </property> <property name="beanNames"> <list> <value>*Dao</value> <value>*Service</value> </list> </property> </bean>
My Service Object:Code:<bean id="linkedArticleDao" class="net.brewerfan.dao.article.hibernate.LinkedArticleHibernateDaoImpl"> <property name="sessionFactory"><ref local="sessionFactory"/></property> </bean> <bean id="playerDao" class="net.brewerfan.dao.common.hibernate.PlayerHibernateDaoImpl"> <property name="sessionFactory"><ref local="sessionFactory"/></property> </bean>
I have a base Dao implementation I use and extend with all my Daos:Code:<bean id="articleService" class="net.brewerfan.dao.article.ArticleService"> <property name="linkedArticleDao"><ref local="linkedArticleDao"/></property> <property name="playerDao"><ref local="playerDao"/></property> </bean>
Here's my client code (a struts action):Code:public abstract class AbstractBrewerfanHibernateDao extends HibernateDaoSupport { protected abstract Class getPersistentClass(); public List findAll() throws DataAccessException { return (getLocalTemplate().find("from " + getPersistentClass().getName())); } public Entity find(long id) throws DataAccessException { List results = getLocalTemplate().find( "from " + getPersistentClass().getName() + " where id=" + id); if (results.size() > 0) { return ((Entity) results.get(0)); } else { throw new IllegalArgumentException("No " + getPersistentClass().getName() + " found with id: " + id); } } public void store(Entity entity) throws DataAccessException { if (entity.getId() == 0) { getLocalTemplate().save(entity); } else { getLocalTemplate().update(entity); } } public void store(Collection collection) throws DataAccessException { for (Iterator iter = collection.iterator(); iter.hasNext();) { Entity element = (Entity) iter.next(); store(element); } } public void remove(long id) { HibernateTemplate ht = this.getLocalTemplate(); Object o = ht.load(getPersistentClass(), new Long(id)); ht.delete(o); } public List findLimited(int numberToFind, String orderProp, String orderByType) { Query query; try { query = this.getLocalTemplate().createQuery( this.getLocalSession(), "from " + this.getPersistentClass().getName() + " order by " + orderProp + " " + orderByType); query.setMaxResults(numberToFind); return (query.list()); } catch (DataAccessResourceFailureException e) { e.printStackTrace(); } catch (HibernateException e) { e.printStackTrace(); } catch (IllegalStateException e) { e.printStackTrace(); } return (null); } protected Criteria createCriteria() throws HibernateException { return (this.getLocalTemplate().createCriteria(this.getLocalSession(), this.getPersistentClass())); } private Session getLocalSession() { return (SessionFactoryUtils.getSession(this.getSessionFactory(), true)); } private HibernateTemplate getLocalTemplate() { return (new HibernateTemplate(this.getSessionFactory())); }
I'm getting "Initiating transaction commit" written out three times in stdout, so i'm assuming there is one transaction being started and stoppedCode:public class AddLinkedArticlePlayerAction extends AdminAction { /* * (non-Javadoc) * * @see net.brewerfan.gui.admin.action.AdminAction#adminPerform(org.apache.struts.action.ActionMapping, * org.apache.struts.action.ActionForm, * javax.servlet.http.HttpServletRequest, * javax.servlet.http.HttpServletResponse, * net.brewerfan.bizmodel.common.User) */ public ActionForward adminPerform(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, User user) throws ApplicationException { System.out.println("Starting transaction!"); AddLinkedArticlePlayerForm playerForm = (AddLinkedArticlePlayerForm) form; long playerId = Long.parseLong(playerForm.getPlayerId()); ArticleService service = (ArticleService) BrewerfanConstants.APPLICATION_CONTEXT .getBean("articleService"); Player player; try { player = service.findPlayer(playerId); } catch (IllegalArgumentException e) { ActionErrors ae = new ActionErrors(); ae.add("playerId", new ActionError("error.common.playerId.notfound")); this.saveErrors(request, ae); return (new ActionForward(mapping.getInput())); } LinkedArticle article = service.findLinkedAritcle(playerForm .getLinkedArticleId()); Set players = article.getPlayers(); if (players == null) { players = new HashSet(); } players.add(player); article.setPlayers(players); service.store(article); request.getSession().setAttribute("linkedArticleId", Long.toString(playerForm.getLinkedArticleId())); System.out.println("Ending transaction!"); return this.getRedirectSuccess(mapping); }
for each call to the service (which delegeates to the dao). I've been trying to figure this out on my own for a month now... any help for this
novice would be greatly appreciated!


Reply With Quote