View Javadoc
1   /*
2   
3     Licensed to the Apache Software Foundation (ASF) under one or more
4     contributor license agreements.  See the NOTICE file distributed with
5     this work for additional information regarding copyright ownership.
6     The ASF licenses this file to You under the Apache License, Version 2.0
7     (the "License"); you may not use this file except in compliance with
8     the License.  You may obtain a copy of the License at
9   
10        https://www.apache.org/licenses/LICENSE-2.0
11  
12     Unless required by applicable law or agreed to in writing, software
13     distributed under the License is distributed on an "AS IS" BASIS,
14     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15     See the License for the specific language governing permissions and
16     limitations under the License.
17   */
18  package org.apache.commons.dbcp2.managed;
19  
20  import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
21  import static org.junit.jupiter.api.Assertions.assertEquals;
22  import static org.junit.jupiter.api.Assertions.assertNotNull;
23  import static org.junit.jupiter.api.Assertions.assertNull;
24  import static org.junit.jupiter.api.Assertions.assertThrows;
25  import static org.junit.jupiter.api.Assertions.fail;
26  
27  import java.sql.Connection;
28  import java.sql.SQLException;
29  
30  import javax.sql.XADataSource;
31  import javax.transaction.TransactionManager;
32  import javax.transaction.TransactionSynchronizationRegistry;
33  import javax.transaction.xa.XAException;
34  
35  import org.apache.commons.dbcp2.BasicDataSource;
36  import org.apache.commons.dbcp2.TestBasicDataSource;
37  import org.apache.geronimo.transaction.manager.TransactionManagerImpl;
38  import org.h2.Driver;
39  import org.h2.jdbcx.JdbcDataSource;
40  import org.junit.jupiter.api.Test;
41  import org.junit.jupiter.api.function.ThrowingSupplier;
42  
43  import com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionManagerImple;
44  import com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionSynchronizationRegistryImple;
45  
46  /**
47   * TestSuite for BasicManagedDataSource
48   */
49  public class TestBasicManagedDataSource extends TestBasicDataSource {
50  
51      @Override
52      protected BasicDataSource createDataSource() throws Exception {
53          final BasicManagedDataSource basicManagedDataSource = new BasicManagedDataSource();
54          final TransactionManagerImpl transactionManager = new TransactionManagerImpl();
55          basicManagedDataSource.setTransactionManager(transactionManager);
56          basicManagedDataSource.setTransactionSynchronizationRegistry(transactionManager);
57          return basicManagedDataSource;
58      }
59  
60      @Test
61      void testCreateXaDataSourceNewInstance() throws SQLException, XAException {
62          try (final BasicManagedDataSource basicManagedDataSource = new BasicManagedDataSource()) {
63              basicManagedDataSource.setXADataSource(JdbcDataSource.class.getCanonicalName());
64              basicManagedDataSource.setDriverClassName(Driver.class.getName());
65              basicManagedDataSource.setTransactionManager(new TransactionManagerImpl());
66              assertNotNull(basicManagedDataSource.createConnectionFactory());
67          }
68      }
69  
70      @Test
71      void testCreateXaDataSourceNoInstanceSetAndNoDataSource() throws SQLException, XAException {
72          try (final BasicManagedDataSource basicManagedDataSource = new BasicManagedDataSource()) {
73              basicManagedDataSource.setDriverClassName("org.apache.commons.dbcp2.TesterDriver");
74              basicManagedDataSource.setUrl("jdbc:apache:commons:testdriver");
75              basicManagedDataSource.setTransactionManager(new TransactionManagerImpl());
76              assertNotNull(basicManagedDataSource.createConnectionFactory());
77          }
78      }
79  
80      /**
81       * JIRA: DBCP-294
82       * Verify that PoolableConnections created by BasicManagedDataSource unregister themselves
83       * when reallyClosed.
84       */
85      @Test
86      void testReallyClose() throws Exception {
87          try (final BasicManagedDataSource basicManagedDataSource = new BasicManagedDataSource()) {
88              basicManagedDataSource.setTransactionManager(new TransactionManagerImpl());
89              basicManagedDataSource.setDriverClassName("org.apache.commons.dbcp2.TesterDriver");
90              basicManagedDataSource.setUrl("jdbc:apache:commons:testdriver");
91              basicManagedDataSource.setUsername("userName");
92              basicManagedDataSource.setPassword("password");
93              basicManagedDataSource.setMaxIdle(1);
94              // Create two connections
95              final ManagedConnection<?> conn = (ManagedConnection<?>) basicManagedDataSource.getConnection();
96              assertNotNull(basicManagedDataSource.getTransactionRegistry().getXAResource(conn));
97              final ManagedConnection<?> conn2 = (ManagedConnection<?>) basicManagedDataSource.getConnection();
98              conn2.close(); // Return one connection to the pool
99              conn.close(); // No room at the inn - this will trigger reallyClose(), which should unregister
100             assertThrows(SQLException.class, () -> basicManagedDataSource.getTransactionRegistry().getXAResource(conn),
101                     "Expecting SQLException - XAResources orphaned");
102             conn2.close();
103         }
104     }
105 
106     @Test
107     void testRuntimeExceptionsAreRethrown() throws SQLException, XAException {
108         try (final BasicManagedDataSource basicManagedDataSource = new BasicManagedDataSource()) {
109             basicManagedDataSource.setTransactionManager(new TransactionManagerImpl());
110             basicManagedDataSource.setDriverClassName("org.apache.commons.dbcp2.TesterDriver");
111             basicManagedDataSource.setUrl("jdbc:apache:commons:testdriver");
112             basicManagedDataSource.setUsername("userName");
113             basicManagedDataSource.setPassword("password");
114             basicManagedDataSource.setMaxIdle(1);
115             // results in a NPE
116             assertThrows(NullPointerException.class, () -> basicManagedDataSource.createPoolableConnectionFactory(null));
117         }
118     }
119 
120     @Test
121     void testSetDriverName() throws SQLException {
122         try (final BasicManagedDataSource basicManagedDataSource = new BasicManagedDataSource()) {
123             basicManagedDataSource.setDriverClassName("adams");
124             assertEquals("adams", basicManagedDataSource.getDriverClassName());
125             basicManagedDataSource.setDriverClassName(null);
126             assertNull(basicManagedDataSource.getDriverClassName());
127         }
128     }
129 
130     @Test
131     void testSetNullXaDataSourceInstance() throws SQLException, XAException {
132         try (final BasicManagedDataSource basicManagedDataSource = new BasicManagedDataSource()) {
133             basicManagedDataSource.setTransactionManager(new TransactionManagerImpl());
134             basicManagedDataSource.setDriverClassName("org.apache.commons.dbcp2.TesterDriver");
135             basicManagedDataSource.setUrl("jdbc:apache:commons:testdriver");
136             basicManagedDataSource.setUsername("userName");
137             basicManagedDataSource.setPassword("password");
138             basicManagedDataSource.setMaxIdle(1);
139             basicManagedDataSource.setXaDataSourceInstance(null);
140             assertNull(basicManagedDataSource.getXaDataSourceInstance());
141         }
142     }
143 
144     /** DBCP-564 */
145     @Test
146     void testSetRollbackOnlyBeforeGetConnectionDoesNotLeak() throws Exception {
147         final TransactionManager transactionManager = ((BasicManagedDataSource) ds).getTransactionManager();
148         final int n = 3;
149         ds.setMaxIdle(n);
150         ds.setMaxTotal(n);
151 
152         for (int i = 0; i <= n; i++) { // loop n+1 times
153             transactionManager.begin();
154             transactionManager.setRollbackOnly();
155             try (final Connection conn = getConnection()) {
156                 assertNotNull(conn);
157             }
158             transactionManager.rollback();
159         }
160 
161         assertEquals(0, ds.getNumActive());
162         assertEquals(1, ds.getNumIdle());
163     }
164 
165     @Test
166     void testSetXaDataSourceInstance() throws SQLException, XAException {
167         try (final BasicManagedDataSource basicManagedDataSource = new BasicManagedDataSource()) {
168             basicManagedDataSource.setTransactionManager(new TransactionManagerImpl());
169             basicManagedDataSource.setDriverClassName("org.apache.commons.dbcp2.TesterDriver");
170             basicManagedDataSource.setUrl("jdbc:apache:commons:testdriver");
171             basicManagedDataSource.setUsername("userName");
172             basicManagedDataSource.setPassword("password");
173             basicManagedDataSource.setMaxIdle(1);
174             basicManagedDataSource.setXaDataSourceInstance(new JdbcDataSource());
175             assertNotNull(basicManagedDataSource.createConnectionFactory());
176         }
177     }
178 
179     @Test
180     void testTransactionManagerNotSet() throws SQLException {
181         try (final BasicManagedDataSource basicManagedDataSource = new BasicManagedDataSource()) {
182             assertThrows(SQLException.class, basicManagedDataSource::createConnectionFactory);
183         }
184     }
185 
186     @Test
187     void testTransactionSynchronizationRegistry() throws Exception {
188         try (final BasicManagedDataSource basicManagedDataSource = new BasicManagedDataSource()) {
189             basicManagedDataSource.setTransactionManager(new TransactionManagerImple());
190             final TransactionSynchronizationRegistry tsr = new TransactionSynchronizationRegistryImple();
191             basicManagedDataSource.setTransactionSynchronizationRegistry(tsr);
192             final JdbcDataSource xaDataSource = new JdbcDataSource();
193             xaDataSource.setUrl("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1");
194             basicManagedDataSource.setXaDataSourceInstance(xaDataSource);
195             basicManagedDataSource.setMaxIdle(1);
196 
197             final TransactionManager tm = basicManagedDataSource.getTransactionManager();
198             tm.begin();
199             tsr.registerInterposedSynchronization(new SynchronizationAdapter() {
200                 @Override
201                 public void beforeCompletion() {
202                     try (Connection connection = assertDoesNotThrow((ThrowingSupplier<Connection>) basicManagedDataSource::getConnection)) {
203                         assertNotNull(connection);
204                     } catch (final SQLException e) {
205                         fail(e);
206                     }
207                 }
208             });
209             tm.commit();
210         }
211     }
212 
213     @Test
214     void testXADataSource() throws SQLException {
215         try (final BasicManagedDataSource basicManagedDataSource = new BasicManagedDataSource()) {
216             basicManagedDataSource.setXADataSource("anything");
217             assertEquals("anything", basicManagedDataSource.getXADataSource());
218         }
219     }
220 
221     @Test
222     void testXaDataSourceInstance() throws SQLException {
223         try (final BasicManagedDataSource basicManagedDataSource = new BasicManagedDataSource()) {
224             final XADataSource ds = new JdbcDataSource();
225             basicManagedDataSource.setXaDataSourceInstance(ds);
226             assertEquals(ds, basicManagedDataSource.getXaDataSourceInstance());
227         }
228     }
229 }