View | Details | Raw Unified | Return to bug 54693
Collapse All | Expand All

(-)src/main/java/org/apache/tomcat/jdbc/pool/PoolConfiguration.java (+13 lines)
Lines 524-529 Link Here
524
    public void setValidationQuery(String validationQuery);
524
    public void setValidationQuery(String validationQuery);
525
525
526
    /**
526
    /**
527
     * The timeout in seconds before a connection validation queries fail.
528
     * A value less than or equal to zero will disable this feature.  Defaults to -1. 
529
     * @return the timeout value in seconds 
530
     */
531
    public int getValidationQueryTimeout();
532
    
533
    /**
534
     * The timeout in seconds before a connection validation queries fail.
535
     * A value less than or equal to zero will disable this feature.  Defaults to -1. 
536
     */
537
    public void setValidationQueryTimeout(int validationQueryTimeout);
538
    
539
    /**
527
     * Return the name of the optional validator class - may be null.
540
     * Return the name of the optional validator class - may be null.
528
     *
541
     *
529
     * @return the name of the optional validator class - may be null
542
     * @return the name of the optional validator class - may be null
(-)src/main/java/org/apache/tomcat/jdbc/pool/PooledConnection.java (+6 lines)
Lines 451-456 Link Here
451
        Statement stmt = null;
451
        Statement stmt = null;
452
        try {
452
        try {
453
            stmt = connection.createStatement();
453
            stmt = connection.createStatement();
454
            
455
            int validationQueryTimeout = poolProperties.getValidationQueryTimeout();
456
            if (validationQueryTimeout > 0) {
457
            	stmt.setQueryTimeout(validationQueryTimeout);
458
            }
459
            
454
            stmt.execute(query);
460
            stmt.execute(query);
455
            stmt.close();
461
            stmt.close();
456
            this.lastValidated = now;
462
            this.lastValidated = now;
(-)src/main/java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPool.java (+10 lines)
Lines 310-315 Link Here
310
    public String getValidationQuery() {
310
    public String getValidationQuery() {
311
        return getPoolProperties().getValidationQuery();
311
        return getPoolProperties().getValidationQuery();
312
    }
312
    }
313
    
314
    @Override
315
    public int getValidationQueryTimeout() {
316
    	return getPoolProperties().getValidationQueryTimeout();
317
    }
313
318
314
    /**
319
    /**
315
     * {@inheritDoc}
320
     * {@inheritDoc}
Lines 664-669 Link Here
664
        getPoolProperties().setValidationQuery(validationQuery);
669
        getPoolProperties().setValidationQuery(validationQuery);
665
    }
670
    }
666
671
672
    @Override
673
    public void setValidationQueryTimeout(int validationQueryTimeout) {
674
    	getPoolProperties().setValidationQueryTimeout(validationQueryTimeout);
675
    }
676
    
667
    /**
677
    /**
668
     * {@inheritDoc}
678
     * {@inheritDoc}
669
     */
679
     */
(-)src/main/java/org/apache/tomcat/jdbc/pool/DataSourceFactory.java (+7 lines)
Lines 80-85 Link Here
80
    protected static final String PROP_TESTWHILEIDLE = "testWhileIdle";
80
    protected static final String PROP_TESTWHILEIDLE = "testWhileIdle";
81
    protected static final String PROP_TESTONCONNECT = "testOnConnect";
81
    protected static final String PROP_TESTONCONNECT = "testOnConnect";
82
    protected static final String PROP_VALIDATIONQUERY = "validationQuery";
82
    protected static final String PROP_VALIDATIONQUERY = "validationQuery";
83
    protected static final String PROP_VALIDATIONQUERY_TIMEOUT = "validationQueryTimeout";
83
    protected static final String PROP_VALIDATOR_CLASS_NAME = "validatorClassName";
84
    protected static final String PROP_VALIDATOR_CLASS_NAME = "validatorClassName";
84
85
85
    protected static final String PROP_NUMTESTSPEREVICTIONRUN = "numTestsPerEvictionRun";
86
    protected static final String PROP_NUMTESTSPEREVICTIONRUN = "numTestsPerEvictionRun";
Lines 149-154 Link Here
149
        PROP_URL,
150
        PROP_URL,
150
        PROP_USERNAME,
151
        PROP_USERNAME,
151
        PROP_VALIDATIONQUERY,
152
        PROP_VALIDATIONQUERY,
153
        PROP_VALIDATIONQUERY_TIMEOUT,
152
        PROP_VALIDATOR_CLASS_NAME,
154
        PROP_VALIDATOR_CLASS_NAME,
153
        PROP_VALIDATIONINTERVAL,
155
        PROP_VALIDATIONINTERVAL,
154
        PROP_ACCESSTOUNDERLYINGCONNECTIONALLOWED,
156
        PROP_ACCESSTOUNDERLYINGCONNECTIONALLOWED,
Lines 366-371 Link Here
366
        if (value != null) {
368
        if (value != null) {
367
            poolProperties.setValidationQuery(value);
369
            poolProperties.setValidationQuery(value);
368
        }
370
        }
371
        
372
        value = properties.getProperty(PROP_VALIDATIONQUERY_TIMEOUT);
373
        if (value != null) {
374
        	poolProperties.setValidationQueryTimeout(Integer.parseInt(value));
375
        }
369
376
370
        value = properties.getProperty(PROP_VALIDATOR_CLASS_NAME);
377
        value = properties.getProperty(PROP_VALIDATOR_CLASS_NAME);
371
        if (value != null) {
378
        if (value != null) {
(-)src/main/java/org/apache/tomcat/jdbc/pool/PoolProperties.java (+17 lines)
Lines 57-62 Link Here
57
    private volatile int minIdle = initialSize;
57
    private volatile int minIdle = initialSize;
58
    private volatile int maxWait = 30000;
58
    private volatile int maxWait = 30000;
59
    private volatile String validationQuery;
59
    private volatile String validationQuery;
60
    private volatile int validationQueryTimeout = -1;
60
    private volatile String validatorClassName;
61
    private volatile String validatorClassName;
61
    private volatile Validator validator;
62
    private volatile Validator validator;
62
    private volatile boolean testOnBorrow = false;
63
    private volatile boolean testOnBorrow = false;
Lines 382-387 Link Here
382
    /**
383
    /**
383
     * {@inheritDoc}
384
     * {@inheritDoc}
384
     */
385
     */
386
    @Override
387
    public int getValidationQueryTimeout() {
388
    	return validationQueryTimeout;
389
    }
390
    
391
    /**
392
     * {@inheritDoc}
393
     */
394
    @Override
395
    public void setValidationQueryTimeout(int validationQueryTimeout) {
396
    	this.validationQueryTimeout = validationQueryTimeout;
397
    }
398
    
399
    /**
400
     * {@inheritDoc}
401
     */
385
402
386
    @Override
403
    @Override
387
    public String getValidatorClassName() {
404
    public String getValidatorClassName() {
(-)src/main/java/org/apache/tomcat/jdbc/pool/DataSourceProxy.java (+18 lines)
Lines 452-457 Link Here
452
    public void setValidatorClassName(String className) {
452
    public void setValidatorClassName(String className) {
453
        this.poolProperties.setValidatorClassName(className);
453
        this.poolProperties.setValidatorClassName(className);
454
    }
454
    }
455
    
456
    /**
457
     * {@inheritDoc}
458
     */
459
    
460
    @Override
461
    public void setValidationQueryTimeout(int validationQueryTimeout) {
462
    	this.poolProperties.setValidationQueryTimeout(validationQueryTimeout);
463
    }
455
464
456
    /**
465
    /**
457
     * {@inheritDoc}
466
     * {@inheritDoc}
Lines 928-933 Link Here
928
    /**
937
    /**
929
     * {@inheritDoc}
938
     * {@inheritDoc}
930
     */
939
     */
940
    
941
    @Override
942
    public int getValidationQueryTimeout() {
943
    	return getPoolProperties().getValidationQueryTimeout();
944
    }
945
    
946
    /**
947
     * {@inheritDoc}
948
     */
931
949
932
    @Override
950
    @Override
933
    public String getValidatorClassName() {
951
    public String getValidatorClassName() {
(-)src/main/java/org/apache/tomcat/jdbc/pool/mbeans-descriptors.xml (+5 lines)
Lines 125-130 Link Here
125
           description="The query to run during validation"
125
           description="The query to run during validation"
126
                  type="java.lang.String"
126
                  type="java.lang.String"
127
             writeable="false"/>
127
             writeable="false"/>
128
             
129
    <attribute    name="validationQueryTimeout"
130
           description="The timeout in seconds before a connection validation queries fail"
131
                  type="java.lang.Integer"
132
             writeable="false" />
128
133
129
    <attribute    name="testOnBorrow"
134
    <attribute    name="testOnBorrow"
130
           description="True if validation happens when a connection is requested"
135
           description="True if validation happens when a connection is requested"
(-)doc/jdbc-pool.xml (+9 lines)
Lines 277-282 Link Here
277
         Example values are <code>SELECT 1</code>(mysql), <code>select 1 from dual</code>(oracle), <code>SELECT 1</code>(MS Sql Server)
277
         Example values are <code>SELECT 1</code>(mysql), <code>select 1 from dual</code>(oracle), <code>SELECT 1</code>(MS Sql Server)
278
      </p>
278
      </p>
279
    </attribute>
279
    </attribute>
280
    
281
    <attribute name="validationQueryTimeout" required="false">
282
      <p>(int) The timeout in seconds before a connection validation queries fail.  This works by calling 
283
         <code>java.sql.Statement.setQueryTimeout(seconds)</code> on the statement that executes the <code>validationQuery</code>.
284
         The pool itself doesn't timeout the query, it is still up to the JDBC driver to enforce query timeouts. 
285
         A value less than or equal to zero will disable this feature. 
286
         The default value is <code>-1</code>.
287
      </p>
288
    </attribute>
280
289
281
    <attribute name="validatorClassName" required="false">
290
    <attribute name="validatorClassName" required="false">
282
      <p>(String) The name of a class which implements the
291
      <p>(String) The name of a class which implements the
(-)src/test/java/org/apache/tomcat/jdbc/test/TestValidationQueryTimeout.java (+162 lines)
Line 0 Link Here
1
package org.apache.tomcat.jdbc.test;
2
3
import java.sql.Connection;
4
import java.sql.DriverManager;
5
import java.sql.DriverPropertyInfo;
6
import java.sql.SQLException;
7
import java.sql.SQLFeatureNotSupportedException;
8
import java.sql.Statement;
9
import java.util.Properties;
10
import java.util.logging.Logger;
11
12
import junit.framework.Assert;
13
14
import org.apache.tomcat.jdbc.pool.interceptor.QueryTimeoutInterceptor;
15
import org.junit.After;
16
import org.junit.Before;
17
import org.junit.Test;
18
19
public class TestValidationQueryTimeout extends DefaultTestCase {
20
	
21
	private static int TIMEOUT = 10;
22
	private static boolean isTimeoutSet;
23
	
24
	@Before
25
	public void setUp() throws SQLException {
26
		DriverManager.registerDriver(new MockDriver());
27
		
28
		// use our mock driver
29
		this.datasource.setDriverClassName(MockDriver.class.getName());
30
        this.datasource.setUrl(MockDriver.url);
31
        
32
        // Required to trigger validation query's execution 
33
        this.datasource.setTestOnBorrow(true);
34
        this.datasource.setValidationInterval(-1);
35
        this.datasource.setValidationQuery("SELECT 1");
36
        this.datasource.setValidationQueryTimeout(TIMEOUT);
37
		this.datasource.setConnectionProperties("expectedTimeout=" + TIMEOUT);
38
        
39
		TIMEOUT = 10;
40
		isTimeoutSet = false;
41
	}
42
	
43
	@After
44
	public void tearDown() throws SQLException {
45
		DriverManager.deregisterDriver(new MockDriver());
46
	}
47
	
48
	@Test
49
	public void testValidationQueryTimeoutEnabled() throws Exception {
50
    	// because testOnBorrow is true, this triggers the validation query
51
    	this.datasource.getConnection();
52
    	Assert.assertTrue(isTimeoutSet);
53
	}
54
	
55
	@Test
56
	public void testValidationQueryTimeoutDisabled() throws Exception {
57
		this.datasource.setValidationQueryTimeout(-1);
58
		
59
    	// because testOnBorrow is true, this triggers the validation query
60
    	this.datasource.getConnection();
61
    	Assert.assertFalse(isTimeoutSet);
62
	}
63
	
64
	@Test
65
	public void testValidationQueryTimeoutWithQueryTimeoutInterceptor() throws Exception {
66
		int interceptorTimeout = 30;
67
		this.datasource.setJdbcInterceptors(
68
							QueryTimeoutInterceptor.class.getName()+
69
							"(queryTimeout="+ interceptorTimeout +")");
70
		
71
		// because testOnBorrow is true, this triggers the validation query
72
    	Connection con = this.datasource.getConnection();
73
    	Assert.assertTrue(isTimeoutSet);
74
    	
75
    	// increase the expected timeout to 30, which is what we set for the interceptor
76
    	TIMEOUT = 30;
77
    	
78
    	// now create a statement, make sure the query timeout is set by the interceptor
79
    	Statement st = con.createStatement();
80
        Assert.assertEquals(interceptorTimeout, st.getQueryTimeout());
81
        st.close();
82
        st = con.prepareStatement("");
83
        Assert.assertEquals(interceptorTimeout, st.getQueryTimeout());
84
        st.close();
85
        st = con.prepareCall("");
86
        Assert.assertEquals(interceptorTimeout, st.getQueryTimeout());
87
        st.close();
88
        con.close();
89
        
90
        // pull another connection and check it
91
        TIMEOUT = 10;
92
        isTimeoutSet = false;
93
        this.datasource.getConnection();
94
        Assert.assertTrue(isTimeoutSet);
95
	}
96
	
97
	/**
98
	 * Mock Driver, Connection and Statement implementations use to verify setQueryTimeout was called.
99
	 */
100
    public static class MockDriver implements java.sql.Driver {
101
    	public static final String url = "jdbc:tomcat:mock";
102
103
        public MockDriver() {
104
        }
105
106
        @Override
107
        public boolean acceptsURL(String url) throws SQLException {
108
            return url!=null && url.equals(MockDriver.url);
109
        }
110
111
        @Override
112
        public Connection connect(String url, Properties info) throws SQLException {
113
            return new MockConnection(info);
114
        }
115
116
        @Override
117
        public int getMajorVersion() {
118
            return 0;
119
        }
120
121
        @Override
122
        public int getMinorVersion() {
123
            return 0;
124
        }
125
126
        @Override
127
        public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException {
128
            return null;
129
        }
130
131
        @Override
132
        public boolean jdbcCompliant() {
133
            return false;
134
        }
135
136
        @Override
137
        public Logger getParentLogger() throws SQLFeatureNotSupportedException {
138
            return null;
139
        }
140
    }
141
    
142
    public static class MockConnection extends org.apache.tomcat.jdbc.test.driver.Connection {
143
        public MockConnection(Properties info) {
144
			super(info);
145
		}
146
147
		@Override
148
        public Statement createStatement() throws SQLException {
149
            return new MockStatement();
150
        }
151
    }
152
    
153
    public static class MockStatement extends org.apache.tomcat.jdbc.test.driver.Statement {
154
    	@Override
155
    	public void setQueryTimeout(int seconds) throws SQLException {
156
    		super.setQueryTimeout(seconds);
157
    		Assert.assertEquals(TIMEOUT, seconds);
158
    		isTimeoutSet = true;
159
    	}
160
    }
161
    
162
}

Return to bug 54693