scottr
Aug 15th, 2004, 09:16 PM
Hi All,
I am having a problem using the HibernateInterceptor and TransactionInterceptor for declarative transaction demarcation.
Basically, what I am trying to do looks like this:
public class MyService
{
public void A ()
{
// Retrieve data from a DAO
..
// Iterate through a list of entities. Call method B to store each
// entity in the database (in its own transaction)
for (Iterator i = entityList.iterator(); i.hasNext();){
this.B((DataItem) i.next());
}
}
protected void B (DataItem entity)
{
// Load some reference data from the database
..
// Set fields, do some logic
..
// Save entity to the database using a DAO
dao.save(entity);
}
}
I am trying to set up interceptors that will:
a) wrap method A in a hibernate session, thus ensuring that for the duration of a call to A and all sub-methods, the same Hibernate session will be used (ie. an OpenSessionInView style pattern).
b) wrap method B in a hibernate transaction, thus ensuring that for each call to B, a new transaction is used. Any errors that occur within that transaction should cause the transaction to roll-back, but should not affect subsequent calls to B.
The xml configuration file for this service bean looks like this:
<beans>
<bean id="myService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyTargetClass"><value>true</value></property>
<property name="target"><ref local="myServiceTarget"/></property>
<property name="interceptorNames">
<list>
<value>hibernateSessInterceptor</value>
<value>hibernateTxInterceptor</value>
</list>
</property>
</bean>
<bean id="myServiceTarget" class="mypackage.MyService">
<!-- property configurationsdefined here -->
</bean>
<bean id="hibernateSessInterceptor" class="org.springframework.orm.hibernate.HibernateInterce ptor">
<property name="sessionFactory"><ref bean="sessionFactory"/></property>
</bean>
<bean id="hibernateTxInterceptor" class="org.springframework.transaction.interceptor.Transa ctionInterceptor">
<property name="transactionManager"><ref bean="hibernateTxManager"/></property>
<property name="transactionAttributeSource">
<value>mypackage.MyService.B=PROPAGATION_REQUIRED</value>
</property>
</bean>
</beans>
The problem I am having is that upon running this, no data is inserted in the database. It appears that the problem is that no transactions are being opened, and as such the saved data is not being inserted into the database. If an error occurs, the stack trace I get looks something like this:
java.lang.Exception:
... (etc, etc)
at mypackage.MyService.B(MyService.java:92)
at mypackage.MyService.A(MyService.java:70)
at mypackage.MyService$$FastClassByCGLIB$$a36e139c.in voke(<generated>)
at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy. java:149)
at org.springframework.aop.framework.Cglib2AopProxy$M ethodInvocationImpl.invokeJoinpoint(Cglib2AopProxy .java:392)
at org.springframework.aop.framework.ReflectiveMethod Invocation.proceed(ReflectiveMethodInvocation.java :114)
at org.springframework.transaction.interceptor.Transa ctionInterceptor.invoke(TransactionInterceptor.jav a:169)
at org.springframework.aop.framework.ReflectiveMethod Invocation.proceed(ReflectiveMethodInvocation.java :134)
at org.springframework.aop.framework.Cglib2AopProxy.i ntercept(Cglib2AopProxy.java:144)
at mypackage.MyService$$EnhancerByCGLIB$$b02f66a1.A(<generated>)
... (etc, etc)
It appears from this stack trace that only method A is being intercepted by the CGLIB interceptor, and that method B is not being intercepted, hence has no transaction demarcation. Which brings me to my question, which is, what is going wrong with this configuration, that method B is not being intercepted?
Thanks in advance to anyone who might have tips that could help here.
Regards,
Scott Russell
I am having a problem using the HibernateInterceptor and TransactionInterceptor for declarative transaction demarcation.
Basically, what I am trying to do looks like this:
public class MyService
{
public void A ()
{
// Retrieve data from a DAO
..
// Iterate through a list of entities. Call method B to store each
// entity in the database (in its own transaction)
for (Iterator i = entityList.iterator(); i.hasNext();){
this.B((DataItem) i.next());
}
}
protected void B (DataItem entity)
{
// Load some reference data from the database
..
// Set fields, do some logic
..
// Save entity to the database using a DAO
dao.save(entity);
}
}
I am trying to set up interceptors that will:
a) wrap method A in a hibernate session, thus ensuring that for the duration of a call to A and all sub-methods, the same Hibernate session will be used (ie. an OpenSessionInView style pattern).
b) wrap method B in a hibernate transaction, thus ensuring that for each call to B, a new transaction is used. Any errors that occur within that transaction should cause the transaction to roll-back, but should not affect subsequent calls to B.
The xml configuration file for this service bean looks like this:
<beans>
<bean id="myService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyTargetClass"><value>true</value></property>
<property name="target"><ref local="myServiceTarget"/></property>
<property name="interceptorNames">
<list>
<value>hibernateSessInterceptor</value>
<value>hibernateTxInterceptor</value>
</list>
</property>
</bean>
<bean id="myServiceTarget" class="mypackage.MyService">
<!-- property configurationsdefined here -->
</bean>
<bean id="hibernateSessInterceptor" class="org.springframework.orm.hibernate.HibernateInterce ptor">
<property name="sessionFactory"><ref bean="sessionFactory"/></property>
</bean>
<bean id="hibernateTxInterceptor" class="org.springframework.transaction.interceptor.Transa ctionInterceptor">
<property name="transactionManager"><ref bean="hibernateTxManager"/></property>
<property name="transactionAttributeSource">
<value>mypackage.MyService.B=PROPAGATION_REQUIRED</value>
</property>
</bean>
</beans>
The problem I am having is that upon running this, no data is inserted in the database. It appears that the problem is that no transactions are being opened, and as such the saved data is not being inserted into the database. If an error occurs, the stack trace I get looks something like this:
java.lang.Exception:
... (etc, etc)
at mypackage.MyService.B(MyService.java:92)
at mypackage.MyService.A(MyService.java:70)
at mypackage.MyService$$FastClassByCGLIB$$a36e139c.in voke(<generated>)
at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy. java:149)
at org.springframework.aop.framework.Cglib2AopProxy$M ethodInvocationImpl.invokeJoinpoint(Cglib2AopProxy .java:392)
at org.springframework.aop.framework.ReflectiveMethod Invocation.proceed(ReflectiveMethodInvocation.java :114)
at org.springframework.transaction.interceptor.Transa ctionInterceptor.invoke(TransactionInterceptor.jav a:169)
at org.springframework.aop.framework.ReflectiveMethod Invocation.proceed(ReflectiveMethodInvocation.java :134)
at org.springframework.aop.framework.Cglib2AopProxy.i ntercept(Cglib2AopProxy.java:144)
at mypackage.MyService$$EnhancerByCGLIB$$b02f66a1.A(<generated>)
... (etc, etc)
It appears from this stack trace that only method A is being intercepted by the CGLIB interceptor, and that method B is not being intercepted, hence has no transaction demarcation. Which brings me to my question, which is, what is going wrong with this configuration, that method B is not being intercepted?
Thanks in advance to anyone who might have tips that could help here.
Regards,
Scott Russell