1 package org.hibernate.transaction; 3 4 import javax.naming.InitialContext ; 5 import javax.naming.NamingException ; 6 import javax.transaction.Status ; 7 import javax.transaction.Synchronization ; 8 import javax.transaction.SystemException ; 9 import javax.transaction.UserTransaction ; 10 11 import org.apache.commons.logging.Log; 12 import org.apache.commons.logging.LogFactory; 13 import org.hibernate.AssertionFailure; 14 import org.hibernate.HibernateException; 15 import org.hibernate.Transaction; 16 import org.hibernate.TransactionException; 17 import org.hibernate.jdbc.JDBCContext; 18 import org.hibernate.util.JTAHelper; 19 20 33 public class JTATransaction implements Transaction { 34 35 private static final Log log = LogFactory.getLog(JTATransaction.class); 36 37 private final JDBCContext jdbcContext; 38 private final TransactionFactory.Context transactionContext; 39 40 private UserTransaction ut; 41 private boolean newTransaction; 42 private boolean begun; 44 private boolean commitFailed; 45 private boolean callback; 46 private javax.transaction.Transaction transaction; 47 48 public JTATransaction(JDBCContext jdbcContext, TransactionFactory.Context transactionContext) { 49 this.jdbcContext = jdbcContext; 50 this.transactionContext = transactionContext; 51 } 52 53 public void begin(InitialContext context, String utName) throws HibernateException { 54 log.debug("begin"); 55 56 log.debug("Looking for UserTransaction under: " + utName); 57 try { 58 ut = (UserTransaction ) context.lookup(utName); 59 } 60 catch (NamingException ne) { 61 log.error("Could not find UserTransaction in JNDI", ne); 62 throw new TransactionException("Could not find UserTransaction in JNDI: ", ne); 63 } 64 if (ut==null) { 65 throw new AssertionFailure("A naming service lookup returned null"); 66 } 67 68 log.debug("Obtained UserTransaction"); 69 70 try { 71 newTransaction = ut.getStatus() == Status.STATUS_NO_TRANSACTION; 72 if (newTransaction) { 73 ut.begin(); 74 log.debug("Began a new JTA transaction"); 75 } 76 } 77 catch (Exception e) { 78 log.error("JTA transaction begin failed", e); 79 throw new TransactionException("JTA transaction begin failed", e); 80 } 81 82 88 89 boolean synchronization = jdbcContext.registerSynchronizationIfPossible(); 90 91 if ( !newTransaction && !synchronization ) { 92 log.warn("You should set hibernate.transaction.manager_lookup_class if cache is enabled"); 93 } 94 95 if (!synchronization) { 96 callback = jdbcContext.registerCallbackIfNecessary(); 103 } 104 105 begun = true; 106 } 107 108 public void commit() throws HibernateException { 109 if (!begun) { 110 throw new TransactionException("Transaction not successfully started"); 111 } 112 113 log.debug("commit"); 114 115 boolean flush = !transactionContext.isFlushModeNever() 116 && ( callback || !transactionContext.isFlushBeforeCompletionEnabled() ); 117 118 if (flush) { 119 transactionContext.managedFlush(); } 121 122 if (callback && newTransaction) { 123 jdbcContext.beforeTransactionCompletion(this); 124 } 125 126 closeIfRequired(); 127 128 if (newTransaction) { 129 try { 130 ut.commit(); 131 log.debug("Committed JTA UserTransaction"); 132 } 133 catch (Exception e) { 134 commitFailed = true; log.error("JTA commit failed", e); 136 throw new TransactionException("JTA commit failed: ", e); 137 } 138 finally { 139 afterCommitRollback(); 140 } 141 } 142 else { 143 afterCommitRollback(); 148 } 149 150 } 151 152 public void rollback() throws HibernateException { 153 if (!begun) { 154 throw new TransactionException("Transaction not successfully started"); 155 } 156 157 log.debug("rollback"); 158 159 162 163 try { 164 closeIfRequired(); 165 } 166 catch (Exception e) { 167 log.error("could not close session during rollback", e); 168 } 170 171 try { 172 if (newTransaction) { 173 if (!commitFailed) { 174 ut.rollback(); 175 log.debug("Rolled back JTA UserTransaction"); 176 } 177 } 178 else { 179 ut.setRollbackOnly(); 180 log.debug("set JTA UserTransaction to rollback only"); 181 } 182 } 183 catch (Exception e) { 184 log.error("JTA rollback failed", e); 185 throw new TransactionException("JTA rollback failed", e); 186 } 187 finally { 188 afterCommitRollback(); 189 } 190 } 191 192 private static final int NULL = Integer.MIN_VALUE; 193 194 private void afterCommitRollback() throws TransactionException { 195 196 if (callback) { 198 if (!newTransaction) log.warn("You should set hibernate.transaction.manager_lookup_class if cache is enabled"); 199 int status=NULL; 200 try { 201 status = ut.getStatus(); 202 } 203 catch (Exception e) { 204 log.error("Could not determine transaction status after commit", e); 205 throw new TransactionException("Could not determine transaction status after commit", e); 206 } 207 finally { 208 212 jdbcContext.afterTransactionCompletion(status==Status.STATUS_COMMITTED, this); 213 } 214 215 } 216 } 217 218 public boolean wasRolledBack() throws TransactionException { 219 220 if (!begun) return false; 221 if (commitFailed) return true; 222 223 final int status; 224 try { 225 status = ut.getStatus(); 226 } 227 catch (SystemException se) { 228 log.error("Could not determine transaction status", se); 229 throw new TransactionException("Could not determine transaction status", se); 230 } 231 if (status==Status.STATUS_UNKNOWN) { 232 throw new TransactionException("Could not determine transaction status"); 233 } 234 else { 235 return JTAHelper.isRollback(status); 236 } 237 } 238 239 public boolean wasCommitted() throws TransactionException { 240 241 if (!begun || commitFailed) return false; 242 243 final int status; 244 try { 245 status = ut.getStatus(); 246 } 247 catch (SystemException se) { 248 log.error("Could not determine transaction status", se); 249 throw new TransactionException("Could not determine transaction status: ", se); 250 } 251 if (status==Status.STATUS_UNKNOWN) { 252 throw new TransactionException("Could not determine transaction status"); 253 } 254 else { 255 return status==Status.STATUS_COMMITTED; 256 } 257 } 258 259 public boolean isActive() throws TransactionException { 260 261 if (!begun || commitFailed) return false; 262 263 final int status; 264 try { 265 status = ut.getStatus(); 266 } 267 catch (SystemException se) { 268 log.error("Could not determine transaction status", se); 269 throw new TransactionException("Could not determine transaction status: ", se); 270 } 271 if (status==Status.STATUS_UNKNOWN) { 272 throw new TransactionException("Could not determine transaction status"); 273 } 274 else { 275 return status==Status.STATUS_ACTIVE; 276 } 277 } 278 279 public void registerSynchronization(Synchronization sync) throws HibernateException { 280 if (transaction!=null) { 281 try { 282 transaction.registerSynchronization(sync); 283 } 284 catch (Exception e) { 285 throw new TransactionException("could not register
|