1 16 17 package org.springframework.orm.ojb; 18 19 import java.sql.Connection ; 20 21 import javax.sql.DataSource ; 22 23 import org.apache.ojb.broker.OJBRuntimeException; 24 import org.apache.ojb.broker.PBKey; 25 import org.apache.ojb.broker.PersistenceBroker; 26 import org.apache.ojb.broker.PersistenceBrokerFactory; 27 import org.apache.ojb.broker.TransactionAbortedException; 28 import org.apache.ojb.broker.accesslayer.LookupException; 29 30 import org.springframework.jdbc.datasource.ConnectionHolder; 31 import org.springframework.jdbc.datasource.DataSourceUtils; 32 import org.springframework.jdbc.datasource.JdbcTransactionObjectSupport; 33 import org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy; 34 import org.springframework.transaction.CannotCreateTransactionException; 35 import org.springframework.transaction.IllegalTransactionStateException; 36 import org.springframework.transaction.TransactionDefinition; 37 import org.springframework.transaction.TransactionSystemException; 38 import org.springframework.transaction.support.AbstractPlatformTransactionManager; 39 import org.springframework.transaction.support.DefaultTransactionStatus; 40 import org.springframework.transaction.support.TransactionSynchronizationManager; 41 42 64 public class PersistenceBrokerTransactionManager extends AbstractPlatformTransactionManager { 65 66 private PBKey pbKey = PersistenceBrokerFactory.getDefaultKey(); 67 68 private DataSource dataSource; 69 70 71 75 public PersistenceBrokerTransactionManager() { 76 } 77 78 83 public PersistenceBrokerTransactionManager(String jcdAlias) { 84 setJcdAlias(jcdAlias); 85 } 86 87 91 public PersistenceBrokerTransactionManager(PBKey pbKey) { 92 setPbKey(pbKey); 93 } 94 95 99 public void setJcdAlias(String jcdAlias) { 100 this.pbKey = new PBKey(jcdAlias); 101 } 102 103 107 public void setPbKey(PBKey pbKey) { 108 this.pbKey = pbKey; 109 } 110 111 114 public PBKey getPbKey() { 115 return pbKey; 116 } 117 118 137 public void setDataSource(DataSource dataSource) { 138 if (dataSource instanceof TransactionAwareDataSourceProxy) { 139 this.dataSource = ((TransactionAwareDataSourceProxy) dataSource).getTargetDataSource(); 143 } 144 else { 145 this.dataSource = dataSource; 146 } 147 } 148 149 152 public DataSource getDataSource() { 153 return dataSource; 154 } 155 156 157 protected Object doGetTransaction() { 158 PersistenceBrokerTransactionObject txObject = new PersistenceBrokerTransactionObject(); 159 PersistenceBrokerHolder pbHolder = 160 (PersistenceBrokerHolder) TransactionSynchronizationManager.getResource(getPbKey()); 161 txObject.setPersistenceBrokerHolder(pbHolder); 162 return txObject; 163 } 164 165 protected boolean isExistingTransaction(Object transaction) { 166 PersistenceBrokerTransactionObject txObject = (PersistenceBrokerTransactionObject) transaction; 167 return (txObject.getPersistenceBrokerHolder() != null); 168 } 169 170 protected void doBegin(Object transaction, TransactionDefinition definition) { 171 if (getDataSource() != null && TransactionSynchronizationManager.hasResource(getDataSource())) { 172 throw new IllegalTransactionStateException( 173 "Pre-bound JDBC Connection found - PersistenceBrokerTransactionManager does not support " + 174 "running within DataSourceTransactionManager if told to manage the DataSource itself. " + 175 "It is recommended to use a single PersistenceBrokerTransactionManager for all transactions " + 176 "on a single DataSource, no matter whether PersistenceBroker or JDBC access."); 177 } 178 179 PersistenceBroker pb = null; 180 181 try { 182 pb = getPersistenceBroker(); 183 if (logger.isDebugEnabled()) { 184 logger.debug("Opened new PersistenceBroker [" + pb + "] for OJB transaction"); 185 } 186 187 PersistenceBrokerTransactionObject txObject = (PersistenceBrokerTransactionObject) transaction; 188 txObject.setPersistenceBrokerHolder(new PersistenceBrokerHolder(pb)); 189 190 Connection con = pb.serviceConnectionManager().getConnection(); 191 Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition); 192 txObject.setPreviousIsolationLevel(previousIsolationLevel); 193 194 pb.beginTransaction(); 195 196 if (getDataSource() != null) { 198 ConnectionHolder conHolder = new ConnectionHolder(con); 199 if (definition.getTimeout() != TransactionDefinition.TIMEOUT_DEFAULT) { 200 conHolder.setTimeoutInSeconds(definition.getTimeout()); 201 } 202 if (logger.isDebugEnabled()) { 203 logger.debug("Exposing OJB transaction as JDBC transaction [" + conHolder.getConnection() + "]"); 204 } 205 TransactionSynchronizationManager.bindResource(getDataSource(), conHolder); 206 txObject.setConnectionHolder(conHolder); 207 } 208 209 TransactionSynchronizationManager.bindResource(getPbKey(), txObject.getPersistenceBrokerHolder()); 211 } 212 213 catch (Exception ex) { 214 releasePersistenceBroker(pb); 215 throw new CannotCreateTransactionException("Could not open OJB PersistenceBroker for transaction", ex); 216 } 217 } 218 219 protected Object doSuspend(Object transaction) { 220 PersistenceBrokerTransactionObject txObject = (PersistenceBrokerTransactionObject) transaction; 221 txObject.setPersistenceBrokerHolder(null); 222 PersistenceBrokerHolder pbHolder = 223 (PersistenceBrokerHolder) TransactionSynchronizationManager.unbindResource(getPbKey()); 224 ConnectionHolder connectionHolder = null; 225 if (getDataSource() != null) { 226 connectionHolder = (ConnectionHolder) TransactionSynchronizationManager.unbindResource(getDataSource()); 227 } 228 return new SuspendedResourcesHolder(pbHolder, connectionHolder); 229 } 230 231 protected void doResume(Object transaction, Object suspendedResources) { 232 SuspendedResourcesHolder resourcesHolder = (SuspendedResourcesHolder) suspendedResources; 233 if (TransactionSynchronizationManager.hasResource(getPbKey())) { 234 TransactionSynchronizationManager.unbindResource(getPbKey()); 237 } 238 TransactionSynchronizationManager.bindResource(getPbKey(), resourcesHolder.getPersistenceBrokerHolder()); 239 if (getDataSource() != null) { 240 TransactionSynchronizationManager.bindResource(getDataSource(), resourcesHolder.getConnectionHolder()); 241 } 242 } 243 244 protected void doCommit(DefaultTransactionStatus status) { 245 PersistenceBrokerTransactionObject txObject = (PersistenceBrokerTransactionObject) status.getTransaction(); 246 if (status.isDebug()) { 247 logger.debug("Committing OJB transaction on PersistenceBroker [" + 248 txObject.getPersistenceBrokerHolder().getPersistenceBroker() + "]"); 249 } 250 try { 251 txObject.getPersistenceBrokerHolder().getPersistenceBroker().commitTransaction(); 252 } 253 catch (TransactionAbortedException ex) { 254 throw new TransactionSystemException("Could not commit OJB transaction", ex); 256 } 257 } 258 259 protected void doRollback(DefaultTransactionStatus status) { 260 PersistenceBrokerTransactionObject txObject = (PersistenceBrokerTransactionObject) status.getTransaction(); 261 if (status.isDebug()) { 262 logger.debug("Rolling back OJB transaction on PersistenceBroker [" + 263 txObject.getPersistenceBrokerHolder().getPersistenceBroker() + "]"); 264 } 265 txObject.getPersistenceBrokerHolder().getPersistenceBroker().abortTransaction(); 266 } 267 268 protected void doSetRollbackOnly(DefaultTransactionStatus status) { 269 PersistenceBrokerTransactionObject txObject = (PersistenceBrokerTransactionObject) status.getTransaction(); 270 if (status.isDebug()) { 271 logger.debug("Setting OJB transaction on PersistenceBroker [" + 272 txObject.getPersistenceBrokerHolder().getPersistenceBroker() + "] rollback-only"); 273 } 274 txObject.setRollbackOnly(); 275 } 276 277 protected void doCleanupAfterCompletion(Object transaction) { 278 PersistenceBrokerTransactionObject txObject = (PersistenceBrokerTransactionObject) transaction; 279 280 TransactionSynchronizationManager.unbindResource(getPbKey()); 282 txObject.getPersistenceBrokerHolder().clear(); 283 284 if (getDataSource() != null) { 286 TransactionSynchronizationManager.unbindResource(getDataSource()); 287 } 288 289 PersistenceBroker pb = txObject.getPersistenceBrokerHolder().getPersistenceBroker(); 290 try { 291 Connection con = pb.serviceConnectionManager().getConnection(); 292 DataSourceUtils.resetConnectionAfterTransaction(con, txObject.getPreviousIsolationLevel()); 293 } 294 catch (LookupException ex) { 295 logger.info("Could not look up JDBC Connection of OJB PersistenceBroker", ex); 296 } 297 298 if (logger.isDebugEnabled()) { 299 logger.debug("Closing OJB PersistenceBroker [" + pb + "] after transaction"); 300 } 301 releasePersistenceBroker(pb); 302 } 303 304 305 315 protected PersistenceBroker getPersistenceBroker() throws OJBRuntimeException { 316 return PersistenceBrokerFactory.createPersistenceBroker(getPbKey()); 317 } 318 319 329 protected void releasePersistenceBroker(PersistenceBroker pb) { 330 OjbFactoryUtils.releasePersistenceBroker(pb, getPbKey()); 331 } 332 333 334 343 private static class PersistenceBrokerTransactionObject extends JdbcTransactionObjectSupport { 344 345 private PersistenceBrokerHolder persistenceBrokerHolder; 346 347 public void setPersistenceBrokerHolder(PersistenceBrokerHolder persistenceBrokerHolder) { 348 this.persistenceBrokerHolder = persistenceBrokerHolder; 349 } 350 351 public PersistenceBrokerHolder getPersistenceBrokerHolder() { 352 return persistenceBrokerHolder; 353 } 354 355 public void setRollbackOnly() { 356 getPersistenceBrokerHolder().setRollbackOnly(); 357 if (getConnectionHolder() != null) { 358 getConnectionHolder().setRollbackOnly(); 359 } 360 } 361 362 public boolean isRollbackOnly() { 363 return getPersistenceBrokerHolder().isRollbackOnly() || 364 (getConnectionHolder() != null && getConnectionHolder().isRollbackOnly()); 365 } 366 } 367 368 369 373 private static class SuspendedResourcesHolder { 374 375 private final PersistenceBrokerHolder persistenceBrokerHolder; 376 377 private final ConnectionHolder connectionHolder; 378 379 private SuspendedResourcesHolder(PersistenceBrokerHolder pbHolder, ConnectionHolder conHolder) { 380 this.persistenceBrokerHolder = pbHolder; 381 this.connectionHolder = conHolder; 382 } 383 384 private PersistenceBrokerHolder getPersistenceBrokerHolder() { 385 return persistenceBrokerHolder; 386 } 387 388 private ConnectionHolder getConnectionHolder() { 389 return connectionHolder; 390 } 391 } 392 393 } 394 | Popular Tags |