/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.commons.dbcp;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.pool.PoolableObjectFactory;
import org.apache.commons.pool.impl.GenericObjectPool;

An implementation of a Jakarta-Commons ObjectPool which tracks JDBC connections and can recover abandoned db connections. If logAbandoned=true, a stack trace will be printed for any abandoned db connections recovered.

Author:Glenn L. Nielsen
Version:$Revision: 899987 $ $Date: 2010-01-16 11:51:16 -0500 (Sat, 16 Jan 2010) $
/** * <p>An implementation of a Jakarta-Commons ObjectPool which * tracks JDBC connections and can recover abandoned db connections. * If logAbandoned=true, a stack trace will be printed for any * abandoned db connections recovered. * * @author Glenn L. Nielsen * @version $Revision: 899987 $ $Date: 2010-01-16 11:51:16 -0500 (Sat, 16 Jan 2010) $ */
public class AbandonedObjectPool extends GenericObjectPool {
DBCP AbandonedConfig
/** * DBCP AbandonedConfig */
private final AbandonedConfig config;
A list of connections in use
/** * A list of connections in use */
private final List trace = new ArrayList();
Create an ObjectPool which tracks db connections.
Params:
  • factory – PoolableObjectFactory used to create this
  • config – configuration for abandoned db connections
/** * Create an ObjectPool which tracks db connections. * * @param factory PoolableObjectFactory used to create this * @param config configuration for abandoned db connections */
public AbandonedObjectPool(PoolableObjectFactory factory, AbandonedConfig config) { super(factory); this.config = config; }
Get a db connection from the pool. If removeAbandoned=true, recovers db connections which have been idle > removeAbandonedTimeout and getNumActive() > getMaxActive() - 3 and getNumIdle() < 2
Throws:
  • Exception – if an exception occurs retrieving a connection from the pool
Returns:Object jdbc Connection
/** * Get a db connection from the pool. * * If removeAbandoned=true, recovers db connections which * have been idle > removeAbandonedTimeout and * getNumActive() > getMaxActive() - 3 and * getNumIdle() < 2 * * @return Object jdbc Connection * @throws Exception if an exception occurs retrieving a * connection from the pool */
public Object borrowObject() throws Exception { if (config != null && config.getRemoveAbandoned() && (getNumIdle() < 2) && (getNumActive() > getMaxActive() - 3) ) { removeAbandoned(); } Object obj = super.borrowObject(); if (obj instanceof AbandonedTrace) { ((AbandonedTrace) obj).setStackTrace(); } if (obj != null && config != null && config.getRemoveAbandoned()) { synchronized (trace) { trace.add(obj); } } return obj; }
Return a db connection to the pool.
Params:
  • obj – db Connection to return
Throws:
  • Exception – if an exception occurs returning the connection to the pool
/** * Return a db connection to the pool. * * @param obj db Connection to return * @throws Exception if an exception occurs returning the connection * to the pool */
public void returnObject(Object obj) throws Exception { if (config != null && config.getRemoveAbandoned()) { synchronized (trace) { boolean foundObject = trace.remove(obj); if (!foundObject) { return; // This connection has already been invalidated. Stop now. } } } super.returnObject(obj); }
Invalidates an object from the pool.
Params:
  • obj – object to be returned
Throws:
  • Exception – if an exception occurs invalidating the object
/** * Invalidates an object from the pool. * * @param obj object to be returned * @throws Exception if an exception occurs invalidating the object */
public void invalidateObject(Object obj) throws Exception { if (config != null && config.getRemoveAbandoned()) { synchronized (trace) { boolean foundObject = trace.remove(obj); if (!foundObject) { return; // This connection has already been invalidated. Stop now. } } } super.invalidateObject(obj); }
Recover abandoned db connections which have been idle greater than the removeAbandonedTimeout.
/** * Recover abandoned db connections which have been idle * greater than the removeAbandonedTimeout. */
private void removeAbandoned() { // Generate a list of abandoned connections to remove long now = System.currentTimeMillis(); long timeout = now - (config.getRemoveAbandonedTimeout() * 1000); ArrayList remove = new ArrayList(); synchronized (trace) { Iterator it = trace.iterator(); while (it.hasNext()) { AbandonedTrace pc = (AbandonedTrace) it.next(); if (pc.getLastUsed() > timeout) { continue; } if (pc.getLastUsed() > 0) { remove.add(pc); } } } // Now remove the abandoned connections Iterator it = remove.iterator(); while (it.hasNext()) { AbandonedTrace pc = (AbandonedTrace) it.next(); if (config.getLogAbandoned()) { pc.printStackTrace(); } try { invalidateObject(pc); } catch (Exception e) { e.printStackTrace(); } } } }