1 22 package org.jboss.ejb.plugins; 23 24 import java.util.Hashtable ; 25 26 import java.rmi.RemoteException ; 27 28 import javax.transaction.Transaction ; 29 import javax.transaction.Status ; 30 import javax.transaction.SystemException ; 31 32 import javax.naming.Context ; 33 import javax.naming.InitialContext ; 34 import javax.naming.Name ; 35 import javax.naming.Reference ; 36 import javax.naming.RefAddr ; 37 import javax.naming.spi.ObjectFactory ; 38 39 import org.jboss.ejb.EnterpriseContext; 40 import org.jboss.ejb.AllowedOperationsAssociation; 41 import org.jboss.invocation.Invocation; 42 import org.jboss.tm.TxUtils; 43 44 50 abstract class AbstractTxInterceptorBMT extends AbstractTxInterceptor 51 { 52 54 60 private ThreadLocal userTransaction = new ThreadLocal (); 61 62 68 protected boolean stateless = true; 69 70 72 74 76 78 public void create() throws Exception 79 { 80 super.create(); 82 83 RefAddr refAddr = new RefAddr ("userTransaction") 85 { 86 87 private static final long serialVersionUID = 1L; 88 89 public Object getContent() 90 { 91 return userTransaction; 92 } 93 }; 94 95 Reference ref = new Reference ("javax.transaction.UserTransaction", refAddr, new UserTxFactory().getClass() 96 .getName(), null); 97 ((Context ) new InitialContext ().lookup("java:comp/")).bind("UserTransaction", ref); 98 } 99 100 public void stop() 101 { 102 try 104 { 105 ((Context ) new InitialContext ().lookup("java:comp/")).unbind("UserTransaction"); 106 } 107 catch (Exception e) 108 { 109 } 111 } 112 113 115 130 protected Object invokeNext(Invocation mi) throws Exception 131 { 132 Transaction oldTransaction = mi.getTransaction(); 134 135 Object oldUserTx = userTransaction.get(); 138 139 Transaction threadTx = tm.suspend(); 142 143 try 144 { 145 EnterpriseContext ctx = ((EnterpriseContext) mi.getEnterpriseContext()); 146 147 try 149 { 150 AllowedOperationsAssociation.pushInMethodFlag(IN_INTERCEPTOR_METHOD); 151 userTransaction.set(ctx.getEJBContext().getUserTransaction()); 152 } 153 finally 154 { 155 AllowedOperationsAssociation.popInMethodFlag(); 156 } 157 158 Transaction beanTx = ctx.getTransaction(); 160 161 if (beanTx != null) 164 tm.resume(beanTx); 165 166 mi.setTransaction(beanTx); 168 169 try 170 { 171 return super.invokeNext(mi, false); 174 } 175 finally 176 { 177 try 178 { 179 if (stateless) 180 checkStatelessDone(); 181 else 182 checkBadStateful(); 183 } 184 finally 185 { 186 tm.suspend(); 187 } 188 } 189 } 190 finally 191 { 192 userTransaction.set(oldUserTx); 194 195 mi.setTransaction(oldTransaction); 198 199 if (threadTx != null) 201 tm.resume(threadTx); 202 } 203 } 204 205 private void checkStatelessDone() throws RemoteException 206 { 207 int status = Status.STATUS_NO_TRANSACTION; 208 209 try 210 { 211 status = tm.getStatus(); 212 } 213 catch (SystemException ex) 214 { 215 log.error("Failed to get status", ex); 216 } 217 218 switch (status) 219 { 220 case Status.STATUS_ACTIVE : 221 case Status.STATUS_COMMITTING : 222 case Status.STATUS_MARKED_ROLLBACK : 223 case Status.STATUS_PREPARING : 224 case Status.STATUS_ROLLING_BACK : 225 try 226 { 227 tm.rollback(); 228 } 229 catch (Exception ex) 230 { 231 log.error("Failed to rollback", ex); 232 } 233 case Status.STATUS_PREPARED : 235 String msg = "Application error: BMT stateless bean " + container.getBeanMetaData().getEjbName() 236 + " should complete transactions before" + " returning (ejb1.1 spec, 11.6.1)"; 237 log.error(msg); 238 239 throw new RemoteException (msg); 241 } 242 } 243 244 private void checkBadStateful() throws RemoteException 245 { 246 int status = Status.STATUS_NO_TRANSACTION; 247 248 try 249 { 250 status = tm.getStatus(); 251 } 252 catch (SystemException ex) 253 { 254 log.error("Failed to get status", ex); 255 } 256 257 switch (status) 258 { 259 case Status.STATUS_COMMITTING : 260 case Status.STATUS_MARKED_ROLLBACK : 261 case Status.STATUS_PREPARING : 262 case Status.STATUS_ROLLING_BACK : 263 try 264 { 265 tm.rollback(); 266 } 267 catch (Exception ex) 268 { 269 log.error("Failed to rollback", ex); 270 } 271 String msg = "BMT stateful bean '" + container.getBeanMetaData().getEjbName() 272 + "' did not complete user transaction properly status=" + TxUtils.getStatusAsString(status); 273 log.error(msg); 274 } 275 } 276 277 279 public static class UserTxFactory implements ObjectFactory 280 { 281 public Object getObjectInstance(Object ref, Name name, Context nameCtx, Hashtable environment) throws Exception 282 { 283 RefAddr refAddr = ((Reference ) ref).get(0); 285 ThreadLocal threadLocal = (ThreadLocal ) refAddr.getContent(); 287 288 return threadLocal.get(); 290 } 291 } 292 293 } 294 | Popular Tags |