Class QueryTimeoutInterceptor

All Implemented Interfaces:
InvocationHandler

public class QueryTimeoutInterceptor extends AbstractCreateStatementInterceptor
Interceptor that sets a query timeout on every created Statement.

The timeout is applied by the createStatement hook, which only runs for statement-creation calls that pass through this interceptor. When combined with StatementCache, this interceptor must therefore be listed before StatementCache in the jdbcInterceptors configuration. A statement cache hit is served by the cache without invoking the rest of the chain, and a statement recycled into the cache has its query timeout reset to zero, so an interceptor listed after the cache never sees the reuse and the cached statement executes with no timeout. Listed before the cache, the hook runs for every creation request, including the ones the cache serves, and the timeout is re-applied to the reused statement.

The same applies to statements whose connection never enters the chain: one reached through PooledConnection.getConnection() or unwrap, and, on a pool backed by an XADataSource, the only connection an application uses - such an application gets its connection from PooledConnection.getConnection(), which the pool answers with the session behind the chain. Those statements keep whatever timeout the driver gives them; for the XA case the pool warns at startup, see poolStarted(ConnectionPool).

Whether a configured timeout actually interrupts a query is up to the driver. A driver that refuses Statement.setQueryTimeout(int) does not stop the statement from being handed out - the pool cannot enforce a timeout itself, so such a statement runs unbounded - and the refusal is reported once per physical connection rather than once per statement, so that the log says what is not in effect without repeating itself for every statement that connection creates.

  • Constructor Details

    • QueryTimeoutInterceptor

      public QueryTimeoutInterceptor()
      Default constructor.
  • Method Details

    • setProperties

      public void setProperties(Map<String, PoolProperties.InterceptorProperty> properties)
      Initializes the queryTimeout property from the provided configuration map. A name that is not one of the names this interceptor reads is not applied and is warned about: names are matched exactly, so a mis-cased queryTimeout is not a spelling of the property but a different, unread name - and the timeout it leaves unconfigured keeps the aggressive default, which is the wrong direction for a typo to fail in. A value that is not an integer is likewise not applied and is warned about: the timeout keeps the value it has - for a fresh instance the one-second default - so a misconfigured pool behaves as the default and the warning says so as the bad value is configured. The pool configures an interceptor instance once at pool start, once per physical connection chain, and once when the pool stops, so these warnings are no more frequent than the per-connection driver refusal report below; that report is the one that can re-fire, when the pool replaces the physical session behind a connection.
      Overrides:
      setProperties in class JdbcInterceptor
      Parameters:
      properties - map of interceptor properties
    • poolStarted

      public void poolStarted(ConnectionPool pool)
      Ends the silence about the one configuration in which this interceptor is inert for an application's normal use: a pool backed by a XADataSource, where the application's only Connection comes from PooledConnection.getConnection() and so stays outside this chain (see the class javadoc and the getConnection() branch of ProxyConnection). The interceptor cannot reach the statements created there - that would mean re-wrapping the session the pool hands out, which is a pool-level change, not an interceptor's - and refusing to start the pool would deny an application a timeout its driver may still apply at its own creation call, so what is done instead is one warning at pool start, while the configuration is still the operator's to change. Statements taken through the pool's own chained handle keep the configured timeout even on an XA-backed pool, so the warning names the one route the escape runs by, not the pool as a whole.
      Overrides:
      poolStarted in class JdbcInterceptor
      Parameters:
      pool - the pool that is starting
    • isKnownProperty

      protected boolean isKnownProperty(String name)
      Whether this interceptor configuration understands the named property. queryTimeout is this class's own; useEquals is read by the JdbcInterceptor base. A subclass that adds properties should recognize them here too, so the unrecognized-name report stays a report about a typo rather than becoming a report about the subclass's own design.
      Parameters:
      name - the property name as configured
      Returns:
      true if the name is understood and its value acted upon
    • createStatement

      public Object createStatement(Object proxy, Method method, Object[] args, Object statement, long time)
      Sets the query timeout on the created statement if it is a Statement and the timeout value is positive.
      Specified by:
      createStatement in class AbstractCreateStatementInterceptor
      Parameters:
      proxy - the actual proxy object
      method - the method that was called
      args - the arguments to the method
      statement - the statement that the underlying connection created
      time - elapsed time in milliseconds
      Returns:
      the (possibly wrapped) statement object
    • disconnected

      public void disconnected(ConnectionPool parent, PooledConnection con, boolean finalizing)
      Forgets the reported refusal and the reported unexpected failure, as the physical connection this interceptor is attached to is gone: the session that replaces it gets its own reports, the way it gets its own driver to answer the call.
      Overrides:
      disconnected in class JdbcInterceptor
      Parameters:
      parent - - the connection pool that this connection belongs to
      con - - the pooled connection that holds this connection
      finalizing - - if this connection is finalizing. True means that the pooled connection will not reconnect the underlying connection
    • closeInvoked

      public void closeInvoked()
      No-op; the refusal record belongs to the physical connection, not to the borrow, so ending a borrow has nothing here to clean up.
      Specified by:
      closeInvoked in class AbstractCreateStatementInterceptor