1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 package org.hibernate.context.internal;
25
26 import java.util.Map;
27 import java.util.concurrent.ConcurrentHashMap;
28
29 import javax.transaction.Synchronization;
30 import javax.transaction.Transaction;
31 import javax.transaction.TransactionManager;
32
33 import org.jboss.logging.Logger;
34
35 import org.hibernate.ConnectionReleaseMode;
36 import org.hibernate.HibernateException;
37 import org.hibernate.Session;
38 import org.hibernate.context.spi.AbstractCurrentSessionContext;
39 import org.hibernate.context.spi.CurrentSessionContext;
40 import org.hibernate.engine.spi.SessionFactoryImplementor;
41 import org.hibernate.engine.transaction.internal.jta.JtaStatusHelper;
42 import org.hibernate.internal.CoreMessageLogger;
43 import org.hibernate.service.jta.platform.spi.JtaPlatform;
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 public class JTASessionContext extends AbstractCurrentSessionContext {
69 private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, JTASessionContext.class.getName());
70
71 private transient Map<Object, Session> currentSessionMap = new ConcurrentHashMap<Object, Session>();
72
73 public JTASessionContext(SessionFactoryImplementor factory) {
74 super( factory );
75 }
76
77 @Override
78 public Session currentSession() throws HibernateException {
79 final JtaPlatform jtaPlatform = factory().getServiceRegistry().getService( JtaPlatform.class );
80 final TransactionManager transactionManager = jtaPlatform.retrieveTransactionManager();
81 if ( transactionManager == null ) {
82 throw new HibernateException( "No TransactionManagerLookup specified" );
83 }
84
85 Transaction txn;
86 try {
87 txn = transactionManager.getTransaction();
88 if ( txn == null ) {
89 throw new HibernateException( "Unable to locate current JTA transaction" );
90 }
91 if ( !JtaStatusHelper.isActive( txn.getStatus() ) ) {
92
93
94
95 throw new HibernateException( "Current transaction is not in progress" );
96 }
97 }
98 catch ( HibernateException e ) {
99 throw e;
100 }
101 catch ( Throwable t ) {
102 throw new HibernateException( "Problem locating/validating JTA transaction", t );
103 }
104
105 final Object txnIdentifier = jtaPlatform.getTransactionIdentifier( txn );
106
107 Session currentSession = currentSessionMap.get( txnIdentifier );
108
109 if ( currentSession == null ) {
110 currentSession = buildOrObtainSession();
111
112 try {
113 txn.registerSynchronization( buildCleanupSynch( txnIdentifier ) );
114 }
115 catch ( Throwable t ) {
116 try {
117 currentSession.close();
118 }
119 catch ( Throwable ignore ) {
120 LOG.debug( "Unable to release generated current-session on failed synch registration", ignore );
121 }
122 throw new HibernateException( "Unable to register cleanup Synchronization with TransactionManager" );
123 }
124
125 currentSessionMap.put( txnIdentifier, currentSession );
126 }
127 else {
128 validateExistingSession( currentSession );
129 }
130
131 return currentSession;
132 }
133
134
135
136
137
138
139
140
141 private CleanupSynch buildCleanupSynch(Object transactionIdentifier) {
142 return new CleanupSynch( transactionIdentifier, this );
143 }
144
145
146
147
148
149
150
151
152
153 protected Session buildOrObtainSession() {
154 return baseSessionBuilder()
155 .autoClose( isAutoCloseEnabled() )
156 .connectionReleaseMode( getConnectionReleaseMode() )
157 .flushBeforeCompletion( isAutoFlushEnabled() )
158 .openSession();
159 }
160
161
162
163
164
165
166 protected boolean isAutoCloseEnabled() {
167 return true;
168 }
169
170
171
172
173
174
175 protected boolean isAutoFlushEnabled() {
176 return true;
177 }
178
179
180
181
182
183
184 protected ConnectionReleaseMode getConnectionReleaseMode() {
185 return ConnectionReleaseMode.AFTER_STATEMENT;
186 }
187
188
189
190
191 protected static class CleanupSynch implements Synchronization {
192 private Object transactionIdentifier;
193 private JTASessionContext context;
194
195 public CleanupSynch(Object transactionIdentifier, JTASessionContext context) {
196 this.transactionIdentifier = transactionIdentifier;
197 this.context = context;
198 }
199
200
201
202
203 public void beforeCompletion() {
204 }
205
206
207
208
209 public void afterCompletion(int i) {
210 context.currentSessionMap.remove( transactionIdentifier );
211 }
212 }
213 }