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
14
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 }