PDA

View Full Version : Cannot rollback tx when using TransactionProxyFactoryBean


amd700
Dec 6th, 2004, 03:37 AM
Hi all,
I have encountered a problem when using Spring Transaction Management feature.
The following sources are based on the example petClinic sources.
But the TransactionProxyFactoryBean seem go wrong (maybe) when I intentionally throw a DataAccessException in storeComposite method.
The transaction still commit instead rollback.
Please help me. Thank you


--------- composite.hbm.xml -----------
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hib...g-2.0.dtd">

<hibernate-mapping auto-import="true">
<class name="example.framework.model.CompositeModel" table="Composite">
<id name="id" type="int" unsaved-value="-1">
<generator class="assigned"/>
</id>

<set name="children" lazy="false" cascade="all">
<key column="parent_id"/>
<one-to-many class="example.framework.model.CompositeModel"/>
</set>

<property name="parentId" column="parent_id" type="java.lang.Integer"/>
<property name="name" type="java.lang.String"/>
<property name="description" type="java.lang.String"/>
</class>
</hibernate-mapping>



----------------jdbc.properties ---------------
jdbc.driverClassName=org.hsqldb.jdbcDriver
jdbc.url=jdbc:hsqldb:hsql://localhost:9001
jdbc.username=sa
jdbc.password=

hibernate.dialect=net.sf.hibernate.dialect.HSQLDia lect



----------------- applicationContext.xml -----------
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/s...beans.dtd">
<beans>
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyP laceholderConfigurer">
<property name="location"><value>jdbc.properties</value></property>
</bean>

<!-- Local DataSource that works in any environment -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerD ataSource">
<property name="driverClassName"><value>${jdbc.driverClassName}</value></property>
<property name="url"><value>${jdbc.url}</value></property>
<property name="username"><value>${jdbc.username}</value></property>
<property name="password"><value>${jdbc.password}</value></property>
</bean>

<!-- Hibernate SessionFactory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFact oryBean">
<property name="dataSource"><ref local="dataSource"/></property>
<property name="mappingResources">
<value>composite.hbm.xml</value>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>

<!-- Transaction manager for a single Hibernate SessionFactory (alternative to JTA) -->
<bean id="transactionManager" class="org.springframework.orm.hibernate.HibernateTransac tionManager">
<property name="sessionFactory"><ref local="sessionFactory"/></property>
</bean>


<bean id="compositeTarget" class="example.framework.persistent.CompositePMImpl">
<property name="sessionFactory"><ref local="sessionFactory"/></property>
</bean>

<bean id="proxy" class="org.springframework.transaction.interceptor.Transa ctionProxyFactoryBean">
<property name="transactionManager"><ref local="transactionManager"/></property>
<property name="target"><ref local="compositeTarget"/></property>
<property name="transactionAttributes">
<props>
<prop key="store*">PROPAGATION_REQUIRED</prop>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>

</beans>


------------- CompositeModel.java --------------------
package example.framework.model;

import java.util.Iterator;
import java.util.Set;

public class CompositeModel {
private int m_nId = 0;
private int m_nParentId = 0;
private String m_sName = null;
private String m_sDescription = null;
private CompositeModel m_parent = null;
private Set m_children = null;

public int getId() {
return m_nId;
}

public void setId(int m_nId) {
this.m_nId = m_nId;
}

public int getParentId() {
return m_nParentId;
}

public void setParentId(int m_nParentId) {
this.m_nParentId = m_nParentId;
}

public String getName() {
return m_sName;
}

public void setName(String m_sName) {
this.m_sName = m_sName;
}

public String getDescription() {
return m_sDescription;
}

public void setDescription(String m_sDescription) {
this.m_sDescription = m_sDescription;
}

public CompositeModel getParent() {
return m_parent;
}

public void setParent(CompositeModel m_parent) {
this.m_parent = m_parent;
}

public Set getChildren() {
return m_children;
}

public void setChildren(Set m_children) {
this.m_children = m_children;
}

public String toString() {
final StringBuffer buf = new StringBuffer();
buf.append("CompositeModel");
buf.append("\n\tm_nId=").append(m_nId);
buf.append("\n\tm_nParent=").append(m_nParentId);
buf.append("\n\tm_sName=").append(m_sName);
buf.append("\n\tm_sDescription=").append(m_sDescription);
buf.append("\n\tm_parent=").append(m_parent == null ? null : m_parent.toString());

Set children = getChildren();
if (children == null)
buf.append("\n\tHas no children");
else {
buf.append("\n\tNumber of children = " + children.size());
buf.append("\n\t{");
for (Iterator i = children.iterator(); i.hasNext();) {
CompositeModel com = (CompositeModel) i.next();
buf.append(com.toString());
}
buf.append("\n\t}");
}

buf.append("\n\t------------------");
return buf.toString();
}
}



---------CompositePM---------------
package example.framework.persistent;

import example.framework.model.CompositeModel;
import org.springframework.dao.DataAccessException;

import java.util.List;

public interface CompositePM {
public List listComposite();
public CompositeModel findComposite(int nId);
public void storeComposite(CompositeModel composite) throws DataAccessException;
public void updateComposite(CompositeModel composite) throws DataAccessException;
public void deleteComposite(CompositeModel composite) throws DataAccessException;
}


------CompositePMImpl---------------
package example.framework.persistent;

import example.framework.model.CompositeModel;
import org.springframework.dao.DataAccessException;
import org.springframework.orm.hibernate.support.Hibernat eDaoSupport;

import java.util.List;

public class CompositePMImpl extends HibernateDaoSupport implements CompositePM {
public List listComposite() {
return getHibernateTemplate().find("from CompositeModel AS composite");
}

public CompositeModel findComposite(int nId) {
return (CompositeModel) getHibernateTemplate().load(CompositeModel.class, new Integer(nId));
}

public void storeComposite(CompositeModel composite) throws DataAccessException {
getHibernateTemplate().save(composite);
throw new DataAccessException("exception") {};
}

public void updateComposite(CompositeModel composite) throws DataAccessException {
getHibernateTemplate().update(composite);
}

public void deleteComposite(CompositeModel composite) throws DataAccessException {
getHibernateTemplate().delete(composite);
}
}



package example.framework;

import example.framework.model.CompositeModel;
import example.framework.persistent.CompositePM;
import net.sf.hibernate.HibernateException;
import org.springframework.context.support.ClassPathXmlAp plicationContext;

import java.util.ArrayList;
import java.util.List;

public class TestFramework {

private ClassPathXmlApplicationContext ac = null;
private CompositePM composite = null;

public void initFramework() {
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
composite = (CompositePM) ac.getBean("compositeTarget");
}

private void printComposite(CompositeModel composite) {
System.out.println(composite);
}

private void printComposite(List composites) {
for (int i=0; i<composites.size(); i++)
printComposite((CompositeModel) composites.get(i));
}

public List listAllComposite() {
return composite.listComposite();
}

public CompositeModel findComposite(int nId) {
return composite.findComposite(nId);
}

public void insertComposite(CompositeModel composite) throws HibernateException {
this.composite.storeComposite(composite);
}

public void performTest() throws HibernateException {
// select composite
List list = new ArrayList();
CompositeModel com = findComposite(1);
list.add(com);
printComposite(list);

CompositeModel c = null;
// insert successfully
c = new CompositeModel();
c.setId(10);
c.setParentId(2);
c.setName("new composite");
c.setDescription("Description");
composite.storeComposite(c);
}

public static void main(String[] agrs) throws HibernateException {
TestFramework tf = new TestFramework();

tf.initFramework();
tf.performTest();
}
}

Alef Arendsen
Dec 6th, 2004, 05:29 AM
It seems you're retrieving the target instead of the proxy here:


composite = (CompositePM) ac.getBean("compositeTarget");


Change this to


composite = (CompositePM) ac.getBean("proxy");


and you should be just fine...

regards,
Alef