Hello!
I've been struggling for some time with a problem during load testing an app and it seems that for some strange reason a SessionFactory with an associated C3P0 datasource will not close properly, leaving several threads and a pool with open connections after each test. I wonder if anyone has come across this situation.

Even more specifically, this only happens if the C3P0 integration is done via a dataSource bean, but NOT if done via hibernate's c3p0 properties.

I managed to narrow the issue to this JUnit test (The dumpThreads method is not relevant to the problem, it's just a debugging aid)
Code:
package com.planetalia.webng.hibernate;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.cfg.Configuration;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

public class ConnectionTest{
	private static final int HIBERNATE = 1;
	private static final int SPRING= 2;
	
	private int mode = HIBERNATE;
	
	private void dumpThreads() {
		StringBuilder sb = new StringBuilder("THREAD COUNT IS  ");
		sb.append(Thread.activeCount());
		sb.append(": ");
		Thread[] liveThreads = new Thread[Thread.activeCount()];
		long id = Thread.currentThread().getId();
		Thread.enumerate(liveThreads);
		for (int i = 0; i < liveThreads.length; i++) {
			long tid = liveThreads[i].getId();
			sb.append(tid);
			sb.append((tid==id)?"*(":"(");
			StackTraceElement[] stack = liveThreads[i].getStackTrace();
			int lastElement = stack.length-1;
			if (lastElement >=0) {
				sb.append(stack[lastElement].getClassName());
				sb.append(".");
				sb.append(stack[lastElement].getMethodName());
				sb.append(")");
				
			}
			sb.append(liveThreads[i].getState());
			sb.append("\t");
		}
		System.out.println(sb);
	}
	
	@Before
	public void start() throws Exception {
		SessionFactory sessionFactory = null;
		switch (mode) {
			case HIBERNATE: {
				Configuration configuration = new AnnotationConfiguration();
				configuration.configure("hibernate.cfg.xml");
				sessionFactory = configuration.buildSessionFactory();
				break;
			}
			case SPRING: {
				ApplicationContext ctx = new FileSystemXmlApplicationContext("wiring.xml");
				sessionFactory = (SessionFactory)ctx.getBean("sessionFactory");
				break;
			}
		}
		Session session = sessionFactory.getCurrentSession();
		Transaction tx = session.beginTransaction();
		tx.commit();
		sessionFactory.close();
		
		dumpThreads();
	}
	
	@Test public void test1() throws Exception {Thread.sleep(500);}
	@Test public void test2() throws Exception {Thread.sleep(500);}
	@Test public void test3() throws Exception {Thread.sleep(500);}
	@Test public void test4() throws Exception {Thread.sleep(500);}
	@Test public void test5() throws Exception {Thread.sleep(500);}
	@Test public void test6() throws Exception {Thread.sleep(500);}
	@Test public void test7() throws Exception {Thread.sleep(500);}
	@Test public void test8() throws Exception {Thread.sleep(500);}
}
This test uses only Hibernate or Spring+Hibernate.

For the first mode, the following configuration file is used (hibernate.cfg.xml):
Code:
<hibernate-configuration>
	<session-factory>
		<property name='connection.driver_class'>com.mysql.jdbc.Driver</property>
		<property name='connection.url'>jdbc:mysql://localhost/test</property>
		<property name='connection.username'>test</property>
		<property name='connection.password'>test</property>
		<property name='dialect'>org.hibernate.dialect.MySQLInnoDBDialect</property>
		<property name='current_session_context_class'>thread</property>
		<property name='cache.provider_class'>org.hibernate.cache.NoCacheProvider</property>
		<property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
		
		<property name="hibernate.c3p0.min_size">15</property>
		<property name="hibernate.c3p0.max_size">200</property>
		<property name="hibernate.c3p0.max_statements">100</property>
	</session-factory>
</hibernate-configuration>
And for the second (Spring+Hibernate) mode, the following file is used (wiring.xml):
Code:
  <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
		<property name="driverClass" value="com.mysql.jdbc.Driver"/>
		<property name="jdbcUrl" value="jdbc:mysql://localhost/test"/>
		<property name="user" value="test"/>
		<property name="password" value="test"/>
		
		<property name="minPoolSize" value="15"/>
		<property name="maxPoolSize" value="200"/>
		<property name="maxStatements" value="100"/>
	</bean>
	
	 <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>		
    <property name="hibernateProperties">
      <value>
      <!-- 
      	hibernate.connection.driver_class = com.mysql.jdbc.Driver
      	hibernate.connection.url=jdbc:mysql://localhost/test
      	hibernate.connection.username=test
      	hibernate.connection.password=test
      	
      	hibernate.connection.provider_class = org.hibernate.connection.C3P0ConnectionProvider
      	hibernate.c3p0.min_size=15
      	hibernate.c3p0.max_size=200
      	hibernate.c3p0.max_statements=100
      	 -->
        hibernate.dialect = org.hibernate.dialect.MySQLInnoDBDialect
        hibernate.cache.provider_class = org.hibernate.cache.NoCacheProvider
        hibernate.show_sql = false
        hibernate.current_session_context_class=thread
      </value>
    </property>
  </bean>
If the test is run in the SPRING mode, each consecutive test leaves behind 4 threads and a fully built (and connected) pool, regardless of the sessionFactory.close() method. According to the dump, the threads are basically waiting on some monitor. But this only happens if the C3P0 initialization is performed using <property name="dataSource" ref="dataSource"/>. If I remove that property and instead initialize C3P0 using the commented hibernate properties, it works properly.

If the test is run in the HIBERNATE mode, there are no "leftover" threads and/or pools. However, if in this mode I "forget" to call sessionFactory.close(), I get exactly the same behaviour as the SPRING mode WITH sessionFactory.close();

(Versions are: Hibernate: 3, C3P0: 0.9.1, Spring: 2.5.6.SEC01 (2009-04-22) )

Any ideas or similar problems? Thanks!