1 package org.synchronoss.cpo.jdbc.jta;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 import static org.testng.Assert.*;
26
27 import java.util.ArrayList;
28 import java.util.Collection;
29 import java.util.stream.Stream;
30 import javax.transaction.xa.XAException;
31 import javax.transaction.xa.XAResource;
32 import javax.transaction.xa.Xid;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
35 import org.synchronoss.cpo.core.CpoAdapter;
36 import org.synchronoss.cpo.core.CpoAdapterFactoryManager;
37 import org.synchronoss.cpo.core.CpoOrderBy;
38 import org.synchronoss.cpo.core.CpoQuery;
39 import org.synchronoss.cpo.core.helper.ExceptionHelper;
40 import org.synchronoss.cpo.core.jta.CpoXaError;
41 import org.synchronoss.cpo.jdbc.ValueObject;
42 import org.synchronoss.cpo.jdbc.adapter.JdbcStatics;
43 import org.synchronoss.cpo.jdbc.adapter.ValueObjectFactory;
44 import org.testng.annotations.AfterMethod;
45 import org.testng.annotations.BeforeMethod;
46 import org.testng.annotations.Parameters;
47 import org.testng.annotations.Test;
48
49
50 public class JdbcXaResourceTest {
51
52
53 private static final int IDB = 2600000;
54 private static final Logger logger = LoggerFactory.getLogger(JdbcXaResourceTest.class);
55 private CpoAdapter cpoAdapter = null;
56 private JdbcCpoXaAdapter cpoXaAdapter1 = null;
57 private JdbcCpoXaAdapter cpoXaAdapter2 = null;
58 private ArrayList<ValueObject> al = new ArrayList<>();
59 private boolean isXaSupported = true;
60
61
62 public JdbcXaResourceTest() {}
63
64
65
66
67
68 @Parameters({"db.xasupport"})
69 @BeforeMethod
70 public void setUp(boolean xaSupport) {
71 String method = "setUp:";
72 isXaSupported = xaSupport;
73
74 try {
75 cpoAdapter = CpoAdapterFactoryManager.getCpoAdapter(JdbcStatics.ADAPTER_CONTEXT_JDBC);
76 cpoXaAdapter1 =
77 (JdbcCpoXaAdapter)
78 CpoAdapterFactoryManager.getCpoXaAdapter(JdbcStatics.ADAPTER_CONTEXT_JDBC);
79 cpoXaAdapter2 =
80 (JdbcCpoXaAdapter)
81 CpoAdapterFactoryManager.getCpoXaAdapter(JdbcStatics.ADAPTER_CONTEXT_JDBC);
82 assertNotNull(cpoXaAdapter1, method + "CpoXaAdapter1 is null");
83 assertNotNull(cpoXaAdapter2, method + "CpoXaAdapter2 is null");
84 } catch (Exception e) {
85 fail(method + ExceptionHelper.getLocalizedMessage(e));
86 }
87 }
88
89
90 @AfterMethod
91 public void tearDown() {
92 String method = "tearDown:";
93 try {
94 cpoAdapter.deleteBeans(al);
95 } catch (Exception e) {
96 fail(method + e.getMessage());
97 } finally {
98 al.clear();
99 }
100
101 cpoAdapter = null;
102 cpoXaAdapter1 = null;
103 cpoXaAdapter2 = null;
104 }
105
106
107 @Test
108 public void testCoordination() {
109 if (isXaSupported) {
110 String method = "testCoordination:";
111 ValueObject valObj1 = ValueObjectFactory.createValueObject(IDB + 1);
112 ValueObject valObj2 = ValueObjectFactory.createValueObject(IDB + 2);
113 al.add(valObj1);
114 al.add(valObj2);
115
116 Xid xid1 = new MyXid(100, new byte[] {0x01}, new byte[] {0x02});
117 Xid xid2 = new MyXid(100, new byte[] {0x11}, new byte[] {0x22});
118
119 try {
120 cpoXaAdapter1.start(xid1, XAResource.TMNOFLAGS);
121 cpoXaAdapter2.start(xid2, XAResource.TMNOFLAGS);
122 cpoXaAdapter1.insertBean(valObj1);
123 cpoXaAdapter2.insertBean(valObj2);
124 cpoXaAdapter1.end(xid1, XAResource.TMSUCCESS);
125 cpoXaAdapter2.end(xid2, XAResource.TMSUCCESS);
126
127 cpoXaAdapter1.prepare(xid1);
128 cpoXaAdapter2.prepare(xid2);
129
130 cpoXaAdapter1.commit(xid1, false);
131 cpoXaAdapter2.commit(xid2, false);
132
133 CpoOrderBy cob = cpoXaAdapter1.newOrderBy(ValueObject.ATTR_ID, true);
134 Collection<CpoOrderBy> colCob = new ArrayList<>();
135 colCob.add(cob);
136
137 ValueObject valObj = ValueObjectFactory.createValueObject();
138 try (Stream<ValueObject> beans =
139 cpoXaAdapter1.retrieveBeans(
140 CpoQuery.group(ValueObject.FG_LIST_NULL).orderBys(colCob), valObj)) {
141 var list =
142 beans
143 .filter(b -> Math.abs(b.getId()) >= IDB && Math.abs(b.getId()) < IDB + 100000)
144 .toList();
145 var rvo = list.getFirst();
146 assertEquals(rvo.getId(), IDB + 1, "1 != " + rvo.getId());
147 assertEquals(list.size(), 2, "list size is " + list.size());
148 assertEquals(list.get(0).getId(), IDB + 1, "ValuObject(1) is missing");
149 assertEquals(list.get(1).getId(), IDB + 2, "ValuObject(2) is missing");
150 assertEquals(cpoXaAdapter1.deleteBeans(al), 2);
151 }
152 } catch (Exception e) {
153 fail(method + ExceptionHelper.getLocalizedMessage(e));
154 } finally {
155 try {
156 cpoXaAdapter1.close(xid1);
157 } catch (Exception ignored) {
158 }
159 try {
160 cpoXaAdapter1.close(xid2);
161 } catch (Exception ignored) {
162 }
163 }
164 } else {
165 logger.error(cpoAdapter.getDataSourceName() + " does not support XA Transactions");
166 }
167 }
168
169
170 @Test
171 public void testRollback() {
172 if (isXaSupported) {
173 String method = "testRollback:";
174 ValueObject valObj1 = ValueObjectFactory.createValueObject(IDB + 1);
175 ValueObject valObj2 = ValueObjectFactory.createValueObject(IDB + 2);
176 al.add(valObj1);
177 al.add(valObj2);
178
179 Xid xid1 = new MyXid(100, new byte[] {0x01}, new byte[] {0x02});
180 Xid xid2 = new MyXid(100, new byte[] {0x11}, new byte[] {0x22});
181
182 try {
183 cpoXaAdapter1.start(xid1, XAResource.TMNOFLAGS);
184 cpoXaAdapter2.start(xid2, XAResource.TMNOFLAGS);
185 cpoXaAdapter1.insertBean(valObj1);
186 cpoXaAdapter2.insertBean(valObj2);
187 cpoXaAdapter1.end(xid1, XAResource.TMSUCCESS);
188 cpoXaAdapter2.end(xid2, XAResource.TMSUCCESS);
189
190 cpoXaAdapter1.prepare(xid1);
191 cpoXaAdapter2.prepare(xid2);
192
193 cpoXaAdapter1.rollback(xid1);
194 cpoXaAdapter2.rollback(xid2);
195
196 ValueObject valObj = ValueObjectFactory.createValueObject();
197 try (Stream<ValueObject> beans =
198 cpoAdapter.retrieveBeans(ValueObject.FG_LIST_NULL, valObj)) {
199 var list =
200 beans
201 .filter(b -> Math.abs(b.getId()) >= IDB && Math.abs(b.getId()) < IDB + 100000)
202 .toList();
203 assertTrue(list.isEmpty(), "list SHOULD BE EMPTY");
204 }
205 } catch (Exception e) {
206 fail(method + ExceptionHelper.getLocalizedMessage(e));
207 } finally {
208 try {
209 cpoXaAdapter1.close(xid1);
210 } catch (Exception ignored) {
211 }
212 try {
213 cpoXaAdapter1.close(xid2);
214 } catch (Exception ignored) {
215 }
216 }
217 } else {
218 logger.error(cpoAdapter.getDataSourceName() + " does not support XA Transactions");
219 }
220 }
221
222
223 @Test
224 public void testRecover() {
225 if (isXaSupported) {
226 String method = "testRecover:";
227 ValueObject valObj = ValueObjectFactory.createValueObject(IDB + 1);
228 al.add(valObj);
229
230 Xid xid = new MyXid(100, new byte[] {0x01}, new byte[] {0x02});
231 try {
232
233 cpoXaAdapter1.start(xid, XAResource.TMNOFLAGS);
234 cpoXaAdapter1.insertBean(valObj);
235 cpoXaAdapter1.end(xid, XAResource.TMSUCCESS);
236 cpoXaAdapter1.prepare(xid);
237
238
239
240 Xid[] recoveredXids =
241 cpoXaAdapter2.recover(XAResource.TMSTARTRSCAN | XAResource.TMENDRSCAN);
242
243 assertNotNull(recoveredXids);
244 assertTrue(recoveredXids.length > 0);
245
246 boolean xidFound = false;
247
248 for (int i = 0; i < recoveredXids.length; i++) {
249 if (recoveredXids[i] != null && recoveredXids[i].equals(xid)) {
250 xidFound = true;
251
252 break;
253 }
254 }
255
256 assertTrue(xidFound);
257
258 recoveredXids = cpoXaAdapter1.recover(XAResource.TMSTARTRSCAN);
259
260 assertNotNull(recoveredXids);
261 assertTrue(recoveredXids.length > 0);
262
263 xidFound = false;
264
265 for (int i = 0; i < recoveredXids.length; i++) {
266 if (recoveredXids[i] != null && recoveredXids[i].equals(xid)) {
267 xidFound = true;
268
269 break;
270 }
271 }
272
273 assertTrue(xidFound);
274
275
276 cpoXaAdapter1.recover(XAResource.TMSTARTRSCAN);
277 cpoXaAdapter1.recover(XAResource.TMENDRSCAN);
278 cpoXaAdapter1.recover(XAResource.TMSTARTRSCAN | XAResource.TMENDRSCAN);
279
280
281 try {
282 cpoXaAdapter1.recover(XAResource.TMSUCCESS);
283 fail("XAException should have been thrown");
284 } catch (XAException xae) {
285 assertTrue(xae.getLocalizedMessage().startsWith(CpoXaError.XAER_INVAL.toString()));
286 }
287 } catch (Exception e) {
288 fail(method + ExceptionHelper.getLocalizedMessage(e));
289 } finally {
290 try {
291 cpoXaAdapter1.close(xid);
292 } catch (Exception ignored) {
293 }
294 }
295 } else {
296 logger.error(cpoAdapter.getDataSourceName() + " does not support XA Transactions");
297 }
298 }
299
300 @Test
301 public void testSuspendableTx() throws Exception {
302 if (isXaSupported) {
303 String method = "testSuspendableTx:";
304 ValueObject valObj = ValueObjectFactory.createValueObject(IDB + 1);
305 al.add(valObj);
306
307 Xid xid = new MyXid(100, new byte[] {0x01}, new byte[] {0x02});
308
309 try {
310 cpoXaAdapter1.start(xid, XAResource.TMNOFLAGS);
311 cpoXaAdapter1.retrieveBean(valObj);
312 cpoXaAdapter1.end(xid, XAResource.TMSUSPEND);
313 cpoXaAdapter1.start(xid, XAResource.TMRESUME);
314 cpoXaAdapter1.retrieveBean(valObj);
315 cpoXaAdapter1.end(xid, XAResource.TMSUCCESS);
316 cpoXaAdapter1.commit(xid, true);
317
318 cpoXaAdapter1.close(xid);
319
320 cpoXaAdapter1.start(xid, XAResource.TMNOFLAGS);
321 cpoXaAdapter1.retrieveBean(valObj);
322 cpoXaAdapter1.end(xid, XAResource.TMSUCCESS);
323 cpoXaAdapter1.start(xid, XAResource.TMJOIN);
324 cpoXaAdapter1.retrieveBean(valObj);
325 cpoXaAdapter1.end(xid, XAResource.TMSUCCESS);
326 cpoXaAdapter1.commit(xid, true);
327 } catch (Exception e) {
328 fail(method + ExceptionHelper.getLocalizedMessage(e));
329 } finally {
330 try {
331 cpoXaAdapter1.close(xid);
332 } catch (Exception ignored) {
333 }
334 }
335 } else {
336 logger.error(cpoAdapter.getDataSourceName() + " does not support XA Transactions");
337 }
338 }
339
340 @Test
341 public void testCommit() {
342 if (isXaSupported) {
343 String method = "testCommit:";
344 ValueObject valObj = ValueObjectFactory.createValueObject(IDB + 1);
345 al.add(valObj);
346 int ret;
347
348 Xid xid1 = new MyXid(100, new byte[] {0x01}, new byte[] {0x02});
349 try {
350
351 cpoXaAdapter1.start(xid1, XAResource.TMNOFLAGS);
352 cpoXaAdapter1.insertBean(valObj);
353 cpoXaAdapter1.end(xid1, XAResource.TMSUCCESS);
354
355
356 assertNull(cpoAdapter.retrieveBean(valObj));
357
358 ret = cpoXaAdapter1.prepare(xid1);
359 if (ret == XAResource.XA_OK) {
360 cpoXaAdapter1.commit(xid1, false);
361 }
362
363
364 assertNotNull(cpoAdapter.retrieveBean(valObj));
365
366 } catch (Exception e) {
367 fail(method + ExceptionHelper.getLocalizedMessage(e));
368 } finally {
369 try {
370 cpoXaAdapter1.close(xid1);
371 } catch (Exception ignored) {
372 }
373 }
374 } else {
375 logger.error(cpoAdapter.getDataSourceName() + " does not support XA Transactions");
376 }
377 }
378
379 @Test
380 public void testRollback2() {
381 if (isXaSupported) {
382 String method = "testRollback2:";
383 ValueObject valObj = ValueObjectFactory.createValueObject(IDB + 1);
384 al.add(valObj);
385 int ret;
386
387 Xid xid1 = new MyXid(100, new byte[] {0x01}, new byte[] {0x02});
388 try {
389
390 cpoXaAdapter1.start(xid1, XAResource.TMNOFLAGS);
391 cpoXaAdapter1.insertBean(valObj);
392 cpoXaAdapter1.end(xid1, XAResource.TMSUCCESS);
393
394
395 assertNull(cpoAdapter.retrieveBean(valObj));
396
397 ret = cpoXaAdapter1.prepare(xid1);
398 if (ret == XAResource.XA_OK) {
399 cpoXaAdapter1.rollback(xid1);
400 }
401
402
403 assertNull(cpoAdapter.retrieveBean(valObj));
404 } catch (Exception e) {
405 fail(method + ExceptionHelper.getLocalizedMessage(e));
406 } finally {
407 try {
408 cpoXaAdapter1.close(xid1);
409 } catch (Exception ignored) {
410 }
411 }
412 } else {
413 logger.error(cpoAdapter.getDataSourceName() + " does not support XA Transactions");
414 }
415 }
416
417 @Test
418 public void testSuspend() {
419 if (isXaSupported) {
420 String method = "testSuspend:";
421 ValueObject valObj1 = ValueObjectFactory.createValueObject(IDB + 1);
422 ValueObject valObj2 = ValueObjectFactory.createValueObject(IDB + 2);
423 ValueObject valObj3 = ValueObjectFactory.createValueObject(IDB + 3);
424 al.add(valObj1);
425 al.add(valObj2);
426 al.add(valObj3);
427 int ret;
428
429 Xid xid1 = new MyXid(100, new byte[] {0x01}, new byte[] {0x02});
430
431 try {
432 cpoXaAdapter1.start(xid1, XAResource.TMNOFLAGS);
433 cpoXaAdapter1.insertBean(valObj1);
434 cpoXaAdapter1.end(xid1, XAResource.TMSUSPEND);
435
436
437
438 cpoXaAdapter1.insertBean(valObj2);
439
440 cpoXaAdapter1.start(xid1, XAResource.TMRESUME);
441 cpoXaAdapter1.insertBean(valObj3);
442 cpoXaAdapter1.end(xid1, XAResource.TMSUCCESS);
443
444 ret = cpoXaAdapter1.prepare(xid1);
445 if (ret == XAResource.XA_OK) {
446 cpoXaAdapter1.rollback(xid1);
447 }
448
449 ValueObject valObj = ValueObjectFactory.createValueObject();
450 try (Stream<ValueObject> beans =
451 cpoAdapter.retrieveBeans(ValueObject.FG_LIST_NULL, valObj)) {
452 var list =
453 beans
454 .filter(b -> Math.abs(b.getId()) >= IDB && Math.abs(b.getId()) < IDB + 100000)
455 .toList();
456 assertEquals(list.size(), 1, "list size is " + list.size());
457 assertEquals(list.getFirst().getId(), valObj2.getId(), "valObj2 is missing");
458 }
459 } catch (Exception e) {
460 fail(method + ExceptionHelper.getLocalizedMessage(e));
461 } finally {
462 try {
463 cpoXaAdapter1.close(xid1);
464 } catch (Exception ignored) {
465 }
466 }
467 } else {
468 logger.error(cpoAdapter.getDataSourceName() + " does not support XA Transactions");
469 }
470 }
471
472 @Test
473 public void testMultiTrx() {
474 if (isXaSupported) {
475 String method = "testMultiTrx:";
476 ValueObject valObj1 = ValueObjectFactory.createValueObject(IDB + 1);
477 ValueObject valObj2 = ValueObjectFactory.createValueObject(IDB + 2);
478 al.add(valObj1);
479 al.add(valObj2);
480 int ret;
481
482 Xid xid1 = new MyXid(100, new byte[] {0x01}, new byte[] {0x02});
483 Xid xid2 = new MyXid(100, new byte[] {0x11}, new byte[] {0x22});
484 try {
485
486 cpoXaAdapter1.start(xid1, XAResource.TMNOFLAGS);
487 cpoXaAdapter1.insertBean(valObj1);
488 cpoXaAdapter1.end(xid1, XAResource.TMSUCCESS);
489
490 cpoXaAdapter1.start(xid2, XAResource.TMNOFLAGS);
491
492
493
494 ret = cpoXaAdapter1.prepare(xid1);
495 if (ret == XAResource.XA_OK) {
496 cpoXaAdapter1.commit(xid1, false);
497 }
498
499 cpoXaAdapter1.insertBean(valObj2);
500 cpoXaAdapter1.end(xid2, XAResource.TMSUCCESS);
501
502 ret = cpoXaAdapter1.prepare(xid2);
503 if (ret == XAResource.XA_OK) {
504 cpoXaAdapter1.rollback(xid2);
505 }
506
507
508 ValueObject valObj = ValueObjectFactory.createValueObject();
509 try (Stream<ValueObject> beans =
510 cpoAdapter.retrieveBeans(ValueObject.FG_LIST_NULL, valObj)) {
511 var list =
512 beans
513 .filter(b -> Math.abs(b.getId()) >= IDB && Math.abs(b.getId()) < IDB + 100000)
514 .toList();
515 assertEquals(list.size(), 1, "list size is " + list.size());
516 assertEquals(list.getFirst().getId(), valObj1.getId(), "valObj2 is missing");
517 }
518 } catch (Exception e) {
519 fail(method + ExceptionHelper.getLocalizedMessage(e));
520 } finally {
521 try {
522 cpoXaAdapter1.close(xid1);
523 } catch (Exception ignored) {
524 }
525 try {
526 cpoXaAdapter1.close(xid2);
527 } catch (Exception ignored) {
528 }
529 }
530 } else {
531 logger.error(cpoAdapter.getDataSourceName() + " does not support XA Transactions");
532 }
533 }
534
535 @Test
536 public void testJoin() {
537 if (isXaSupported) {
538 String method = "testJoin:";
539 ValueObject valObj1 = ValueObjectFactory.createValueObject(IDB + 1);
540 ValueObject valObj2 = ValueObjectFactory.createValueObject(IDB + 2);
541 al.add(valObj1);
542 al.add(valObj2);
543 int ret;
544
545 Xid xid1 = new MyXid(100, new byte[] {0x01}, new byte[] {0x02});
546 try {
547
548 cpoXaAdapter1.start(xid1, XAResource.TMNOFLAGS);
549 cpoXaAdapter1.insertBean(valObj1);
550 cpoXaAdapter1.end(xid1, XAResource.TMSUCCESS);
551
552 if (cpoXaAdapter2.isSameRM(cpoXaAdapter1)) {
553 cpoXaAdapter2.start(xid1, XAResource.TMJOIN);
554 cpoXaAdapter2.insertBean(valObj2);
555 cpoXaAdapter2.end(xid1, XAResource.TMSUCCESS);
556 } else {
557 fail("Unable to join XAResources with the same resource manager");
558 }
559
560 ret = cpoXaAdapter1.prepare(xid1);
561 if (ret == XAResource.XA_OK) {
562 cpoXaAdapter1.commit(xid1, false);
563 }
564
565
566 ValueObject valObj = ValueObjectFactory.createValueObject();
567 try (Stream<ValueObject> beans =
568 cpoAdapter.retrieveBeans(ValueObject.FG_LIST_NULL, valObj)) {
569 var list =
570 beans
571 .filter(b -> Math.abs(b.getId()) >= IDB && Math.abs(b.getId()) < IDB + 100000)
572 .toList();
573 assertEquals(list.size(), 2, "list size is " + list.size());
574 }
575 } catch (Exception e) {
576 fail(method + ExceptionHelper.getLocalizedMessage(e));
577 } finally {
578 try {
579 cpoXaAdapter1.close(xid1);
580 } catch (Exception ignored) {
581 }
582 }
583 } else {
584 logger.error(cpoAdapter.getDataSourceName() + " does not support XA Transactions");
585 }
586 }
587
588 @Test
589 public void testRecover2() {
590 if (isXaSupported) {
591 String method = "testRecover2:";
592 ValueObject valObj1 = ValueObjectFactory.createValueObject(IDB + 1);
593 ValueObject valObj2 = ValueObjectFactory.createValueObject(IDB + 2);
594 ValueObject valObj3 = ValueObjectFactory.createValueObject(IDB + 3);
595 al.add(valObj1);
596 al.add(valObj2);
597 al.add(valObj3);
598
599 Xid[] xids;
600
601 Xid xid1 = new MyXid(100, new byte[] {0x01}, new byte[] {0x02});
602 Xid xid2 = new MyXid(100, new byte[] {0x11}, new byte[] {0x22});
603 Xid xid3 = new MyXid(100, new byte[] {0x13}, new byte[] {0x23});
604
605
606 try {
607
608 cpoXaAdapter1.start(xid1, XAResource.TMNOFLAGS);
609 cpoXaAdapter1.insertBean(valObj1);
610 cpoXaAdapter1.end(xid1, XAResource.TMSUCCESS);
611 cpoXaAdapter1.prepare(xid1);
612
613 cpoXaAdapter1.start(xid2, XAResource.TMNOFLAGS);
614 cpoXaAdapter1.insertBean(valObj2);
615 cpoXaAdapter1.end(xid2, XAResource.TMSUSPEND);
616
617 cpoXaAdapter1.start(xid3, XAResource.TMNOFLAGS);
618 cpoXaAdapter1.insertBean(valObj3);
619 cpoXaAdapter1.end(xid3, XAResource.TMFAIL);
620
621 xids = cpoXaAdapter1.recover(XAResource.TMSTARTRSCAN | XAResource.TMENDRSCAN);
622 assertTrue(xids.length > 0, "In progress resources must be created");
623 assertEquals(1, xids.length, "There should be 1 in progress transaction");
624 for (int i = 0; xids != null && i < xids.length; i++) {
625 try {
626 cpoXaAdapter1.rollback(xids[i]);
627 } catch (XAException ex) {
628 try {
629 cpoXaAdapter1.forget(xids[i]);
630 } catch (XAException ex1) {
631 fail("rollback/forget failed: " + ex1.getMessage());
632 }
633 }
634 }
635 } catch (Exception e) {
636 fail(method + ExceptionHelper.getLocalizedMessage(e));
637 } finally {
638 try {
639 cpoXaAdapter1.close(xid1);
640 } catch (Exception ignored) {
641 }
642 try {
643 cpoXaAdapter1.close(xid2);
644 } catch (Exception ignored) {
645 }
646 try {
647 cpoXaAdapter1.close(xid3);
648 } catch (Exception ignored) {
649 }
650 }
651 } else {
652 logger.error(cpoAdapter.getDataSourceName() + " does not support XA Transactions");
653 }
654 }
655
656 @Test
657 public void testNothing() {}
658
659 public class MyXid implements Xid {
660 protected int formatId;
661 protected byte[] gtrid;
662 protected byte[] bqual;
663
664 public MyXid() {}
665
666 public MyXid(int formatId, byte gtrid[], byte bqual[]) {
667 this.formatId = formatId;
668 this.gtrid = gtrid;
669 this.bqual = bqual;
670 }
671
672 public int getFormatId() {
673 return formatId;
674 }
675
676 public byte[] getBranchQualifier() {
677 return bqual;
678 }
679
680 public byte[] getGlobalTransactionId() {
681 return gtrid;
682 }
683 }
684 }