1
1
/*
2
- * Copyright (c) 2023 Oracle and/or its affiliates.
2
+ * Copyright (c) 2023, 2024 Oracle and/or its affiliates.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
@@ -80,13 +80,59 @@ public final class JtaAdaptingDataSource extends AbstractDataSource {
80
80
* made immediately upon {@link Connection} allocation
81
81
*
82
82
* @exception NullPointerException if {@code ts}, {@code tsr} or {@code ds} is {@code null}
83
+ *
84
+ * @see #JtaAdaptingDataSource(TransactionSupplier, TransactionSynchronizationRegistry, boolean, ExceptionConverter,
85
+ * DataSource, boolean, boolean)
83
86
*/
84
87
public JtaAdaptingDataSource (TransactionSupplier ts ,
85
88
TransactionSynchronizationRegistry tsr ,
86
89
boolean interposedSynchronizations ,
87
90
ExceptionConverter ec ,
88
91
DataSource ds ,
89
92
boolean immediateEnlistment ) {
93
+ this (ts , tsr , interposedSynchronizations , ec , ds , immediateEnlistment , true );
94
+ }
95
+
96
+ /**
97
+ * Creates a new {@link JtaAdaptingDataSource} that wraps the supplied {@link DataSource} and helps its {@linkplain
98
+ * DataSource#getConnection() connections} participate in XA transactions.
99
+ *
100
+ * <p>Behavior is left deliberately undefined if the supplied {@link DataSource}'s {@link
101
+ * DataSource#getConnection()} or {@link DataSource#getConnection(String, String)} methods are implemented to return
102
+ * or augment the return value of an invocation of the {@link javax.sql.PooledConnection#getConnection()
103
+ * XAConnection#getConnection()} method. Less formally, and in general, this class is deliberately not designed to
104
+ * work with JDBC constructs that are already XA-aware.</p>
105
+ *
106
+ * @param ts a {@link TransactionSupplier}; must not be {@code null}
107
+ *
108
+ * @param tsr a {@link TransactionSynchronizationRegistry}; must not be {@code null}
109
+ *
110
+ * @param interposedSynchronizations whether any {@link jakarta.transaction.Synchronization Synchronization}s
111
+ * registered should be registered as interposed synchronizations; see {@link
112
+ * TransactionSynchronizationRegistry#registerInterposedSynchronization(jakarta.transaction.Synchronization)} and
113
+ * {@link jakarta.transaction.Transaction#registerSynchronization(jakarta.transaction.Synchronization)}
114
+ *
115
+ * @param ec an {@link ExceptionConverter}; may be {@code null} in which case a default implementation will be used
116
+ * instead
117
+ *
118
+ * @param ds a {@link DataSource} that may not be XA-compliant; must not be {@code null}; normally supplied by a
119
+ * connection pool implementation
120
+ *
121
+ * @param immediateEnlistment whether attempts to enlist new {@link Connection}s in a global transaction should be
122
+ * made immediately upon {@link Connection} allocation
123
+ *
124
+ * @param preemptiveEnlistmentChecks whether early checks will be made to see if an enlistment attempt will succeed,
125
+ * or whether enlistment validation will be performed by the JTA implementation
126
+ *
127
+ * @exception NullPointerException if {@code ts}, {@code tsr} or {@code ds} is {@code null}
128
+ */
129
+ public JtaAdaptingDataSource (TransactionSupplier ts ,
130
+ TransactionSynchronizationRegistry tsr ,
131
+ boolean interposedSynchronizations ,
132
+ ExceptionConverter ec ,
133
+ DataSource ds ,
134
+ boolean immediateEnlistment ,
135
+ boolean preemptiveEnlistmentChecks ) {
90
136
super ();
91
137
Objects .requireNonNull (ts , "ts" );
92
138
Objects .requireNonNull (tsr , "tsr" );
@@ -99,9 +145,24 @@ public JtaAdaptingDataSource(TransactionSupplier ts,
99
145
// the (inherited) PooledConnection#close() method, which reads, in part: "An application never calls this
100
146
// method directly; it is called by the connection pool module, or manager." As of this writing this branch
101
147
// of this constructor implements this non-standard behavior.
102
- this .acs =
103
- (u , p ) -> xa (ts , tsr , interposedSynchronizations , ec , xads .getXAConnection (u , p ), immediateEnlistment , true );
104
- this .uacs = () -> xa (ts , tsr , interposedSynchronizations , ec , xads .getXAConnection (), immediateEnlistment , true );
148
+ this .acs = (u , p ) ->
149
+ xa (ts ,
150
+ tsr ,
151
+ interposedSynchronizations ,
152
+ ec ,
153
+ xads .getXAConnection (u , p ),
154
+ immediateEnlistment ,
155
+ preemptiveEnlistmentChecks ,
156
+ true );
157
+ this .uacs = () ->
158
+ xa (ts ,
159
+ tsr ,
160
+ interposedSynchronizations ,
161
+ ec ,
162
+ xads .getXAConnection (),
163
+ immediateEnlistment ,
164
+ preemptiveEnlistmentChecks ,
165
+ true );
105
166
} else {
106
167
Objects .requireNonNull (ds , "ds" );
107
168
this .acs =
@@ -156,6 +217,59 @@ public JtaAdaptingDataSource(TransactionSupplier ts,
156
217
XADataSource xads ,
157
218
boolean immediateEnlistment ,
158
219
boolean closeXac ) {
220
+ this (ts , tsr , interposedSynchronizations , ec , xads , immediateEnlistment , true , closeXac );
221
+ }
222
+
223
+ /**
224
+ * Creates a new {@link JtaAdaptingDataSource} that adapts the supplied {@link XADataSource} and helps {@link
225
+ * Connection}s it indirectly supplies (by way of its {@linkplain XADataSource#getXAConnection() associated
226
+ * <code>XAConnection</code>}) participate in XA transactions.
227
+ *
228
+ * @param ts a {@link TransactionSupplier}; must not be {@code null}
229
+ *
230
+ * @param tsr a {@link TransactionSynchronizationRegistry}; must not be {@code null}
231
+ *
232
+ * @param interposedSynchronizations whether any {@link jakarta.transaction.Synchronization Synchronization}s
233
+ * registered should be registered as interposed synchronizations; see {@link
234
+ * TransactionSynchronizationRegistry#registerInterposedSynchronization(jakarta.transaction.Synchronization)} and
235
+ * {@link jakarta.transaction.Transaction#registerSynchronization(jakarta.transaction.Synchronization)}
236
+ *
237
+ * @param ec an {@link ExceptionConverter}; may be {@code null} in which case a default implementation will be used
238
+ * instead
239
+ *
240
+ * @param xads an {@link XADataSource} supplied by a connection pool implementation; must not be {@code null}
241
+ *
242
+ * @param immediateEnlistment whether attempts to enlist new {@link Connection}s in a global transaction should be
243
+ * made immediately upon {@link Connection} allocation
244
+ *
245
+ * @param preemptiveEnlistmentChecks whether early checks will be made to see if an enlistment attempt will succeed,
246
+ * or whether enlistment validation will be performed by the JTA implementation
247
+ *
248
+ * @param closeXac whether or not {@link XAConnection}s {@linkplain XADataSource#getXAConnection() supplied} by the
249
+ * supplied {@link XADataSource} should be {@linkplain javax.sql.PooledConnection#close() closed} when {@linkplain
250
+ * XAConnection#getConnection() their <code>Connection</code>}s are {@linkplain Connection#close() closed} (in a
251
+ * non-standard fashion)
252
+ *
253
+ * @exception NullPointerException if {@code ts}, {@code tsr} or {@code xads} is {@code null}
254
+ *
255
+ * @deprecated This constructor exists only to handle certain XA-aware connection pools that allow an end-user
256
+ * caller to "borrow" {@link XAConnection}s and to "return" them using their {@link
257
+ * javax.sql.PooledConnection#close() close()} methods, a non-standard practice which is discouraged by the
258
+ * documentation of {@link javax.sql.PooledConnection} (from which {@link XAConnection} inherits). For
259
+ * such connection pools, {@link XAConnection}s that are "borrowed" must be returned in this manner to avoid leaks.
260
+ * This constructor implements this behavior. Before using it, you should make sure that the connection pool in
261
+ * question implementing or supplying the {@link XADataSource} has the behavior described above; normally an {@link
262
+ * XAConnection} should not be used directly or closed by end-user code.
263
+ */
264
+ @ Deprecated (since = "3.1.0" )
265
+ public JtaAdaptingDataSource (TransactionSupplier ts ,
266
+ TransactionSynchronizationRegistry tsr ,
267
+ boolean interposedSynchronizations ,
268
+ ExceptionConverter ec ,
269
+ XADataSource xads ,
270
+ boolean immediateEnlistment ,
271
+ boolean preemptiveEnlistmentChecks ,
272
+ boolean closeXac ) {
159
273
super ();
160
274
Objects .requireNonNull (xads , "xads" );
161
275
Objects .requireNonNull (ts , "ts" );
@@ -168,8 +282,24 @@ public JtaAdaptingDataSource(TransactionSupplier ts,
168
282
// is called by the connection pool module, or manager." As of this writing this constructor permits this
169
283
// non-standard behavior when closeXac is true.
170
284
this .acs =
171
- (u , p ) -> xa (ts , tsr , interposedSynchronizations , ec , xads .getXAConnection (u , p ), immediateEnlistment , closeXac );
172
- this .uacs = () -> xa (ts , tsr , interposedSynchronizations , ec , xads .getXAConnection (), immediateEnlistment , closeXac );
285
+ (u , p ) ->
286
+ xa (ts ,
287
+ tsr ,
288
+ interposedSynchronizations ,
289
+ ec ,
290
+ xads .getXAConnection (u , p ),
291
+ immediateEnlistment ,
292
+ preemptiveEnlistmentChecks ,
293
+ closeXac );
294
+ this .uacs = () ->
295
+ xa (ts ,
296
+ tsr ,
297
+ interposedSynchronizations ,
298
+ ec ,
299
+ xads .getXAConnection (),
300
+ immediateEnlistment ,
301
+ preemptiveEnlistmentChecks ,
302
+ closeXac );
173
303
}
174
304
175
305
@ Override // DataSource
@@ -189,12 +319,14 @@ public Connection getConnection() throws SQLException {
189
319
190
320
191
321
@ Deprecated
322
+ @ SuppressWarnings ("ParameterNumber" )
192
323
private static JtaConnection xa (TransactionSupplier ts ,
193
324
TransactionSynchronizationRegistry tsr ,
194
325
boolean interposedSynchronizations ,
195
326
ExceptionConverter ec ,
196
327
XAConnection xac ,
197
328
boolean immediateEnlistment ,
329
+ boolean preemptiveEnlistmentChecks ,
198
330
boolean closeXac )
199
331
throws SQLException {
200
332
if (closeXac ) {
@@ -204,13 +336,16 @@ private static JtaConnection xa(TransactionSupplier ts,
204
336
// reads: "An application never calls this method directly; it is called by the connection pool module, or
205
337
// manager." This branch of this method implements this non-standard behavior, ensuring that both the
206
338
// Connection and its sourcing XAConnection are closed appropriately.
207
- return new JtaConnection (ts ,
208
- tsr ,
209
- interposedSynchronizations ,
210
- ec ,
211
- xac .getConnection (),
212
- xac ::getXAResource ,
213
- immediateEnlistment ) {
339
+ return
340
+ new JtaConnection (ts ,
341
+ tsr ,
342
+ interposedSynchronizations ,
343
+ ec ,
344
+ xac .getConnection (),
345
+ xac ::getXAResource ,
346
+ null , // no Xid consumer
347
+ immediateEnlistment ,
348
+ preemptiveEnlistmentChecks ) {
214
349
@ Override
215
350
protected void onClose () throws SQLException {
216
351
xac .close ();
@@ -224,7 +359,9 @@ protected void onClose() throws SQLException {
224
359
ec ,
225
360
xac .getConnection (),
226
361
xac ::getXAResource ,
227
- immediateEnlistment );
362
+ null , // no Xid consumer
363
+ immediateEnlistment ,
364
+ preemptiveEnlistmentChecks );
228
365
}
229
366
230
367
0 commit comments