1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.jadira.usertype.spi.jta;
17
18 import java.lang.reflect.Field;
19 import java.lang.reflect.InvocationTargetException;
20 import java.lang.reflect.Method;
21
22 import javax.naming.NamingException;
23 import javax.transaction.Status;
24 import javax.transaction.Synchronization;
25 import javax.transaction.Transaction;
26 import javax.transaction.TransactionManager;
27 import javax.transaction.xa.XAResource;
28
29 import org.omg.CORBA.SystemException;
30 import org.springframework.jndi.JndiTemplate;
31 import org.springframework.transaction.PlatformTransactionManager;
32 import org.springframework.transaction.TransactionSystemException;
33 import org.springframework.transaction.jta.WebSphereUowTransactionManager;
34
35
36
37
38
39
40
41
42
43
44
45
46 public class SpringWebSphereUowTransactionManager extends WebSphereUowTransactionManager {
47
48 private static final long serialVersionUID = 4838070722625854290L;
49
50 private static final String UOW_SYNCHRONIZATION_REGISTRY_JNDINAME = "java:comp/websphere/UOWSynchronizationRegistry";
51 private static final String USER_TRANASCTION_JNDINAME = "java:comp/UserTransaction";
52
53 private static final Field UOW_FIELD;
54
55 static {
56 try {
57 UOW_FIELD = WebSphereUowTransactionManager.class.getDeclaredField("uowManager");
58 UOW_FIELD.setAccessible(true);
59 } catch (SecurityException e) {
60 throw new IllegalStateException(
61 "Not permitted to access WebSphereUowTransactionManager: " + e.getMessage(), e);
62 } catch (NoSuchFieldException e) {
63 throw new IllegalStateException("Could not find WebSphereUowTransactionManager: " + e.getMessage(), e);
64 }
65 }
66
67
68
69
70 public SpringWebSphereUowTransactionManager() {
71 super();
72 }
73
74 @Override
75 public void afterPropertiesSet() throws TransactionSystemException {
76 super.afterPropertiesSet();
77 setTransactionManager(new TransactionManagerAdapter(getJndiTemplate(), retrieveUowManager()));
78 setUserTransactionName(USER_TRANASCTION_JNDINAME);
79 }
80
81 private Object retrieveUowManager() {
82 try {
83 Object uowManager = UOW_FIELD.get(this);
84 return uowManager;
85 } catch (SecurityException e) {
86 throw new IllegalStateException(
87 "Not permitted to access WebSphereUowTransactionManager: " + e.getMessage(), e);
88 } catch (IllegalArgumentException e) {
89 throw new IllegalStateException("Unexpected argument accessing WebSphereUowTransactionManager: "
90 + e.getMessage(), e);
91 } catch (IllegalAccessException e) {
92 throw new IllegalStateException("Unexpected exception accessing WebSphereUowTransactionManager: "
93 + e.getMessage(), e);
94 }
95 }
96
97
98
99
100 public static class TransactionManagerAdapter implements TransactionManager {
101
102 private final JndiTemplate jndiTemplate;
103
104 private final Object uowManager;
105 private final Class<?> uowManagerClass;
106
107 private final Object uowSynchronizationRegistry;
108 private final Class<?> uowSynchronizationRegistryClass;
109
110 private final Method registerSynchronizationMethod;
111 private final Method setRollbackOnlyMethod;
112
113 private final Class<?> extendedJTATransactionClass;
114 private final Method getLocalIdMethod;
115
116
117
118
119
120
121 private TransactionManagerAdapter(JndiTemplate jndiTemplate, Object uowManager) {
122
123 try {
124 this.uowManagerClass = Class.forName("com.ibm.ws.uow.UOWManager");
125
126 this.uowSynchronizationRegistry = jndiTemplate.lookup(UOW_SYNCHRONIZATION_REGISTRY_JNDINAME);
127 this.uowSynchronizationRegistryClass = Class
128 .forName("com.ibm.websphere.uow.UOWSynchronizationRegistry");
129
130 this.registerSynchronizationMethod = uowSynchronizationRegistryClass.getMethod(
131 "registerInterposedSynchronization", new Class[] { Synchronization.class });
132 this.setRollbackOnlyMethod = uowManagerClass.getMethod("setRollbackOnly", new Class[] {});
133
134 this.extendedJTATransactionClass = Class
135 .forName("com.ibm.websphere.jtaextensions.ExtendedJTATransaction");
136 this.getLocalIdMethod = extendedJTATransactionClass.getMethod("getLocalId", (Class[]) null);
137
138 } catch (ClassNotFoundException e) {
139 throw new IllegalStateException("Could not find required WebSphere class: " + e.getMessage(), e);
140 } catch (NoSuchMethodException e) {
141 throw new IllegalStateException("Could not find required method: " + e.getMessage(), e);
142 } catch (NamingException e) {
143 throw new IllegalStateException("Problem accessing JNDI: " + e.getMessage(), e);
144 }
145
146 this.jndiTemplate = jndiTemplate;
147 this.uowManager = uowManager;
148 }
149
150 @Override
151 public void begin() {
152 throw new UnsupportedOperationException("begin() is not supported");
153 }
154
155 @Override
156 public void commit() {
157 throw new UnsupportedOperationException("commit() is not supported");
158 }
159
160 @Override
161 public int getStatus() {
162 throw new UnsupportedOperationException("getStatus() is not supported");
163 }
164
165 @Override
166 public void resume(Transaction txn) {
167 throw new UnsupportedOperationException("resume() is not supported");
168 }
169
170 @Override
171 public void rollback() {
172 throw new UnsupportedOperationException("rollback() is not supported");
173 }
174
175 @Override
176 public void setTransactionTimeout(int i) {
177 throw new UnsupportedOperationException("setTransactionTimeout() is not supported");
178 }
179
180 @Override
181 public Transaction suspend() {
182 throw new UnsupportedOperationException("suspend() is not supported");
183 }
184
185 @Override
186 public void setRollbackOnly() throws IllegalStateException {
187 try {
188 setRollbackOnlyMethod.invoke(uowManager, new Object[] {});
189 } catch (IllegalAccessException e) {
190 throw new IllegalStateException("Could not access setRollbackOnly() on UOWManager: " + e.getMessage(),
191 e);
192 } catch (InvocationTargetException e) {
193 throw new IllegalStateException("Could not invoke setRollbackOnly() on UOWManager: " + e.getMessage(),
194 e);
195 }
196 }
197
198 @Override
199 public Transaction getTransaction() {
200 return new TransactionAdapter(jndiTemplate);
201 }
202
203
204
205
206 public class TransactionAdapter implements Transaction {
207
208 private final Object extendedJTATransaction;
209
210
211
212
213
214 private TransactionAdapter(JndiTemplate template) {
215 try {
216 extendedJTATransaction = template.lookup("java:comp/websphere/ExtendedJTATransaction");
217
218 } catch (NamingException e) {
219 throw new IllegalStateException("Could not find ExtendedJTATransaction in JNDI: " + e.getMessage(),
220 e);
221 }
222 }
223
224 @Override
225 public void registerSynchronization(final Synchronization synchronization) {
226
227 try {
228 registerSynchronizationMethod.invoke(uowSynchronizationRegistry, new Object[] { synchronization });
229 } catch (IllegalArgumentException e) {
230 throw new IllegalStateException("Unexpected argument accessing UOWSynchronizationRegistry: "
231 + e.getMessage(), e);
232 } catch (IllegalAccessException e) {
233 throw new IllegalStateException("Unexpected exception accessing UOWSynchronizationRegistry: "
234 + e.getMessage(), e);
235 } catch (InvocationTargetException e) {
236 throw new IllegalStateException(
237 "Could not invoke registerSynchronization() on UOWSynchronizationRegistry: "
238 + e.getMessage(), e);
239 }
240 }
241
242 @Override
243 public void commit() {
244 throw new UnsupportedOperationException("commit() is not supported");
245 }
246
247 @Override
248 public boolean delistResource(XAResource resource, int i) {
249 throw new UnsupportedOperationException("delistResource() is not supported");
250 }
251
252 @Override
253 public boolean enlistResource(XAResource resource) {
254 throw new UnsupportedOperationException("enlistResource() is not supported");
255 }
256
257 @Override
258 public int getStatus() {
259 if (0 == getLocalId()) {
260 return Status.STATUS_NO_TRANSACTION;
261 } else {
262 return Status.STATUS_ACTIVE;
263 }
264 }
265
266 @Override
267 public void rollback() throws IllegalStateException, SystemException {
268 throw new UnsupportedOperationException("rollback() is not supported");
269 }
270
271 @Override
272 public void setRollbackOnly() {
273 try {
274 setRollbackOnlyMethod.invoke(uowManager, new Object[] {});
275 } catch (IllegalArgumentException e) {
276 throw new IllegalStateException("Unexpected argument accessing UOWManager: " + e.getMessage(), e);
277 } catch (IllegalAccessException e) {
278 throw new IllegalStateException("Unexpected exception accessing UOWManager: " + e.getMessage(), e);
279 } catch (InvocationTargetException e) {
280 throw new IllegalStateException("Could not invoke setRollbackOnly() on UOWManager: "
281 + e.getMessage(), e);
282 }
283 }
284
285 @Override
286 public int hashCode() {
287 return getLocalId();
288 }
289
290 @Override
291 public boolean equals(Object other) {
292 if (!(other instanceof TransactionAdapter))
293 return false;
294 TransactionAdapter that = (TransactionAdapter) other;
295 return getLocalId() == that.getLocalId();
296 }
297
298 private int getLocalId() {
299 try {
300 return ((Integer) (getLocalIdMethod.invoke(extendedJTATransaction, (Object[]) null))).intValue();
301 } catch (IllegalArgumentException e) {
302 throw new IllegalStateException("Unexpected argument accessing ExtendedJTATransaction: "
303 + e.getMessage(), e);
304 } catch (IllegalAccessException e) {
305 throw new IllegalStateException("Unexpected exception accessing ExtendedJTATransaction: "
306 + e.getMessage(), e);
307 } catch (InvocationTargetException e) {
308 throw new IllegalStateException("Could not invoke getLocalId() on ExtendedJTATransaction: "
309 + e.getMessage(), e);
310 }
311 }
312
313 }
314 }
315 }