View Javadoc
1   package com.atlassian.activeobjects.internal;
2   
3   import com.atlassian.activeobjects.spi.TransactionSynchronisationManager;
4   import com.atlassian.sal.api.transaction.TransactionCallback;
5   import com.atlassian.sal.api.transaction.TransactionTemplate;
6   import net.java.ao.EntityManager;
7   import org.slf4j.Logger;
8   import org.slf4j.LoggerFactory;
9   
10  import static com.google.common.base.Preconditions.checkNotNull;
11  
12  /**
13   * Implementation of the {@link com.atlassian.activeobjects.internal.TransactionManager}
14   * that relies on SAL's {@link com.atlassian.sal.api.transaction.TransactionTemplate}.
15   */
16  final class SalTransactionManager extends AbstractLoggingTransactionManager {
17      private final TransactionTemplate transactionTemplate;
18  
19      private final EntityManager entityManager;
20  
21      private final TransactionSynchronisationManager synchManager;
22  
23      private final Logger log = LoggerFactory.getLogger(SalTransactionManager.class);
24  
25      SalTransactionManager(TransactionTemplate transactionTemplate,
26                            EntityManager entityManager,
27                            TransactionSynchronisationManager synchManager) {
28          this.transactionTemplate = checkNotNull(transactionTemplate);
29          this.entityManager = checkNotNull(entityManager);
30          this.synchManager = checkNotNull(synchManager);
31      }
32  
33      <T> T inTransaction(TransactionCallback<T> callback) {
34          final Runnable commitAction = createCommitAction(entityManager);
35          final Runnable rollBackAction = createRollbackAction(entityManager);
36          final boolean transactionSynced = synchManager.runOnSuccessfulCommit(commitAction);
37          if (transactionSynced) {
38              synchManager.runOnRollBack(rollBackAction);
39          }
40          final T result;
41          try {
42              result = transactionTemplate.execute(callback);
43          } catch (final RuntimeException exception) {
44              if (!transactionSynced) {
45                  try {
46                      rollBackAction.run();
47                  } catch (Exception ex) {
48                      log.error("Error occurred performing post roll back action, logging and throwing original exception", ex);
49                  }
50              }
51              throw exception;
52          }
53          if (!transactionSynced) {
54              commitAction.run();
55          }
56          return result;
57      }
58  
59      private Runnable createCommitAction(final EntityManager entityManager) {
60          return new Runnable() {
61              @Override
62              public void run() {
63                  log.debug("Flushing entityManager due to commit");
64                  entityManager.flushEntityCache();
65              }
66          };
67      }
68  
69      private Runnable createRollbackAction(final EntityManager entityManager) {
70          return new Runnable() {
71              @Override
72              public void run() {
73                  log.info("Flushing entityManager due to rollback");
74                  entityManager.flushAll();
75              }
76          };
77      }
78  }