자세한 내용은

https://tomcat.apache.org/tomcat-7.0-doc/jdbc-pool.html#org.apache.tomcat.jdbc.pool.interceptor.QueryTimeoutInterceptor

를 참고하세요.

<Resource name="jdbc/testDs" 
    factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
    jdbcInterceptors="org.apache.tomcat.jdbc.pool.interceptor.QueryTimeoutInterceptor"
    auth="Container"
    type="javax.sql.DataSource"
    username="root"
    password="root"
    driverClassName="org.mariadb.jdbc.Driver"
    validationQuery="SELECT 1"
    validationInterval="15000"
    testOnBorrow="true"
    testWhileIdle="true"
    timeBetweenEvictionRunsMillis="5000"
    minEvictableIdleTimeMillis="10000"
    removeAbandoned="true"
    removeAbandonedTimeout="10"
    url="jdbc:mysql://localhost:3306/test"
    logAbandoned="true"
    initialSize="5"
    maxIdle="5"
    minIdle="5"
    maxActive="10"/>

그런데 이렇게만 설정하면 오류가 발생합니다. 정확히는 NullPointerException 이 발생하는 것이죠.

615, 2015 3:54:27 오후 org.apache.tomcat.jdbc.pool.ConnectionPool init
심각: Unable to inform interceptor of pool start.
java.lang.NullPointerException
        at org.apache.tomcat.jdbc.pool.interceptor.QueryTimeoutInterceptor.setProperties(QueryTimeoutInterceptor.java:36)
        at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:470)
        at org.apache.tomcat.jdbc.pool.ConnectionPool.(ConnectionPool.java:144)
        at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:116)
        at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:103)
        at org.apache.tomcat.jdbc.pool.DataSourceFactory.createDataSource(DataSourceFactory.java:554)
        at org.apache.tomcat.jdbc.pool.DataSourceFactory.getObjectInstance(DataSourceFactory.java:242)
        at org.apache.naming.factory.ResourceFactory.getObjectInstance(ResourceFactory.java:141)
        at javax.naming.spi.NamingManager.getObjectInstance(NamingManager.java:321)
        at org.apache.naming.NamingContext.lookup(NamingContext.java:842)
        at org.apache.naming.NamingContext.lookup(NamingContext.java:153)
        at org.apache.naming.NamingContext.lookup(NamingContext.java:830)
        at org.apache.naming.NamingContext.lookup(NamingContext.java:153)
        at org.apache.naming.NamingContext.lookup(NamingContext.java:830)
        at org.apache.naming.NamingContext.lookup(NamingContext.java:153)
        at org.apache.naming.NamingContext.lookup(NamingContext.java:830)
        at org.apache.naming.NamingContext.lookup(NamingContext.java:167)
        at org.apache.naming.SelectorContext.lookup(SelectorContext.java:156)
        at javax.naming.InitialContext.lookup(InitialContext.java:411)
 
......
 
615, 2015 3:54:27 오후 org.apache.naming.NamingContext lookup
경고: Unexpected exception resolving reference
java.sql.SQLException
        at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:476)
        at org.apache.tomcat.jdbc.pool.ConnectionPool.(ConnectionPool.java:144)
        at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:116)
        at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:103)
        at org.apache.tomcat.jdbc.pool.DataSourceFactory.createDataSource(DataSourceFactory.java:554)
        at org.apache.tomcat.jdbc.pool.DataSourceFactory.getObjectInstance(DataSourceFactory.java:242)
        at org.apache.naming.factory.ResourceFactory.getObjectInstance(ResourceFactory.java:141)
        at javax.naming.spi.NamingManager.getObjectInstance(NamingManager.java:321)
        at org.apache.naming.NamingContext.lookup(NamingContext.java:842)
        at org.apache.naming.NamingContext.lookup(NamingContext.java:153)
        at org.apache.naming.NamingContext.lookup(NamingContext.java:830)
        at org.apache.naming.NamingContext.lookup(NamingContext.java:153)
        at org.apache.naming.NamingContext.lookup(NamingContext.java:830)
        at org.apache.naming.NamingContext.lookup(NamingContext.java:153)
        at org.apache.naming.NamingContext.lookup(NamingContext.java:830)
        at org.apache.naming.NamingContext.lookup(NamingContext.java:167)
        at org.apache.naming.SelectorContext.lookup(SelectorContext.java:156)
        at javax.naming.InitialContext.lookup(InitialContext.java:411)

그래서 이렇게 합니다. queryTimeout 을 2초로 설정하는 경우로 말입니다.

jdbcInterceptors="org.apache.tomcat.jdbc.pool.interceptor.QueryTimeoutInterceptor(queryTimeout=2000)"

그리고 위에서 설정한 값(queryTimeout)은 getQueryTimeout() 으로 얻을 수 있습니다.

하지만 아무데서나 getQueryTimeout() 을 하면 안됩니다.

Statement stmt = null;

null 값인 stmt 에서 stmt.getQueryTimeout() 은... 안됩니다.

stmt = conn.createStatement();

하지만 이제, 됩니다.

마지막으로 QueryTimeoutInterceptor 클래스 소스입니다.

package org.apache.tomcat.jdbc.pool.interceptor;
 
import java.lang.reflect.Method;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Map;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.jdbc.pool.PoolProperties.InterceptorProperty;
 
public class QueryTimeoutInterceptor
  extends AbstractCreateStatementInterceptor
{
  private static Log log = LogFactory.getLog(QueryTimeoutInterceptor.class);
  int timeout;
 
  public void setProperties(Map<String, PoolProperties.InterceptorProperty> properties)
  {
    super.setProperties(properties);
    this.timeout = ((PoolProperties.InterceptorProperty)properties.get("queryTimeout")).getValueAsInt(-1);
  }
 
  public Object createStatement(Object proxy, Method method, Object[] args, Object statement, long time)
  {
    if (((statement instanceof Statement)) &amp;&amp; (this.timeout > 0))
    {
      Statement s = (Statement)statement;
      try
      {
        s.setQueryTimeout(this.timeout);
      }
      catch (SQLException x)
      {
        log.warn("[QueryTimeoutInterceptor] Unable to set query timeout:" + x.getMessage(), x);
      }
    }
    return statement;
  }
 
  public void closeInvoked() {}
}