Package org.jboss.ejb.plugins

Source Code of org.jboss.ejb.plugins.TxInterceptorCMT

/*     */ package org.jboss.ejb.plugins;
/*     */
/*     */ import java.lang.reflect.Method;
/*     */ import java.rmi.RemoteException;
/*     */ import java.util.ArrayList;
/*     */ import java.util.Iterator;
/*     */ import java.util.Map;
/*     */ import java.util.Random;
/*     */ import javax.ejb.EJBException;
/*     */ import javax.ejb.TransactionRequiredLocalException;
/*     */ import javax.transaction.HeuristicMixedException;
/*     */ import javax.transaction.HeuristicRollbackException;
/*     */ import javax.transaction.RollbackException;
/*     */ import javax.transaction.SystemException;
/*     */ import javax.transaction.Transaction;
/*     */ import javax.transaction.TransactionManager;
/*     */ import javax.transaction.TransactionRequiredException;
/*     */ import javax.transaction.TransactionRolledbackException;
/*     */ import org.jboss.ejb.Container;
/*     */ import org.jboss.invocation.Invocation;
/*     */ import org.jboss.invocation.InvocationType;
/*     */ import org.jboss.logging.Logger;
/*     */ import org.jboss.metadata.ApplicationMetaData;
/*     */ import org.jboss.metadata.BeanMetaData;
/*     */ import org.jboss.metadata.MetaData;
/*     */ import org.jboss.metadata.XmlLoadable;
/*     */ import org.jboss.tm.JBossTransactionRolledbackException;
/*     */ import org.jboss.tm.JBossTransactionRolledbackLocalException;
/*     */ import org.jboss.tm.TransactionTimeoutConfiguration;
/*     */ import org.jboss.util.NestedException;
/*     */ import org.jboss.util.deadlock.ApplicationDeadlockException;
/*     */ import org.w3c.dom.Element;
/*     */
/*     */ public class TxInterceptorCMT extends AbstractTxInterceptor
/*     */   implements XmlLoadable
/*     */ {
/*  71 */   public static int MAX_RETRIES = 5;
/*  72 */   public static Random random = new Random();
/*     */
/*  80 */   private boolean exceptionRollback = true;
/*     */
/*  82 */   private TxRetryExceptionHandler[] retryHandlers = null;
/*     */
/*     */   public static ApplicationDeadlockException isADE(Throwable t)
/*     */   {
/*  92 */     while (t != null)
/*     */     {
/*  94 */       if ((t instanceof ApplicationDeadlockException))
/*     */       {
/*  96 */         return (ApplicationDeadlockException)t;
/*     */       }
/*  98 */       if ((t instanceof RemoteException))
/*     */       {
/* 100 */         t = ((RemoteException)t).detail; continue;
/*     */       }
/* 102 */       if ((t instanceof EJBException))
/*     */       {
/* 104 */         t = ((EJBException)t).getCausedByException(); continue;
/*     */       }
/*     */
/* 108 */       return null;
/*     */     }
/*     */
/* 111 */     return null;
/*     */   }
/*     */
/*     */   public void importXml(Element ielement)
/*     */   {
/*     */     try
/*     */     {
/* 124 */       Element element = MetaData.getOptionalChild(ielement, "retry-handlers");
/* 125 */       if (element == null) return;
/* 126 */       ArrayList list = new ArrayList();
/* 127 */       Iterator handlers = MetaData.getChildrenByTagName(element, "handler");
/* 128 */       while (handlers.hasNext())
/*     */       {
/* 130 */         Element handler = (Element)handlers.next();
/* 131 */         String className = MetaData.getElementContent(handler).trim();
/* 132 */         Class clazz = SecurityActions.getContextClassLoader().loadClass(className);
/* 133 */         list.add(clazz.newInstance());
/*     */       }
/* 135 */       this.retryHandlers = ((TxRetryExceptionHandler[])(TxRetryExceptionHandler[])list.toArray(new TxRetryExceptionHandler[list.size()]));
/*     */     }
/*     */     catch (Exception ex)
/*     */     {
/* 139 */       this.log.warn("Unable to importXml for the TxInterceptorCMT", ex);
/*     */     }
/*     */   }
/*     */
/*     */   public void create()
/*     */     throws Exception
/*     */   {
/* 147 */     super.create();
/* 148 */     BeanMetaData bmd = getContainer().getBeanMetaData();
/* 149 */     this.exceptionRollback = bmd.getExceptionRollback();
/* 150 */     if (!this.exceptionRollback)
/* 151 */       this.exceptionRollback = bmd.getApplicationMetaData().getExceptionRollback();
/*     */   }
/*     */
/*     */   public Object invokeHome(Invocation invocation) throws Exception
/*     */   {
/* 156 */     Transaction oldTransaction = invocation.getTransaction();
/* 157 */     for (int i = 0; i < MAX_RETRIES; i++)
/*     */     {
/*     */       try
/*     */       {
/* 161 */         return runWithTransactions(invocation);
/*     */       }
/*     */       catch (Exception ex)
/*     */       {
/* 165 */         checkRetryable(i, ex, oldTransaction);
/*     */       }
/*     */     }
/* 168 */     throw new RuntimeException("Unreachable");
/*     */   }
/*     */
/*     */   public Object invoke(Invocation invocation)
/*     */     throws Exception
/*     */   {
/* 176 */     Transaction oldTransaction = invocation.getTransaction();
/* 177 */     for (int i = 0; i < MAX_RETRIES; i++)
/*     */     {
/*     */       try
/*     */       {
/* 181 */         return runWithTransactions(invocation);
/*     */       }
/*     */       catch (Exception ex)
/*     */       {
/* 185 */         checkRetryable(i, ex, oldTransaction);
/*     */       }
/*     */     }
/* 188 */     throw new RuntimeException("Unreachable");
/*     */   }
/*     */
/*     */   private void checkRetryable(int i, Exception ex, Transaction oldTransaction)
/*     */     throws Exception
/*     */   {
/* 195 */     if ((i + 1 >= MAX_RETRIES) || (oldTransaction != null)) throw ex;
/*     */
/* 197 */     ApplicationDeadlockException deadlock = isADE(ex);
/* 198 */     if (deadlock != null)
/*     */     {
/* 200 */       if (!deadlock.retryable()) throw deadlock;
/* 201 */       this.log.debug(deadlock.getMessage() + " retrying tx " + (i + 1));
/*     */     }
/* 203 */     else if (this.retryHandlers != null)
/*     */     {
/* 205 */       boolean retryable = false;
/* 206 */       for (int j = 0; j < this.retryHandlers.length; j++)
/*     */       {
/* 208 */         retryable = this.retryHandlers[j].retry(ex);
/* 209 */         if (retryable) break;
/*     */       }
/* 211 */       if (!retryable) throw ex;
/* 212 */       this.log.debug(ex.getMessage() + " retrying tx " + (i + 1));
/*     */     }
/*     */     else
/*     */     {
/* 216 */       throw ex;
/*     */     }
/* 218 */     Thread.sleep(random.nextInt(1 + i), random.nextInt(1000));
/*     */   }
/*     */
/*     */   private void printMethod(Method m, byte type)
/*     */   {
/*     */     String txName;
/* 226 */     switch (type)
/*     */     {
/*     */     case 4:
/* 229 */       txName = "TX_MANDATORY";
/* 230 */       break;
/*     */     case 5:
/* 232 */       txName = "TX_NEVER";
/* 233 */       break;
/*     */     case 0:
/* 235 */       txName = "TX_NOT_SUPPORTED";
/* 236 */       break;
/*     */     case 1:
/* 238 */       txName = "TX_REQUIRED";
/* 239 */       break;
/*     */     case 3:
/* 241 */       txName = "TX_REQUIRES_NEW";
/* 242 */       break;
/*     */     case 2:
/* 244 */       txName = "TX_SUPPORTS";
/* 245 */       break;
/*     */     default:
/* 247 */       txName = "TX_UNKNOWN";
/*     */     }
/*     */     String methodName;
/*     */     String methodName;
/* 251 */     if (m != null)
/* 252 */       methodName = m.getName();
/*     */     else {
/* 254 */       methodName = "<no method>";
/*     */     }
/* 256 */     if (this.log.isTraceEnabled())
/*     */     {
/* 258 */       if ((m != null) && ((type == 1) || (type == 3)))
/* 259 */         this.log.trace(txName + " for " + methodName + " timeout=" + this.container.getBeanMetaData().getTransactionTimeout(methodName));
/*     */       else
/* 261 */         this.log.trace(txName + " for " + methodName);
/*     */     }
/*     */   }
/*     */
/*     */   private Object runWithTransactions(Invocation invocation)
/*     */     throws Exception
/*     */   {
/* 284 */     Transaction oldTransaction = invocation.getTransaction();
/*     */
/* 286 */     Transaction newTransaction = null;
/*     */
/* 288 */     boolean trace = this.log.isTraceEnabled();
/* 289 */     if (trace) {
/* 290 */       this.log.trace("Current transaction in MI is " + oldTransaction);
/*     */     }
/* 292 */     InvocationType type = invocation.getType();
/* 293 */     byte transType = this.container.getBeanMetaData().getTransactionMethod(invocation.getMethod(), type);
/*     */
/* 295 */     if (trace) {
/* 296 */       printMethod(invocation.getMethod(), transType);
/*     */     }
/*     */
/* 302 */     Transaction threadTx = this.tm.suspend();
/* 303 */     if (trace)
/* 304 */       this.log.trace("Thread came in with tx " + threadTx);
/*     */     try
/*     */     {
/*     */       Object theTransaction;
/*     */       Object result;
/*     */       Object result;
/*     */       Object result;
/* 307 */       switch (transType)
/*     */       {
/*     */       case 0:
/*     */         try
/*     */         {
/* 314 */           invocation.setTransaction(null);
/* 315 */           localObject1 = invokeNext(invocation, false);
/*     */         }
/*     */         finally
/*     */         {
/*     */           Object localObject1;
/* 319 */           invocation.setTransaction(oldTransaction);
/*     */         }
/*     */
/*     */       case 1:
/* 324 */         int oldTimeout = 0;
/* 325 */         theTransaction = oldTransaction;
/* 326 */         if (oldTransaction == null)
/*     */         {
/* 329 */           oldTimeout = startTransaction(invocation);
/*     */
/* 332 */           newTransaction = this.tm.getTransaction();
/* 333 */           if (trace) {
/* 334 */             this.log.trace("Starting new tx " + newTransaction);
/*     */           }
/*     */
/* 337 */           invocation.setTransaction(newTransaction);
/* 338 */           theTransaction = newTransaction;
/*     */         }
/*     */         else
/*     */         {
/* 344 */           this.tm.resume(oldTransaction);
/*     */         }
/*     */
/*     */         try
/*     */         {
/* 350 */           result = invokeNext(invocation, oldTransaction != null);
/* 351 */           checkTransactionStatus((Transaction)theTransaction, type);
/* 352 */           localObject4 = result;
/*     */         }
/*     */         finally
/*     */         {
/*     */           Object localObject4;
/* 356 */           if (trace) {
/* 357 */             this.log.trace("TxInterceptorCMT: In finally");
/*     */           }
/*     */
/* 360 */           if (newTransaction != null)
/* 361 */             endTransaction(invocation, newTransaction, oldTransaction, oldTimeout);
/*     */           else {
/* 363 */             this.tm.suspend();
/*     */           }
/*     */
/*     */         }
/*     */
/*     */       case 2:
/* 371 */         if (oldTransaction != null)
/*     */         {
/* 373 */           this.tm.resume(oldTransaction);
/*     */         }
/*     */
/*     */         try
/*     */         {
/* 378 */           Object result = invokeNext(invocation, oldTransaction != null);
/* 379 */           if (oldTransaction != null)
/* 380 */             checkTransactionStatus(oldTransaction, type);
/* 381 */           theTransaction = result;
/*     */         }
/*     */         finally
/*     */         {
/* 385 */           this.tm.suspend();
/*     */         }
/*     */
/*     */       case 3:
/* 394 */         int oldTimeout = startTransaction(invocation);
/*     */
/* 397 */         newTransaction = this.tm.getTransaction();
/*     */
/* 400 */         invocation.setTransaction(newTransaction);
/*     */         try
/*     */         {
/* 404 */           result = invokeNext(invocation, false);
/* 405 */           checkTransactionStatus(newTransaction, type);
/* 406 */           result = result;
/*     */         }
/*     */         finally
/*     */         {
/* 411 */           endTransaction(invocation, newTransaction, oldTransaction, oldTimeout);
/*     */         }
/*     */
/*     */       case 4:
/* 416 */         if (oldTransaction == null)
/*     */         {
/* 418 */           if ((type == InvocationType.LOCAL) || (type == InvocationType.LOCALHOME))
/*     */           {
/* 421 */             throw new TransactionRequiredLocalException("Transaction Required");
/*     */           }
/*     */
/* 426 */           throw new TransactionRequiredException("Transaction Required");
/*     */         }
/*     */
/* 432 */         this.tm.resume(oldTransaction);
/*     */         try
/*     */         {
/* 435 */           result = invokeNext(invocation, true);
/* 436 */           checkTransactionStatus(oldTransaction, type);
/* 437 */           result = result;
/*     */         }
/*     */         finally
/*     */         {
/* 441 */           this.tm.suspend();
/*     */         }
/*     */
/*     */       case 5:
/* 446 */         if (oldTransaction != null)
/*     */         {
/* 448 */           throw new EJBException("Transaction not allowed");
/*     */         }
/* 450 */         result = invokeNext(invocation, false); jsr 59;
/*     */       }
/*     */
/* 453 */       this.log.error("Unknown TX attribute " + transType + " for method" + invocation.getMethod());
/*     */     }
/*     */     finally
/*     */     {
/* 459 */       if (threadTx != null) {
/* 460 */         this.tm.resume(threadTx);
/*     */       }
/*     */     }
/* 463 */     return null;
/*     */   }
/*     */
/*     */   private int startTransaction(Invocation invocation)
/*     */     throws Exception
/*     */   {
/* 469 */     int oldTimeout = -1;
/* 470 */     if ((this.tm instanceof TransactionTimeoutConfiguration))
/*     */     {
/* 472 */       oldTimeout = ((TransactionTimeoutConfiguration)this.tm).getTransactionTimeout();
/* 473 */       int newTimeout = this.container.getBeanMetaData().getTransactionTimeout(invocation.getMethod());
/* 474 */       this.tm.setTransactionTimeout(newTimeout);
/*     */     }
/* 476 */     this.tm.begin();
/* 477 */     return oldTimeout;
/*     */   }
/*     */
/*     */   private void endTransaction(Invocation invocation, Transaction tx, Transaction oldTx, int oldTimeout)
/*     */     throws TransactionRolledbackException, SystemException
/*     */   {
/* 484 */     Transaction current = this.tm.getTransaction();
/* 485 */     if (((tx == null) && (current != null)) || (!tx.equals(current))) {
/* 486 */       throw new IllegalStateException("Wrong transaction association: expected " + tx + " was " + current);
/*     */     }
/*     */
/*     */     try
/*     */     {
/* 491 */       if (tx.getStatus() == 1)
/*     */       {
/* 493 */         tx.rollback();
/*     */       }
/*     */       else
/*     */       {
/* 501 */         tx.commit();
/*     */       }
/*     */     }
/*     */     catch (RollbackException e)
/*     */     {
/* 506 */       throwJBossException(e, invocation.getType());
/*     */     }
/*     */     catch (HeuristicMixedException e)
/*     */     {
/* 510 */       throwJBossException(e, invocation.getType());
/*     */     }
/*     */     catch (HeuristicRollbackException e)
/*     */     {
/* 514 */       throwJBossException(e, invocation.getType());
/*     */     }
/*     */     catch (SystemException e)
/*     */     {
/* 518 */       throwJBossException(e, invocation.getType());
/*     */     }
/*     */     catch (IllegalStateException e)
/*     */     {
/* 522 */       throwJBossException(e, invocation.getType());
/*     */     }
/*     */     finally
/*     */     {
/* 527 */       invocation.setTransaction(oldTx);
/*     */
/* 536 */       this.tm.suspend();
/*     */
/* 538 */       if (oldTimeout != -1)
/* 539 */         this.tm.setTransactionTimeout(oldTimeout);
/*     */     }
/*     */   }
/*     */
/*     */   protected void throwJBossException(Exception e, InvocationType type)
/*     */     throws TransactionRolledbackException
/*     */   {
/* 558 */     if ((e instanceof NestedException))
/*     */     {
/* 560 */       NestedException rollback = (NestedException)e;
/* 561 */       if ((rollback.getCause() instanceof Exception))
/*     */       {
/* 563 */         e = (Exception)rollback.getCause();
/*     */       }
/*     */     }
/* 566 */     if ((type == InvocationType.LOCAL) || (type == InvocationType.LOCALHOME))
/*     */     {
/* 569 */       throw new JBossTransactionRolledbackLocalException(e);
/*     */     }
/*     */
/* 573 */     throw new JBossTransactionRolledbackException(e);
/*     */   }
/*     */
/*     */   protected void checkTransactionStatus(Transaction tx, InvocationType type)
/*     */     throws TransactionRolledbackException
/*     */   {
/* 590 */     if (this.exceptionRollback)
/*     */     {
/* 592 */       if (this.log.isTraceEnabled())
/* 593 */         this.log.trace("No exception from ejb, checking transaction status: " + tx);
/* 594 */       int status = 5;
/*     */       try
/*     */       {
/* 597 */         status = tx.getStatus();
/*     */       }
/*     */       catch (Throwable t)
/*     */       {
/* 601 */         this.log.debug("Ignored error trying to retrieve transaction status", t);
/*     */       }
/* 603 */       if (status != 0)
/*     */       {
/* 605 */         Exception e = new Exception("Transaction cannot be committed (probably transaction timeout): " + tx);
/* 606 */         throwJBossException(e, type);
/*     */       }
/*     */     }
/*     */   }
/*     */
/*     */   public void sample(Object s)
/*     */   {
/*     */   }
/*     */
/*     */   public Map retrieveStatistic()
/*     */   {
/* 620 */     return null;
/*     */   }
/*     */
/*     */   public void resetStatistic()
/*     */   {
/*     */   }
/*     */ }

/* Location:           /home/mnovotny/projects/EMBEDDED_JBOSS_BETA3_COMMUNITY/embedded/output/lib/embedded-jboss/lib/jboss-embedded-all.jar
* Qualified Name:     org.jboss.ejb.plugins.TxInterceptorCMT
* JD-Core Version:    0.6.0
*/
TOP

Related Classes of org.jboss.ejb.plugins.TxInterceptorCMT

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.