How to configure RetryAdvice and ExceptionTranslation for Deadlocks using NHibernate and Spring
i am using Spring.net 1.2 with NHibernate 2.0.1.
Within my project i'am facing some Deadlock issues and besides the database tweaks to minimize the occurence i would like to implement Springs RetryAdvice to handle this. I can't find any working example how to configure a this. The reference seems to be clear about how to use it but somehow i can't get it working.<!--Used to translate NHibernate exception to Spring.DataAccessExceptions-->
<object type="Spring.Dao.Attributes.PersistenceExceptionTranslationPostProcessor, Spring.Data"/>
<!--ExceptionHandler performing Retry on Deadlocks-->
<object name="ExceptionHandlingAdvice" type="Spring.Aspects.RetryAdvice, Spring.Aop">
<property name="retryExpression" value="on exception name DeadLockLoserException retry 3x rate (1*#n + 0.5)"/>
</object>
I have added the [Repository] attribute to my DAOs to get ExceptionTranslation enabled and tried to add the RetryAdvice to the TransactionProxyFactoryObject i am using but it won't work. I don't understand where to put this Advice. Do i have to declare a PointCut to add it or how could i get it to work as expected.
Thx in advance 开发者_如何学运维- any help appreciated.
After 1 and a half month of waiting for someone solving my problem i finally found time to elaborate the solution for this by myself. In fact it wasn't that difficult i thought it was. Maybe thats why i wasn't able to find any good example. So here we go: The following test will show the usage:
Configuration: (SessionFactory and TransactionManager etc. omitted for brevity)
<!-- Retries the Tx after DeadlockExceptions -->
<object name="ExceptionHandlingAdvice" type="Spring.Aspects.RetryAdvice, Spring.Aop">
<property name="retryExpression" value="on exception name DeadlockLoserDataAccessException retry 3x delay 1s"/>
</object>
<!--A Transaction-Configuration for our DAO-MOCK-->
<object id="TxProxyConfigurationTemplate" abstract="true" type="Spring.Transaction.Interceptor.TransactionProxyFactoryObject, Spring.Data">
<property name="PlatformTransactionManager" ref="HibernateTransactionManager"/>
<property name="TransactionAttributes">
<name-values>
<add key="ThrowDeadLock*" value="PROPAGATION_REQUIRED"/>
</name-values>
</property>
</object>
<object id="MockDaoTxPFO" parent="TxProxyConfigurationTemplate">
<property name="Target" ref="MockDao"/>
</object>
<!--The ProxyFactoryObject based on the DAO-Mock interface-->
<object id="MockDao" type="Spring.Aop.Framework.ProxyFactoryObject, Spring.Aop" >
<property name="proxyInterfaces" value="RetryAdvice.IDaoMock"/>
<property name="target" ref="MockDaoImpl"/>
<property name="interceptorNames">
<list>
<value>ExceptionHandlingAdvice</value>
</list>
</property>
</object>
<!--Mocked DAO Implementation -->
<object id="MockDaoImpl" type="RetryAdvice.DaoMock, RetryAdvice">
<constructor-arg name="maxExceptionCount" value="2" />
</object>
Mocked Dao: This DAO will throw DeadLockLooserExceptions twice and then pass.
public interface IDaoMock
{
void ThrowDeadLock();
int MethodCallCount { get; }
}
[Repository]
public class DaoMock : IDaoMock
{
private int maxExceptionCount;
public int MethodCallCount { get; private set; }
public DaoMock(int maxExceptionCount)
{
this.maxExceptionCount = maxExceptionCount;
}
public void ThrowDeadLock()
{
MethodCallCount++;
if (MethodCallCount <= maxExceptionCount)
{
throw new DeadlockLoserDataAccessException("FAKE", new HibernateException("This is a fake Exception.", null));
}
}
The Test:
[Test]
public void RetryAdviceTest()
{
IDaoMock mockDao = (IDaoMock)this.appContext.GetObject("MockDaoTxPFO");
mockDao.ThrowDeadLock();
Assert.That(mockDao.MethodCallCount, Is.EqualTo(3));
}
Any hints or remarks appreciated.
精彩评论