Container interceptors and ApplicationDeadlockException handling.
kieroooo Oct 28, 2013 7:40 AMHi,
I'm migrating an application which was previously working on JBoss 4 to JBoss 7. We had an interceptor which was checking out exceptions returned by database driver and converting them to ApplicationDeadlockException when certain sqlstates were occuring. I changed it to container-level interceptor and the code looks like this:
public class DeadlockInterceptor {
@AroundInvoke
public Object invoke(final InvocationContext mi) throws Exception {
try {
return mi.proceed();
}
catch (Exception e) {
handleDeadlockException(e);
throw e;
}
}
private void handleDeadlockException(Exception e) throws ApplicationDeadlockException {
for (Throwable ex = e; ex != null; ex = ex.getCause()) {
if (ex instanceof ApplicationDeadlockException) {
// no need to keep looking if we already have a ApplicationDeadlockException
throw (ApplicationDeadlockException)ex;
}
if (ex instanceof SQLException) {
String sqlState = DeadlockUtil.extractSqlState((SQLException) ex);
if ("40001".equals(sqlState) || "61000".equals(sqlState/*oracle*/)) {
ApplicationDeadlockException deadlock = new ApplicationDeadlockException("database deadlock", true);
deadlock.initCause(ex);
Logger.warning(this, "Detected a DB serialization failure. This could be a possible SQL Deadlock. Now retry the related transaction up to 5 times.");
throw deadlock;
}
}
}
}
}
This was causing JBoss to retry transaction commit up to 5 times. This functionality is handled in org.jboss.as.ejb3.tx.CMTTxInterceptor (6.1.0.Alpha). Checking the program flow it seems container tries to retry the transaction but it is running into an exception:
javax.ejb.EJBException: org.jboss.invocation.CannotProceedException: INV-00002:Invocation cannot proceed (end of interceptor chain has been hit)
at org.jboss.as.ejb3.tx.CMTTxInterceptor.handleExceptionInOurTx(CMTTxInterceptor.java:165)
at org.jboss.as.ejb3.tx.CMTTxInterceptor.invokeInOurTx(CMTTxInterceptor.java:250)
at org.jboss.as.ejb3.tx.CMTTxInterceptor.required(CMTTxInterceptor.java:315)
at org.jboss.as.ejb3.tx.CMTTxInterceptor.processInvocation(CMTTxInterceptor.java:214)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:289)
at org.jboss.as.ejb3.component.interceptors.CurrentInvocationContextInterceptor.processInvocation(CurrentInvocationContextInterceptor.java:41)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:289)
at org.jboss.invocation.InterceptorContext$Invocation.proceed(InterceptorContext.java:376)
[my interceptor code here]
So my question is is this supposed to work? Retry code is still there but maybe it is just some unmaintained legacy thing? Am i doing something wrong using ApplicationDeadlockException this way? Or maybe there is a different way to approach this problem? Thanks in advance,
Michal Wozniak