1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.dbcp2.managed;
19
20 import static org.junit.jupiter.api.Assertions.fail;
21
22 import java.sql.Connection;
23 import java.sql.PreparedStatement;
24 import java.sql.ResultSet;
25 import java.sql.SQLException;
26 import java.sql.Timestamp;
27 import java.time.Duration;
28
29 import javax.transaction.RollbackException;
30 import javax.transaction.Status;
31
32 import org.apache.commons.dbcp2.Utils;
33 import org.junit.jupiter.api.AfterEach;
34 import org.junit.jupiter.api.Assertions;
35 import org.junit.jupiter.api.BeforeEach;
36 import org.junit.jupiter.api.Test;
37
38 import com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionManagerImple;
39 import com.arjuna.ats.jta.common.jtaPropertyManager;
40
41
42
43
44 public class TestConnectionWithNarayana {
45 private static final String CREATE_STMT = "CREATE TABLE TEST_DATA (KEY1 VARCHAR(100), ID BIGINT, VALUE1 DOUBLE PRECISION, INFO TEXT, TS TIMESTAMP)";
46 private static final String INSERT_STMT = "INSERT INTO TEST_DATA (KEY1, ID, VALUE1, INFO, TS) VALUES (?,?,?,?,?)";
47 private static final String SELECT_STMT = "SELECT KEY1, ID, VALUE1, INFO, TS FROM TEST_DATA LIMIT 1";
48 private static final String PAYLOAD;
49 private static final String DROP_STMT = "DROP TABLE TEST_DATA";
50
51 static {
52 final StringBuilder sb = new StringBuilder();
53 sb.append("Start");
54 sb.append("payload");
55 for (int i = 0; i < 10000; i++) {
56 sb.append("...");
57 sb.append(i);
58 }
59 sb.append("End");
60 sb.append("payload");
61
62 PAYLOAD = sb.toString();
63 }
64
65 private BasicManagedDataSource mds;
66
67 @BeforeEach
68 public void setUp() throws Exception {
69 jtaPropertyManager.getJTAEnvironmentBean().setLastResourceOptimisationInterfaceClassName(
70 "org.apache.commons.dbcp2.managed.LocalXAConnectionFactory$LocalXAResource");
71 mds = new BasicManagedDataSource();
72 mds.setTransactionManager(new TransactionManagerImple());
73 mds.setDriverClassName("org.h2.Driver");
74 mds.setUrl("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1");
75
76 mds.setMaxTotal(80);
77 mds.setMinIdle(0);
78 mds.setMaxIdle(80);
79 mds.setMinEvictableIdle(Duration.ofSeconds(10));
80 mds.setDurationBetweenEvictionRuns(Duration.ofSeconds(10));
81 mds.setLogAbandoned(true);
82 mds.setMaxWait(Duration.ofSeconds(2));
83 mds.setRemoveAbandonedOnMaintenance(true);
84 mds.setRemoveAbandonedOnBorrow(true);
85
86 mds.setRemoveAbandonedTimeout(Duration.ofSeconds(10));
87 mds.setLogExpiredConnections(true);
88 mds.setLifo(false);
89
90 try (final Connection conn = mds.getConnection()) {
91 try (final PreparedStatement ps = conn.prepareStatement(CREATE_STMT)) {
92 ps.execute();
93 }
94 }
95 }
96
97 @AfterEach
98 public void tearDown() throws Exception {
99 try (final Connection conn = mds.getConnection()) {
100 try (final PreparedStatement ps = conn.prepareStatement(DROP_STMT)) {
101 ps.execute();
102 }
103 }
104 Utils.closeQuietly(mds);
105 }
106
107 @Test
108 public void testConnectionCommitAfterTimeout() throws Exception {
109 mds.getTransactionManager().setTransactionTimeout(1);
110 mds.getTransactionManager().begin();
111 try (Connection conn = mds.getConnection()) {
112 do {
113 Thread.sleep(1000);
114 } while (mds.getTransactionManager().getTransaction().getStatus() != Status.STATUS_ROLLEDBACK);
115
116 Thread.sleep(1000);
117 try {
118 conn.commit();
119 fail("Should not work after timeout");
120 } catch (final SQLException e) {
121
122 Assertions.assertEquals("Commit can not be set while enrolled in a transaction", e.getMessage());
123 }
124 mds.getTransactionManager().rollback();
125 }
126
127 Assertions.assertEquals(0, mds.getNumActive());
128 }
129
130 @Test
131 public void testConnectionInTimeout() throws Exception {
132 Connection conn = null;
133 PreparedStatement ps = null;
134 for (int i = 0; i < 5; i++) {
135 try {
136 mds.getTransactionManager().setTransactionTimeout(1);
137 mds.getTransactionManager().begin();
138
139 conn = mds.getConnection();
140 ps = conn.prepareStatement(INSERT_STMT);
141 ps.setString(1, Thread.currentThread().getName());
142 ps.setLong(2, i);
143 ps.setDouble(3, new java.util.Random().nextDouble());
144 ps.setString(4, PAYLOAD);
145 ps.setTimestamp(5, new Timestamp(System.currentTimeMillis()));
146 ps.execute();
147
148 int n = 0;
149 do {
150 if (mds.getTransactionManager().getTransaction().getStatus() != Status.STATUS_ACTIVE) {
151 n++;
152 }
153 try (Connection c = mds.getConnection(); PreparedStatement ps2 = c.prepareStatement(SELECT_STMT); ResultSet rs = ps2.executeQuery()) {
154
155 }
156 } while (n < 2);
157
158 ps.close();
159 ps = null;
160 conn.close();
161 conn = null;
162
163 try {
164 mds.getTransactionManager().commit();
165 fail("Should not have been able to commit");
166 } catch (final RollbackException e) {
167
168 if (mds.getTransactionManager().getTransaction() != null) {
169
170 mds.getTransactionManager().rollback();
171 }
172 }
173 } catch (final Exception e) {
174 if (mds.getTransactionManager().getTransaction() != null) {
175
176 mds.getTransactionManager().rollback();
177 }
178 } finally {
179 if (ps != null) {
180 ps.close();
181 }
182 if (conn != null) {
183 conn.close();
184 }
185 }
186 Assertions.assertEquals(0, mds.getNumActive());
187 }
188 }
189
190 @Test
191 public void testRepeatedGetConnectionInTimeout() throws Exception {
192 mds.getTransactionManager().setTransactionTimeout(1);
193 mds.getTransactionManager().begin();
194
195 try {
196 do {
197 Thread.sleep(1000);
198 } while (mds.getTransactionManager().getTransaction().getStatus() != Status.STATUS_ROLLEDBACK);
199
200 Thread.sleep(1000);
201 try (Connection conn = mds.getConnection()) {
202 fail("Should not get the connection 1");
203 } catch (final SQLException e) {
204 if (!e.getCause().getClass().equals(IllegalStateException.class)) {
205 throw e;
206 }
207 try (Connection conn = mds.getConnection()) {
208 fail("Should not get connection 2");
209 } catch (final SQLException e2) {
210 if (!e2.getCause().getClass().equals(IllegalStateException.class)) {
211 throw e2;
212 }
213 }
214 }
215 } finally {
216 mds.getTransactionManager().rollback();
217 }
218 Assertions.assertEquals(0, mds.getNumActive());
219 }
220 }