1 22 package org.jboss.aspects.tx; 23 24 import java.util.ArrayList ; 25 import java.util.Random ; 26 import java.util.StringTokenizer ; 27 import javax.transaction.HeuristicMixedException ; 28 import javax.transaction.HeuristicRollbackException ; 29 import javax.transaction.RollbackException ; 30 import javax.transaction.Status ; 31 import javax.transaction.SystemException ; 32 import javax.transaction.Transaction ; 33 import javax.transaction.TransactionManager ; 34 import org.jboss.aop.joinpoint.Invocation; 35 import org.jboss.logging.Logger; 36 import org.jboss.util.deadlock.ApplicationDeadlockException; 37 38 39 51 52 public class TxPolicy 53 { 54 protected final static Logger log = Logger.getLogger(TxPolicy.class); 55 56 public static int MAX_RETRIES = 5; 57 public static Random random = new Random (); 58 59 public void throwMandatory(Invocation invocation) 60 { 61 throw new RuntimeException ("Transaction is mandatory."); 62 } 63 64 public Object invokeInNoTx(Invocation invocation) throws Throwable 65 { 66 return invocation.invokeNext(); 67 } 68 69 public Object invokeInOurTx(Invocation invocation, TransactionManager tm) throws Throwable 70 { 71 for (int i = 0; i < MAX_RETRIES; i++) 72 { 73 tm.begin(); 74 Transaction tx = tm.getTransaction(); 75 try 76 { 77 try 78 { 79 return invocation.invokeNext(); 80 } 81 catch (Throwable t) 82 { 83 handleExceptionInOurTx(invocation, t, tx); 84 } 85 finally 86 { 87 endTransaction(tm, tx); 88 } 89 } 90 catch (Exception ex) 91 { 92 ApplicationDeadlockException deadlock = ApplicationDeadlockException.isADE(ex); 93 if (deadlock != null) 94 { 95 if (!deadlock.retryable() || 96 i + 1 >= MAX_RETRIES) 97 { 98 throw deadlock; 99 } 100 log.warn(deadlock.getMessage() + " retrying " + (i + 1)); 101 102 Thread.sleep(random.nextInt(1 + i), random.nextInt(1000)); 103 } 104 else 105 { 106 throw ex; 107 } 108 } 109 } 110 throw new RuntimeException ("UNREACHABLE"); 111 } 112 113 public void handleExceptionInOurTx(Invocation invocation, Throwable t, Transaction tx) 114 throws Throwable 115 { 116 rethrowApplicationException(invocation, t); 118 setRollbackOnly(tx); 119 throw t; 120 } 121 122 public Object invokeInCallerTx(Invocation invocation, Transaction tx) throws Throwable 123 { 124 try 125 { 126 return invocation.invokeNext(); 127 } 128 catch (Throwable t) 129 { 130 handleInCallerTx(invocation, t, tx); 131 } 132 throw new RuntimeException ("UNREACHABLE"); 133 } 134 135 public void handleInCallerTx(Invocation invocation, Throwable t, Transaction tx) 136 throws Throwable 137 { 138 rethrowApplicationException(invocation, t); 139 setRollbackOnly(tx); 140 throw t; 141 } 142 143 156 public void endTransaction(TransactionManager tm, Transaction tx) 157 { 158 try 159 { 160 if (tx != tm.getTransaction()) 161 { 162 throw new IllegalStateException ("Wrong tx on thread: expected " + tx + ", actual " + tm.getTransaction()); 163 } 164 165 if (tx.getStatus() == Status.STATUS_MARKED_ROLLBACK) 166 { 167 tm.rollback(); 168 } 169 else 170 { 171 tm.commit(); 176 } 177 } 178 catch (RollbackException e) 179 { 180 handleEndTransactionException(e); 181 } 182 catch (HeuristicMixedException e) 183 { 184 handleEndTransactionException(e); 185 } 186 catch (HeuristicRollbackException e) 187 { 188 handleEndTransactionException(e); 189 } 190 catch (SystemException e) 191 { 192 handleEndTransactionException(e); 193 } 194 } 195 196 public void handleEndTransactionException(Exception e) 197 { 198 throw new RuntimeException (e); 199 } 200 201 208 public void setRollbackOnly(Transaction tx) 209 { 210 try 211 { 212 tx.setRollbackOnly(); 213 } 214 catch (SystemException ex) 215 { 216 log.error("SystemException while setting transaction " + 217 "for rollback only", ex); 218 } 219 catch (IllegalStateException ex) 220 { 221 log.error("IllegalStateException while setting transaction " + 222 "for rollback only", ex); 223 } 224 } 225 226 234 public void rethrowApplicationException(Invocation inv, Throwable e) throws Throwable 235 { 236 Object applicationExceptions = inv.getMetaData("transaction", "application-exceptions"); 237 if (applicationExceptions == null) return; 238 Class [] applicationExceptionsList; 239 if (applicationExceptions instanceof String ) 240 { 241 ArrayList tmpList = new ArrayList (); 242 String aes = (String ) applicationExceptions; 243 aes = aes.trim(); 244 StringTokenizer tokenizer = new StringTokenizer (aes, ","); 245 while (tokenizer.hasMoreTokens()) 246 { 247 String token = tokenizer.nextToken().trim(); 248 Class excClass = Thread.currentThread().getContextClassLoader().loadClass(token); 249 tmpList.add(excClass); 250 } 251 applicationExceptionsList = (Class []) tmpList.toArray(new Class [tmpList.size()]); 252 } 253 else 254 { 255 applicationExceptionsList = (Class []) applicationExceptions; 256 } 257 for (int i = 0; i < applicationExceptionsList.length; i++) 258 { 259 if (applicationExceptionsList[i].isInstance(e)) throw e; 260 } 261 262 } 263 264 } 265 | Popular Tags |