View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.dbcp2.datasources;
19  
20  import static org.junit.jupiter.api.Assertions.assertEquals;
21  import static org.junit.jupiter.api.Assertions.assertFalse;
22  import static org.junit.jupiter.api.Assertions.assertNotNull;
23  import static org.junit.jupiter.api.Assertions.assertThrows;
24  import static org.junit.jupiter.api.Assertions.assertTrue;
25  import static org.junit.jupiter.api.Assertions.fail;
26  
27  import java.sql.CallableStatement;
28  import java.sql.Connection;
29  import java.sql.PreparedStatement;
30  import java.sql.ResultSet;
31  import java.sql.SQLException;
32  import java.sql.Statement;
33  import java.time.Duration;
34  import java.util.ArrayList;
35  
36  import javax.sql.DataSource;
37  
38  import org.apache.commons.dbcp2.DelegatingStatement;
39  import org.apache.commons.dbcp2.TestConnectionPool;
40  import org.apache.commons.dbcp2.TesterDriver;
41  import org.apache.commons.dbcp2.cpdsadapter.DriverAdapterCPDS;
42  import org.apache.commons.lang3.ArrayUtils;
43  import org.junit.jupiter.api.BeforeEach;
44  import org.junit.jupiter.api.Test;
45  
46  /**
47   */
48  public class TestSharedPoolDataSource extends TestConnectionPool {
49  
50      /**
51       * There are 3 different prepareCall statement methods so add a little complexity to reduce what would otherwise be lots
52       * of copy and paste.
53       */
54      private static abstract class AbstractPrepareCallCallback {
55          protected Connection conn;
56  
57          abstract CallableStatement getCallableStatement() throws SQLException;
58  
59          void setConnection(final Connection conn) {
60              this.conn = conn;
61          }
62      }
63  
64      /**
65       * There are 6 different prepareStatement statement methods so add a little complexity to reduce what would otherwise be
66       * lots of copy and paste.
67       */
68      private static abstract class AbstractPrepareStatementCallback {
69          protected Connection conn;
70  
71          abstract PreparedStatement prepareStatement() throws SQLException;
72  
73          void setConnection(final Connection conn) {
74              this.conn = conn;
75          }
76      }
77  
78      private static final class CscbString extends AbstractPrepareCallCallback {
79          @Override
80          CallableStatement getCallableStatement() throws SQLException {
81              return conn.prepareCall("{call home()}");
82          }
83      }
84  
85      private static final class CscbStringIntInt extends AbstractPrepareCallCallback {
86          @Override
87          CallableStatement getCallableStatement() throws SQLException {
88              return conn.prepareCall("{call home()}", 0, 0);
89          }
90      }
91  
92      private static final class CscbStringIntIntInt extends AbstractPrepareCallCallback {
93          @Override
94          CallableStatement getCallableStatement() throws SQLException {
95              return conn.prepareCall("{call home()}", 0, 0, 0);
96          }
97      }
98  
99      private static final class PscbString extends AbstractPrepareStatementCallback {
100         @Override
101         PreparedStatement prepareStatement() throws SQLException {
102             return conn.prepareStatement("select * from dual");
103         }
104     }
105 
106     private static final class PscbStringInt extends AbstractPrepareStatementCallback {
107         @Override
108         PreparedStatement prepareStatement() throws SQLException {
109             return conn.prepareStatement("select * from dual", 0);
110         }
111     }
112 
113     private static final class PscbStringIntArray extends AbstractPrepareStatementCallback {
114         @Override
115         PreparedStatement prepareStatement() throws SQLException {
116             return conn.prepareStatement("select * from dual", ArrayUtils.EMPTY_INT_ARRAY);
117         }
118     }
119 
120     private static final class PscbStringIntInt extends AbstractPrepareStatementCallback {
121         @Override
122         PreparedStatement prepareStatement() throws SQLException {
123             return conn.prepareStatement("select * from dual", 0, 0);
124         }
125     }
126 
127     private static final class PscbStringIntIntInt extends AbstractPrepareStatementCallback {
128         @Override
129         PreparedStatement prepareStatement() throws SQLException {
130             return conn.prepareStatement("select * from dual", 0, 0, 0);
131         }
132     }
133 
134     private static final class PscbStringStringArray extends AbstractPrepareStatementCallback {
135         @Override
136         PreparedStatement prepareStatement() throws SQLException {
137             return conn.prepareStatement("select * from dual", ArrayUtils.EMPTY_STRING_ARRAY);
138         }
139     }
140 
141     private DriverAdapterCPDS pcds;
142 
143     private DataSource ds;
144 
145     private void doTestPoolCallableStatements(final AbstractPrepareCallCallback callBack)
146         throws Exception {
147         final DriverAdapterCPDS myPcds = new DriverAdapterCPDS();
148         myPcds.setDriver("org.apache.commons.dbcp2.TesterDriver");
149         myPcds.setUrl("jdbc:apache:commons:testdriver");
150         myPcds.setUser("foo");
151         myPcds.setPassword("bar");
152         myPcds.setPoolPreparedStatements(true);
153         myPcds.setMaxPreparedStatements(10);
154 
155         try (final SharedPoolDataSource spDs = new SharedPoolDataSource()) {
156             spDs.setConnectionPoolDataSource(myPcds);
157             spDs.setMaxTotal(getMaxTotal());
158             spDs.setDefaultMaxWait(getMaxWaitDuration());
159             spDs.setDefaultTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
160 
161             @SuppressWarnings("resource")
162             final DataSource myDs = spDs;
163 
164             try (Connection conn = ds.getConnection()) {
165                 callBack.setConnection(conn);
166 
167                 assertNotNull(conn);
168                 final long l1HashCode;
169                 final long l2HashCode;
170                 try (CallableStatement stmt = callBack.getCallableStatement()) {
171                     assertNotNull(stmt);
172                     l1HashCode = getDelegateHashCode(stmt);
173                     try (ResultSet rset = stmt.executeQuery()) {
174                         assertNotNull(rset);
175                         assertTrue(rset.next());
176                     }
177                 }
178 
179                 try (CallableStatement stmt = callBack.getCallableStatement()) {
180                     assertNotNull(stmt);
181                     l2HashCode = getDelegateHashCode(stmt);
182                     try (ResultSet rset = stmt.executeQuery()) {
183                         assertNotNull(rset);
184                         assertTrue(rset.next());
185                     }
186                 }
187 
188                 // statement pooling is not enabled, we should get different statements
189                 assertTrue(l1HashCode != l2HashCode);
190             }
191 
192             try (Connection conn = myDs.getConnection()) {
193                 callBack.setConnection(conn);
194 
195                 final long l3HashCode;
196                 final long l4HashCode;
197                 try (CallableStatement stmt = callBack.getCallableStatement()) {
198                     assertNotNull(stmt);
199                     l3HashCode = getDelegateHashCode(stmt);
200                     try (ResultSet rset = stmt.executeQuery()) {
201                         assertNotNull(rset);
202                         assertTrue(rset.next());
203                     }
204                 }
205 
206                 try (CallableStatement stmt = callBack.getCallableStatement()) {
207                     assertNotNull(stmt);
208                     l4HashCode = getDelegateHashCode(stmt);
209                     try (ResultSet rset = stmt.executeQuery()) {
210                         assertNotNull(rset);
211                         assertTrue(rset.next());
212                     }
213                 }
214 
215                 // prepared statement pooling is working
216                 assertEquals(l3HashCode, l4HashCode);
217             }
218         }
219     }
220 
221     private void doTestPoolPreparedStatements(final AbstractPrepareStatementCallback psCallBack) throws Exception {
222         final DriverAdapterCPDS mypcds = new DriverAdapterCPDS();
223         mypcds.setDriver("org.apache.commons.dbcp2.TesterDriver");
224         mypcds.setUrl("jdbc:apache:commons:testdriver");
225         mypcds.setUser("foo");
226         mypcds.setPassword("bar");
227         mypcds.setPoolPreparedStatements(true);
228         mypcds.setMaxPreparedStatements(10);
229 
230         try (final SharedPoolDataSource tds = new SharedPoolDataSource()) {
231             tds.setConnectionPoolDataSource(mypcds);
232             tds.setMaxTotal(getMaxTotal());
233             tds.setDefaultMaxWait(getMaxWaitDuration());
234             tds.setDefaultTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
235 
236             @SuppressWarnings("resource")
237             final
238             DataSource myDs = tds;
239 
240             try (Connection conn = ds.getConnection()) {
241                 final long l1HashCode;
242                 final long l2HashCode;
243                 assertNotNull(conn);
244                 psCallBack.setConnection(conn);
245                 try (PreparedStatement stmt = psCallBack.prepareStatement()) {
246                     assertNotNull(stmt);
247                     l1HashCode = getDelegateHashCode(stmt);
248                     try (ResultSet resultSet = stmt.executeQuery()) {
249                         assertNotNull(resultSet);
250                         assertTrue(resultSet.next());
251                     }
252                 }
253 
254                 try (PreparedStatement stmt = psCallBack.prepareStatement()) {
255                     assertNotNull(stmt);
256                     l2HashCode = getDelegateHashCode(stmt);
257                     try (ResultSet resultSet = stmt.executeQuery()) {
258                         assertNotNull(resultSet);
259                         assertTrue(resultSet.next());
260                     }
261                 }
262 
263                 // statement pooling is not enabled, we should get different statements
264                 assertTrue(l1HashCode != l2HashCode);
265             }
266 
267             try (Connection conn = myDs.getConnection()) {
268                 final long l3HashCode;
269                 final long l4HashCode;
270 
271                 assertNotNull(conn);
272                 psCallBack.setConnection(conn);
273                 try (PreparedStatement stmt = psCallBack.prepareStatement()) {
274                     assertNotNull(stmt);
275                     l3HashCode = getDelegateHashCode(stmt);
276                     try (ResultSet resultSet = stmt.executeQuery()) {
277                         assertNotNull(resultSet);
278                         assertTrue(resultSet.next());
279                     }
280                 }
281 
282                 try (PreparedStatement stmt = psCallBack.prepareStatement()) {
283                     assertNotNull(stmt);
284                     l4HashCode = getDelegateHashCode(stmt);
285                     try (ResultSet resultSet = stmt.executeQuery()) {
286                         assertNotNull(resultSet);
287                         assertTrue(resultSet.next());
288                     }
289                 }
290 
291                 // prepared statement pooling is working
292                 assertEquals(l3HashCode, l4HashCode);
293             }
294         }
295     }
296 
297     @Override
298     protected Connection getConnection() throws Exception {
299         return ds.getConnection("foo","bar");
300     }
301 
302     @SuppressWarnings("resource")
303     private int getDelegateHashCode(final Statement stmt) {
304         return ((DelegatingStatement) stmt).getDelegate().hashCode();
305     }
306 
307     @BeforeEach
308     public void setUp() throws Exception {
309         pcds = new DriverAdapterCPDS();
310         pcds.setDriver("org.apache.commons.dbcp2.TesterDriver");
311         pcds.setUrl("jdbc:apache:commons:testdriver");
312         pcds.setUser("foo");
313         pcds.setPassword("bar");
314         pcds.setPoolPreparedStatements(false);
315         pcds.setAccessToUnderlyingConnectionAllowed(true);
316 
317         final SharedPoolDataSource tds = new SharedPoolDataSource();
318         tds.setConnectionPoolDataSource(pcds);
319         tds.setMaxTotal(getMaxTotal());
320         tds.setDefaultMaxWait(getMaxWaitDuration());
321         tds.setDefaultTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
322         tds.setDefaultAutoCommit(Boolean.TRUE);
323 
324         ds = tds;
325     }
326 
327     // See DBCP-8
328     @Test
329     public void testChangePassword() throws Exception {
330         assertThrows(SQLException.class, () -> ds.getConnection("foo", "bay"));
331         final Connection con1 = ds.getConnection("foo", "bar");
332         final Connection con2 = ds.getConnection("foo", "bar");
333         final Connection con3 = ds.getConnection("foo", "bar");
334         con1.close();
335         con2.close();
336         TesterDriver.addUser("foo", "bay"); // change the user/password setting
337         try (Connection con4 = ds.getConnection("foo", "bay")) { // new password
338             // Idle instances with old password should have been cleared
339             assertEquals(0, ((SharedPoolDataSource) ds).getNumIdle(), "Should be no idle connections in the pool");
340             con4.close();
341             // Should be one idle instance with new pwd
342             assertEquals(1, ((SharedPoolDataSource) ds).getNumIdle(), "Should be one idle connection in the pool");
343             assertThrows(SQLException.class, () -> ds.getConnection("foo", "bar")); // old password
344             try (final Connection con5 = ds.getConnection("foo", "bay")) { // take the idle one
345                 con3.close(); // Return a connection with the old password
346                 ds.getConnection("foo", "bay").close(); // will try bad returned connection and destroy it
347                 assertEquals(1, ((SharedPoolDataSource) ds).getNumIdle(), "Should be one idle connection in the pool");
348             }
349         } finally {
350             TesterDriver.addUser("foo", "bar");
351         }
352     }
353 
354     /**
355      * Tests pool close. Illustrates BZ 37359.
356      *
357      * @throws Exception
358      */
359     @Test
360     public void testClosePool() throws Exception {
361         ((SharedPoolDataSource) ds).close();
362         @SuppressWarnings("resource") // closed below
363         final SharedPoolDataSource tds = new SharedPoolDataSource();
364         // NPE before BZ 37359 fix
365         tds.close();
366     }
367 
368     @Override
369     @Test
370     public void testClosing() throws Exception {
371         final Connection[] c = new Connection[getMaxTotal()];
372         // open the maximum connections
373         for (int i = 0; i < c.length; i++) {
374             c[i] = ds.getConnection();
375         }
376 
377         // close one of the connections
378         c[0].close();
379         assertTrue(c[0].isClosed());
380 
381         // get a new connection
382         c[0] = ds.getConnection();
383 
384         for (final Connection element : c) {
385             element.close();
386         }
387     }
388 
389     @Test
390     public void testClosingWithUserName() throws Exception {
391         final Connection[] c = new Connection[getMaxTotal()];
392         // open the maximum connections
393         for (int i = 0; i < c.length; i++) {
394             c[i] = ds.getConnection("u1", "p1");
395         }
396 
397         // close one of the connections
398         c[0].close();
399         assertTrue(c[0].isClosed());
400         // get a new connection
401         c[0] = ds.getConnection("u1", "p1");
402 
403         for (final Connection element : c) {
404             element.close();
405         }
406 
407         // open the maximum connections
408         for (int i = 0; i < c.length; i++) {
409             c[i] = ds.getConnection("u1", "p1");
410         }
411         for (final Connection element : c) {
412             element.close();
413         }
414     }
415 
416     @Test
417     public void testDbcp369() {
418         final ArrayList<SharedPoolDataSource> dataSources = new ArrayList<>();
419         for (int j = 0; j < 10000; j++) {
420             dataSources.add(new SharedPoolDataSource());
421         }
422 
423         final Thread t1 = new Thread(() -> {
424             for (final SharedPoolDataSource dataSource : dataSources) {
425                 dataSource.setDataSourceName("a");
426             }
427         });
428 
429         final Thread t2 = new Thread(() -> {
430             for (final SharedPoolDataSource dataSource : dataSources) {
431                 try {
432                     dataSource.close();
433                 } catch (final Exception e) {
434                     // Ignore
435                 }
436             }
437         });
438 
439         t1.start();
440         t2.start();
441 
442         try {
443             t1.join();
444             t2.join();
445         } catch (final InterruptedException ie) {
446             // Ignore
447         }
448     }
449 
450     /**
451      * Starting with a successful connection, then incorrect password,
452      * then correct password for same user illustrates
453      * JIRA: DBCP-245
454      */
455     @Test
456     public void testIncorrectPassword() throws SQLException {
457         ds.getConnection("u2", "p2").close();
458         try (Connection c = ds.getConnection("u1", "zlsafjk")){ // Use bad password
459             fail("Able to retrieve connection with incorrect password");
460         } catch (final SQLException e1) {
461             // should fail
462         }
463 
464         // Use good password
465         ds.getConnection("u1", "p1").close();
466         try (Connection c = ds.getConnection("u1", "x")) {
467             fail("Able to retrieve connection with incorrect password");
468         } catch (final SQLException e) {
469             if (!e.getMessage().startsWith("Given password did not match")) {
470                 throw e;
471             }
472             // else the exception was expected
473         }
474 
475         // Make sure we can still use our good password.
476         ds.getConnection("u1", "p1").close();
477 
478         // Try related users and passwords
479         ds.getConnection("foo", "bar").close();
480         try (Connection c = ds.getConnection("u1", "ar")) {
481             fail("Should have caused an SQLException");
482         } catch (final SQLException expected) {
483         }
484         try (Connection c = ds.getConnection("u1", "baz")) {
485             fail("Should have generated SQLException");
486         } catch (final SQLException expected) {
487         }
488     }
489 
490     @Override
491     @Test
492     public void testMaxTotal() throws Exception {
493         final Connection[] c = new Connection[getMaxTotal()];
494         for (int i=0; i<c.length; i++) {
495             c[i] = ds.getConnection();
496             assertNotNull(c[i]);
497         }
498 
499         assertThrows(SQLException.class, ds::getConnection, "Allowed to open more than DefaultMaxTotal connections.");
500 
501         for (final Connection element : c) {
502             element.close();
503         }
504     }
505 
506     @Test
507     public void testMaxWaitMillis() throws Exception {
508         final int maxWaitMillis = 1000;
509         final int theadCount = 20;
510 
511         ((SharedPoolDataSource) ds).setDefaultMaxWait(Duration.ofMillis(maxWaitMillis));
512         // Obtain all the connections from the pool
513         final Connection[] c = new Connection[getMaxTotal()];
514         for (int i = 0; i < c.length; i++) {
515             c[i] = ds.getConnection("foo", "bar");
516             assertNotNull(c[i]);
517         }
518 
519         final long startMillis = System.currentTimeMillis();
520 
521         // Run a thread test with minimal hold time
522         // All threads should end after maxWaitMillis - DBCP-291
523         final PoolTest[] pts = new PoolTest[theadCount];
524         final ThreadGroup threadGroup = new ThreadGroup("testMaxWaitMillis");
525 
526         // Should take ~maxWaitMillis for threads to stop
527         for (int i = 0; i < pts.length; i++) {
528             (pts[i] = new PoolTest(threadGroup, Duration.ofMillis(1), true)).start();
529         }
530 
531         // Wait for all the threads to complete
532         for (final PoolTest poolTest : pts) {
533             poolTest.getThread().join();
534         }
535 
536         final long endMillis = System.currentTimeMillis();
537 
538         // System.out.println("testMaxWaitMillis took " + (end - start) + " ms. maxWaitMillis: " + maxWaitMillis);
539 
540         // Threads should time out in parallel - allow double that to be safe
541         assertTrue(endMillis - startMillis < 2 * maxWaitMillis);
542 
543         // Put all the connections back in the pool
544         for (final Connection element : c) {
545             element.close();
546         }
547     }
548 
549     @Test
550     public void testMultipleThreads1() throws Exception {
551         // Override wait time in order to allow for Thread.sleep(1) sometimes taking a lot longer on
552         // some JVMs, e.g. Windows.
553         final Duration defaultMaxWaitDuration = Duration.ofMillis(430);
554         ((SharedPoolDataSource) ds).setDefaultMaxWait(defaultMaxWaitDuration);
555         multipleThreads(Duration.ofMillis(1), false, false, defaultMaxWaitDuration);
556     }
557 
558     @Test
559     public void testMultipleThreads2() throws Exception {
560         final Duration defaultMaxWaitDuration = Duration.ofMillis(500);
561         ((SharedPoolDataSource) ds).setDefaultMaxWait(defaultMaxWaitDuration);
562         multipleThreads(defaultMaxWaitDuration.multipliedBy(2), true, true, defaultMaxWaitDuration);
563     }
564 
565     @Override
566     @Test
567     public void testOpening() throws Exception {
568         final Connection[] c = new Connection[getMaxTotal()];
569         // test that opening new connections is not closing previous
570         for (int i = 0; i < c.length; i++) {
571             c[i] = ds.getConnection();
572             assertNotNull(c[i]);
573             for (int j = 0; j <= i; j++) {
574                 assertFalse(c[j].isClosed());
575             }
576         }
577 
578         for (final Connection element : c) {
579             element.close();
580         }
581     }
582 
583     /**
584      * Bugzilla Bug 24136 ClassCastException in DriverAdapterCPDS when setPoolPreparedStatements(true)
585      */
586     @Test
587     public void testPoolPrepareCall() throws SQLException {
588         pcds.setPoolPreparedStatements(true);
589         try (final Connection conn = ds.getConnection()) {
590             assertNotNull(conn);
591             try (final PreparedStatement stmt = conn.prepareCall("{call home()}")) {
592                 assertNotNull(stmt);
593                 try (final ResultSet rset = stmt.executeQuery()) {
594                     assertNotNull(rset);
595                     assertTrue(rset.next());
596                 }
597             }
598         }
599     }
600 
601     @Test
602     public void testPoolPreparedCalls() throws Exception {
603         doTestPoolCallableStatements(new CscbString());
604         doTestPoolCallableStatements(new CscbStringIntInt());
605         doTestPoolCallableStatements(new CscbStringIntIntInt());
606     }
607 
608     @Test
609     public void testPoolPreparedStatements() throws Exception {
610         doTestPoolPreparedStatements(new PscbString());
611         doTestPoolPreparedStatements(new PscbStringIntInt());
612         doTestPoolPreparedStatements(new PscbStringInt());
613         doTestPoolPreparedStatements(new PscbStringIntArray());
614         doTestPoolPreparedStatements(new PscbStringStringArray());
615         doTestPoolPreparedStatements(new PscbStringIntIntInt());
616     }
617 
618     @Test
619     public void testPoolPrepareStatement() throws SQLException {
620         pcds.setPoolPreparedStatements(true);
621 
622         try (final Connection conn = ds.getConnection()) {
623             assertNotNull(conn);
624             try (final PreparedStatement stmt = conn.prepareStatement("select * from dual")) {
625                 assertNotNull(stmt);
626                 try (final ResultSet rset = stmt.executeQuery()) {
627                     assertNotNull(rset);
628                     assertTrue(rset.next());
629                 }
630             }
631         }
632     }
633 
634     @Override
635     @Test
636     public void testSimple() throws Exception {
637         try (final Connection conn = ds.getConnection()) {
638             assertNotNull(conn);
639             try (final PreparedStatement stmt = conn.prepareStatement("select * from dual")) {
640                 assertNotNull(stmt);
641                 try (final ResultSet rset = stmt.executeQuery()) {
642                     assertNotNull(rset);
643                     assertTrue(rset.next());
644                 }
645             }
646         }
647     }
648 
649     @Override
650     @Test
651     public void testSimple2() throws SQLException {
652         {
653             final Connection conn = ds.getConnection();
654             assertNotNull(conn);
655 
656             try (PreparedStatement stmt = conn.prepareStatement("select * from dual")) {
657                 assertNotNull(stmt);
658                 try (ResultSet rset = stmt.executeQuery()) {
659                     assertNotNull(rset);
660                     assertTrue(rset.next());
661                 }
662             }
663 
664             try (PreparedStatement stmt = conn.prepareStatement("select * from dual")) {
665                 assertNotNull(stmt);
666                 try (ResultSet rset = stmt.executeQuery()) {
667                     assertNotNull(rset);
668                     assertTrue(rset.next());
669                 }
670             }
671 
672             conn.close();
673             assertThrows(SQLException.class, () -> conn.createStatement(), "Can't use closed connections");
674         }
675         try (Connection conn = ds.getConnection()) {
676             assertNotNull(conn);
677 
678             try (PreparedStatement stmt = conn.prepareStatement("select * from dual")) {
679                 assertNotNull(stmt);
680                 try (ResultSet rset = stmt.executeQuery()) {
681                     assertNotNull(rset);
682                     assertTrue(rset.next());
683                 }
684             }
685 
686             try (PreparedStatement stmt = conn.prepareStatement("select * from dual")) {
687                 assertNotNull(stmt);
688                 try (ResultSet rset = stmt.executeQuery()) {
689                     assertNotNull(rset);
690                     assertTrue(rset.next());
691                 }
692             }
693 
694         }
695     }
696 
697     @Test
698     public void testSimpleWithUsername() throws Exception {
699         try (final Connection conn = ds.getConnection("u1", "p1")) {
700             assertNotNull(conn);
701             try (final PreparedStatement stmt = conn.prepareStatement("select * from dual")) {
702                 assertNotNull(stmt);
703                 try (final ResultSet rset = stmt.executeQuery()) {
704                     assertNotNull(rset);
705                     assertTrue(rset.next());
706                 }
707             }
708         }
709     }
710 
711     @Test
712     public void testTransactionIsolationBehavior() throws Exception {
713         try (final Connection conn = getConnection()) {
714             assertNotNull(conn);
715             assertEquals(Connection.TRANSACTION_READ_COMMITTED, conn.getTransactionIsolation());
716             conn.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
717         }
718 
719         final Connection conn2 = getConnection();
720         assertEquals(Connection.TRANSACTION_READ_COMMITTED, conn2.getTransactionIsolation());
721 
722         final Connection conn3 = getConnection();
723         assertEquals(Connection.TRANSACTION_READ_COMMITTED, conn3.getTransactionIsolation());
724         conn2.close();
725         conn3.close();
726     }
727 }