/
StandaloneJtaStrategy.java
129 lines (110 loc) · 4.23 KB
/
StandaloneJtaStrategy.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package org.jbpm.process.audit.strategy;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.transaction.Status;
import javax.transaction.UserTransaction;
import org.jbpm.process.audit.JPAWorkingMemoryDbLogger;
import org.kie.api.runtime.KieSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This strategy is used by instances that are<ul>
* <li>used outside the {@link KieSession}</li>
* <li>use their own {@link EntityManager} instance per operation</li>
* </ul>
*/
public class StandaloneJtaStrategy implements PersistenceStrategy {
private static final Logger logger = LoggerFactory.getLogger(JPAWorkingMemoryDbLogger.class);
private static final String[] KNOWN_UT_JNDI_KEYS = new String[] {"UserTransaction", "java:jboss/UserTransaction", System.getProperty("jbpm.ut.jndi.lookup")};
protected EntityManagerFactory emf;
private static final Object USER_MANAGED_TRANSACTION = new Object();
public StandaloneJtaStrategy(EntityManagerFactory emf) {
this.emf = emf;
}
@Override
public EntityManager getEntityManager() {
return emf.createEntityManager();
}
@Override
public Object joinTransaction(EntityManager em) {
boolean newTx = false;
UserTransaction ut = findUserTransaction();
if( ut == null ) {
throw new IllegalStateException("Unable to find JTA transaction." );
}
try {
if( ut.getStatus() == Status.STATUS_NO_TRANSACTION ) {
ut.begin();
newTx = true;
// since new transaction was started em must join it
}
} catch(Exception ex) {
throw new IllegalStateException("Unable to find or open a transaction: " + ex.getMessage(), ex);
}
try {
em.joinTransaction();
} catch( Exception e) {
throw new IllegalStateException("Unable to join EntityManager to transaction: " + e.getMessage(), e);
}
if( newTx ) {
return ut;
}
return USER_MANAGED_TRANSACTION;
}
protected static UserTransaction findUserTransaction() {
InitialContext context = null;
try {
context = new InitialContext();
} catch( Exception e ) {
throw new IllegalStateException("Unable to initialized " + InitialContext.class.getName() + " instance.", e);
}
try {
return (UserTransaction) context.lookup( "java:comp/UserTransaction" );
} catch ( NamingException ex ) {
for (String utLookup : KNOWN_UT_JNDI_KEYS) {
if (utLookup != null) {
try {
UserTransaction ut = (UserTransaction) context.lookup(utLookup);
return ut;
} catch (NamingException e) {
logger.debug("User Transaction not found in JNDI under {}", utLookup);
}
}
}
logger.warn("No user transaction found under known names");
return null;
}
}
@Override
public void leaveTransaction(EntityManager em, Object transaction) {
commitTransaction(transaction);
em.clear();
em.close();
}
protected void commitTransaction(Object transaction) {
if( transaction == USER_MANAGED_TRANSACTION ) {
return;
}
UserTransaction ut = null;
if( ! (transaction instanceof UserTransaction) ) {
throw new IllegalStateException("This persistence strategy only deals with UserTransaction instances!" );
} else if( transaction != null ){
ut = (UserTransaction) transaction;
}
try {
if( ut != null ) {
// There's a tx running, close it.
ut.commit();
}
} catch(Exception e) {
logger.error("Unable to commit transaction: ", e);
}
}
@Override
public void dispose() {
// NEVER close the emf, you don't know what it is also being used for!
emf = null;
}
}