From 60cedaec802234d8077560ca3b56906d74d238b7 Mon Sep 17 00:00:00 2001 From: William Keller Date: Mon, 25 May 2015 13:50:50 +1000 Subject: [PATCH 1/2] - Small change to support 'readOnly' transactions, that is - still act like there is a running transaction except begin/commit/rollback actions will have no effect --- .../spring/tx/OrientTransactionManager.java | 54 ++++++++++++++----- 1 file changed, 40 insertions(+), 14 deletions(-) diff --git a/orient-spring-tx/src/main/java/org/ops4j/orient/spring/tx/OrientTransactionManager.java b/orient-spring-tx/src/main/java/org/ops4j/orient/spring/tx/OrientTransactionManager.java index ce69f0a..4b66a92 100644 --- a/orient-spring-tx/src/main/java/org/ops4j/orient/spring/tx/OrientTransactionManager.java +++ b/orient-spring-tx/src/main/java/org/ops4j/orient/spring/tx/OrientTransactionManager.java @@ -21,6 +21,7 @@ import com.orientechnologies.orient.core.db.ODatabaseDocumentInternal; import com.orientechnologies.orient.core.db.ODatabaseInternal; import com.orientechnologies.orient.core.db.ODatabaseRecordThreadLocal; +import com.orientechnologies.orient.core.tx.OTransaction; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.transaction.TransactionDefinition; @@ -43,7 +44,7 @@ public class OrientTransactionManager extends AbstractPlatformTransactionManager private static final long serialVersionUID = 1L; - private static Logger log = LoggerFactory.getLogger(OrientTransactionManager.class); + private final Logger logger = LoggerFactory.getLogger(this.getClass()); private AbstractOrientDatabaseFactory dbf; @@ -51,19 +52,26 @@ public class OrientTransactionManager extends AbstractPlatformTransactionManager protected Object doGetTransaction() throws TransactionException { OrientTransaction tx = new OrientTransaction(); - ODatabaseInternal db = (ODatabaseInternal) TransactionSynchronizationManager.getResource(getResourceFactory()); + ODatabaseInternal db = (ODatabaseInternal) TransactionSynchronizationManager.getResource(dbf); if (db != null) { tx.setDatabase(db); tx.setTx(db.getTransaction()); } - return tx; } @Override protected boolean isExistingTransaction(Object transaction) throws TransactionException { OrientTransaction tx = (OrientTransaction) transaction; - return tx.getTx() == null ? false : tx.getTx().isActive(); + boolean condition = tx.getTx() == null ? false : tx.getTx().isActive(); + if(condition){ + logger.debug("\t\\-- *** " + + "Participating in running transaction: db.hashCode() = {}", tx.getDatabase().hashCode()); + }else{ + logger.debug("*** isExistingTransaction: No active transaction"); + } + + return condition; } @Override @@ -76,28 +84,45 @@ protected void doBegin(Object transaction, TransactionDefinition definition) thr tx.setDatabase(db); TransactionSynchronizationManager.bindResource(dbf, db); } - log.debug("beginning transaction, db.hashCode() = {}", db.hashCode()); + + if(definition.isReadOnly()) { + logger.debug("*** Setting transaction to READ-ONLY, db.hashCode() = {}", db.hashCode()); + db.begin(OTransaction.TXTYPE.NOTX); + } + logger.debug("*** Beginning transaction, db.hashCode() = {}", db.hashCode()); db.begin(); } @Override protected void doCommit(DefaultTransactionStatus status) throws TransactionException { + OrientTransaction tx = (OrientTransaction) status.getTransaction(); ODatabaseInternal db = tx.getDatabase(); - log.debug("committing transaction, db.hashCode() = {}", db.hashCode()); - db.commit(); + if(status.isReadOnly()){ + logger.debug("*** Committing READ-ONLY transaction - will have no effect, db.hashCode() = {}", db.hashCode()); + }else { + logger.debug("*** Committing transaction, db.hashCode() = {}", db.hashCode()); + } + } @Override protected void doRollback(DefaultTransactionStatus status) throws TransactionException { OrientTransaction tx = (OrientTransaction) status.getTransaction(); ODatabaseInternal db = tx.getDatabase(); - log.debug("committing transaction, db.hashCode() = {}", db.hashCode()); + + if(status.isReadOnly()){ + logger.debug("*** Rolling back READ-ONLY transaction - will have no effect, db.hashCode() = {}", db.hashCode()); + }else{ + logger.debug("*** Rolling back transaction, db.hashCode() = {}", db.hashCode()); + } + db.rollback(); } - + @Override protected void doSetRollbackOnly(DefaultTransactionStatus status) throws TransactionException { + logger.debug("*** Marking transaction for rollback"); status.setRollbackOnly(); } @@ -108,18 +133,19 @@ protected void doCleanupAfterCompletion(Object transaction) { tx.getDatabase().close(); } TransactionSynchronizationManager.unbindResource(dbf); + logger.debug("*** Doing cleanup after completion"); } - + @Override protected Object doSuspend(Object transaction) throws TransactionException { OrientTransaction tx = (OrientTransaction) transaction; ODatabaseInternal db = tx.getDatabase(); return db; } - + @Override protected void doResume(Object transaction, Object suspendedResources) - throws TransactionException { + throws TransactionException { OrientTransaction tx = (OrientTransaction) transaction; ODatabaseInternal db = tx.getDatabase(); if (!db.isClosed()) { @@ -137,7 +163,7 @@ public Object getResourceFactory() { /** * Gets the database factory for the database managed by this transaction manager. - * + * * @return the database */ public AbstractOrientDatabaseFactory getDatabaseFactory() { @@ -146,7 +172,7 @@ public AbstractOrientDatabaseFactory getDatabaseFactory() { /** * Sets the database factory for the database managed by this transaction manager. - * + * * @param databaseFactory the database to set */ public void setDatabaseManager(AbstractOrientDatabaseFactory databaseFactory) { From 4c6d81b9a5621d1e898bda471eb2c795383f56bb Mon Sep 17 00:00:00 2001 From: William Keller Date: Tue, 26 May 2015 20:27:56 +1000 Subject: [PATCH 2/2] - Fixed issue relating to doCleanup when no resource is found. Added guard to ensure that resource exists before a cleanup is attempted --- .../spring/tx/OrientTransactionManager.java | 40 ++++++++++++++----- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/orient-spring-tx/src/main/java/org/ops4j/orient/spring/tx/OrientTransactionManager.java b/orient-spring-tx/src/main/java/org/ops4j/orient/spring/tx/OrientTransactionManager.java index 4b66a92..27af486 100644 --- a/orient-spring-tx/src/main/java/org/ops4j/orient/spring/tx/OrientTransactionManager.java +++ b/orient-spring-tx/src/main/java/org/ops4j/orient/spring/tx/OrientTransactionManager.java @@ -22,6 +22,7 @@ import com.orientechnologies.orient.core.db.ODatabaseInternal; import com.orientechnologies.orient.core.db.ODatabaseRecordThreadLocal; import com.orientechnologies.orient.core.tx.OTransaction; +import com.orientechnologies.orient.core.tx.OTransactionNoTx; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.transaction.TransactionDefinition; @@ -63,7 +64,11 @@ protected Object doGetTransaction() throws TransactionException { @Override protected boolean isExistingTransaction(Object transaction) throws TransactionException { OrientTransaction tx = (OrientTransaction) transaction; - boolean condition = tx.getTx() == null ? false : tx.getTx().isActive(); + OTransaction tx1 = tx.getTx(); + boolean condition = tx1 == null ? false : tx1.isActive(); + if(tx1 instanceof OTransactionNoTx){ + condition = true; + } if(condition){ logger.debug("\t\\-- *** " + "Participating in running transaction: db.hashCode() = {}", tx.getDatabase().hashCode()); @@ -86,11 +91,12 @@ protected void doBegin(Object transaction, TransactionDefinition definition) thr } if(definition.isReadOnly()) { - logger.debug("*** Setting transaction to READ-ONLY, db.hashCode() = {}", db.hashCode()); + logger.debug("*** Setting transaction to READ-ONLY - will ignore commits and rollbacks, db.hashCode() = {}", db.hashCode()); db.begin(OTransaction.TXTYPE.NOTX); + }else { + logger.debug("*** Beginning transaction, db.hashCode() = {}", db.hashCode()); + db.begin(); } - logger.debug("*** Beginning transaction, db.hashCode() = {}", db.hashCode()); - db.begin(); } @Override @@ -99,9 +105,10 @@ protected void doCommit(DefaultTransactionStatus status) throws TransactionExcep OrientTransaction tx = (OrientTransaction) status.getTransaction(); ODatabaseInternal db = tx.getDatabase(); if(status.isReadOnly()){ - logger.debug("*** Committing READ-ONLY transaction - will have no effect, db.hashCode() = {}", db.hashCode()); + logger.debug("*** Committing READ-ONLY transaction - will ignore commits and rollbacks, db.hashCode() = {}", db.hashCode()); }else { logger.debug("*** Committing transaction, db.hashCode() = {}", db.hashCode()); + db.commit(); } } @@ -112,7 +119,7 @@ protected void doRollback(DefaultTransactionStatus status) throws TransactionExc ODatabaseInternal db = tx.getDatabase(); if(status.isReadOnly()){ - logger.debug("*** Rolling back READ-ONLY transaction - will have no effect, db.hashCode() = {}", db.hashCode()); + logger.debug("*** Rolling back READ-ONLY transaction - will ignore commits and rollbacks, db.hashCode() = {}", db.hashCode()); }else{ logger.debug("*** Rolling back transaction, db.hashCode() = {}", db.hashCode()); } @@ -122,18 +129,30 @@ protected void doRollback(DefaultTransactionStatus status) throws TransactionExc @Override protected void doSetRollbackOnly(DefaultTransactionStatus status) throws TransactionException { - logger.debug("*** Marking transaction for rollback"); - status.setRollbackOnly(); + + if(status.isReadOnly()){ + logger.debug("*** Marking transaction for rollback - will ignore commits and rollbacks"); + } else { + logger.debug("*** Marking transaction for rollback"); + status.setRollbackOnly(); + } } @Override protected void doCleanupAfterCompletion(Object transaction) { + logger.debug("*** Doing cleanup after completion"); OrientTransaction tx = (OrientTransaction) transaction; if (!tx.getDatabase().isClosed()) { tx.getDatabase().close(); } - TransactionSynchronizationManager.unbindResource(dbf); - logger.debug("*** Doing cleanup after completion"); + + if(TransactionSynchronizationManager.hasResource(dbf)) { + TransactionSynchronizationManager.unbindResource(dbf); + logger.debug("*** Removed resources"); + } else { + logger.debug("*** Did not remove resources"); + } + } @Override @@ -178,4 +197,5 @@ public AbstractOrientDatabaseFactory getDatabaseFactory() { public void setDatabaseManager(AbstractOrientDatabaseFactory databaseFactory) { this.dbf = databaseFactory; } + }