/
DriverProvidedXADataSource.java
92 lines (79 loc) · 3.58 KB
/
DriverProvidedXADataSource.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
package io.narayana;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.util.Properties;
import javax.sql.XADataSource;
import jakarta.transaction.TransactionManager;
import com.arjuna.ats.jdbc.TransactionalDriver;
import io.narayana.util.CodeUtils;
import io.narayana.util.DBUtils;
/**
* <p>
* Usage of {@link TransactionalDriver} managing the transactionality over jdbc connection where
* the <code>ProvidedXADataSourceConnection</code> implementation is used beneath.
* <p>
* {@link XADataSource} is registered to the Narayana transactional driver directly by
* providing it as a property.<br>
* The driver provides connection coming from the provided {@link XADataSource}
* and ensures work done on the connection is part of the local transaction
* which is enlisted to the existing global transaction managed by transaction manager.
*
* <p>
* NOTE: if driver is not loaded directly when they are on classpath the manual registration could
* be needed in similar way as it's
* <p>
* <code>
* // jdbc.drivers is used by DriverManager to class load the driver classes<br>
* // adding the h2 driver<br>
* Properties p = System.getProperties();<br>
* p.put("jdbc.drivers", Driver.class.getName());<br>
* System.setProperties(p);<br>
* // registering narayana jdbc driver to the driver manager<br>
* DriverManager.registerDriver(new TransactionalDriver());<br>
* </code>
*/
public class DriverProvidedXADataSource {
private Connection conn1, conn2;
public void process(Runnable middleAction) throws Exception {
//jdbc:arjuna: <nothing, XADataSource is provided directly,
// the prefix as whole URL defines only the fact we want to use the Narayana transactional driver>
String transactionDriverDefinitionUrl = TransactionalDriver.arjunaDriver;
XADataSource dsXA1 = DBUtils.getXADatasource(DBUtils.DB_1);
Properties props1 = new Properties();
props1.put(TransactionalDriver.XADataSource, dsXA1);
props1.put(TransactionalDriver.userName, DBUtils.DB_USER);
props1.put(TransactionalDriver.password, DBUtils.DB_PASSWORD);
props1.put(TransactionalDriver.poolConnections, "true"); // default
props1.put(TransactionalDriver.maxConnections, "50"); // JBTM-2976
conn1 = DriverManager.getConnection(transactionDriverDefinitionUrl, props1);
XADataSource dsXA2 = DBUtils.getXADatasource(DBUtils.DB_2);
Properties props2 = new Properties();
props2.put(TransactionalDriver.XADataSource, dsXA2);
props2.put(TransactionalDriver.userName, DBUtils.DB_USER);
props2.put(TransactionalDriver.password, DBUtils.DB_PASSWORD);
conn2 = DriverManager.getConnection(transactionDriverDefinitionUrl, props2);
TransactionManager tm = com.arjuna.ats.jta.TransactionManager.transactionManager();
tm.begin();
PreparedStatement ps1 = conn1.prepareStatement(DBUtils.INSERT_STATEMENT);
ps1.setInt(1, 1);
ps1.setString(2, "Arjuna");
PreparedStatement ps2 = conn2.prepareStatement(DBUtils.INSERT_STATEMENT);
ps2.setInt(1, 1);
ps2.setString(2, "Narayana");
try {
ps1.executeUpdate();
middleAction.run();
ps2.executeUpdate();
tm.commit();
} catch (Exception e) {
tm.rollback();
throw e;
}
}
public void closeConnections() {
CodeUtils.swallowException(() -> conn1.rollback());
CodeUtils.swallowException(() -> conn2.rollback());
CodeUtils.closeMultiple(conn1, conn2);
}
}