1 22 package org.jboss.ejb3.tx; 23 24 import javax.ejb.EJBException ; 25 import javax.transaction.Status ; 26 import javax.transaction.SystemException ; 27 import javax.transaction.Transaction ; 28 import javax.transaction.TransactionManager ; 29 import org.jboss.aop.advice.Interceptor; 30 import org.jboss.aop.joinpoint.Invocation; 31 import org.jboss.aop.util.PayloadKey; 32 import org.jboss.ejb3.Container; 33 import org.jboss.ejb3.EJBContainerInvocation; 34 import org.jboss.ejb3.stateful.StatefulBeanContext; 35 import org.jboss.logging.Logger; 36 import org.jboss.tm.TxUtils; 37 38 45 public class BMTInterceptor implements Interceptor 46 { 47 private TransactionManager tm; 48 private boolean isStateless; 49 protected static Logger log = Logger.getLogger(BMTInterceptor.class); 50 51 public BMTInterceptor(TransactionManager tm, boolean stateless) 52 { 53 this.tm = tm; 54 isStateless = stateless; 55 } 56 57 58 public String getName() 59 { 60 return BMTInterceptor.class.getName(); 61 } 62 63 64 65 public Object handleStateless(Invocation invocation) throws Throwable 66 { 67 Container container = (Container)invocation.getAdvisor(); 68 boolean exceptionThrown = false; 69 try 70 { 71 return invocation.invokeNext(); 72 } 73 catch (Exception ex) 74 { 75 exceptionThrown = true; 76 checkStatelessDone(container, ex); 77 throw ex; 78 } 79 finally 80 { 81 try 82 { 83 if (!exceptionThrown) checkStatelessDone(container, null); 84 } 85 finally 86 { 87 tm.suspend(); 88 } 89 } 90 } 91 92 public Object handleStateful(Invocation invocation) throws Throwable 93 { 94 EJBContainerInvocation ejb = (EJBContainerInvocation)invocation; 95 Container container = (Container)invocation.getAdvisor(); 96 97 StatefulBeanContext ctx = (StatefulBeanContext)ejb.getBeanContext(); 98 Transaction tx = (Transaction )ctx.getMetaData().getMetaData("TX", "TX"); 99 if (tx != null) 100 { 101 ctx.getMetaData().addMetaData("TX", "TX", null, PayloadKey.TRANSIENT); 102 tm.resume(tx); 103 } 104 try 105 { 106 return invocation.invokeNext(); 107 } 108 finally 109 { 110 checkBadStateful(container); 111 Transaction newTx = tm.getTransaction(); 112 if (newTx != null) 113 { 114 ctx.getMetaData().addMetaData("TX", "TX", newTx, PayloadKey.TRANSIENT); 115 tm.suspend(); 116 } 117 else 118 { 119 ctx.getMetaData().addMetaData("TX", "TX", null, PayloadKey.TRANSIENT); 120 } 121 } 122 } 123 124 public Object invoke(Invocation invocation) throws Throwable 125 { 126 Transaction oldTx = tm.getTransaction(); 127 if (oldTx != null) tm.suspend(); 128 129 try 130 { 131 if (isStateless) return handleStateless(invocation); 132 else return handleStateful(invocation); 133 } 134 finally 135 { 136 if (oldTx != null) tm.resume(oldTx); 137 } 138 139 140 } 141 142 private void checkStatelessDone(Container container, Exception ex) 143 { 144 int status = Status.STATUS_NO_TRANSACTION; 145 146 try 147 { 148 status = tm.getStatus(); 149 } 150 catch (SystemException sex) 151 { 152 log.error("Failed to get status", sex); 153 } 154 155 switch (status) 156 { 157 case Status.STATUS_ACTIVE : 158 case Status.STATUS_COMMITTING : 159 case Status.STATUS_MARKED_ROLLBACK : 160 case Status.STATUS_PREPARING : 161 case Status.STATUS_ROLLING_BACK : 162 try 163 { 164 tm.rollback(); 165 } 166 catch (Exception sex) 167 { 168 log.error("Failed to rollback", sex); 169 } 170 case Status.STATUS_PREPARED : 172 String msg = "Application error: BMT stateless bean " + container.getEjbName() 173 + " should complete transactions before" + " returning (ejb1.1 spec, 11.6.1)"; 174 log.error(msg); 175 176 if (ex != null) 178 { 179 if (ex instanceof EJBException ) 180 throw (EJBException )ex; 181 else 182 throw new EJBException (msg, ex); 183 } 184 else throw new EJBException (msg); 185 } 186 } 187 188 private void checkBadStateful(Container container) 189 { 190 int status = Status.STATUS_NO_TRANSACTION; 191 192 try 193 { 194 status = tm.getStatus(); 195 } 196 catch (SystemException ex) 197 { 198 log.error("Failed to get status", ex); 199 } 200 201 switch (status) 202 { 203 case Status.STATUS_COMMITTING : 204 case Status.STATUS_MARKED_ROLLBACK : 205 case Status.STATUS_PREPARING : 206 case Status.STATUS_ROLLING_BACK : 207 try 208 { 209 tm.rollback(); 210 } 211 catch (Exception ex) 212 { 213 log.error("Failed to rollback", ex); 214 } 215 String msg = "BMT stateful bean '" + container.getEjbName() 216 + "' did not complete user transaction properly status=" + TxUtils.getStatusAsString(status); 217 log.error(msg); 218 } 219 } 220 221 222 } 223 | Popular Tags |