2012-11-23 12 views
5

dopo aver sviluppato diverse webapps che avevano tutte un setup simile con spring, hibernate e c3p0 come connectionpool volevo investigare su un problema che ho notato ogni volta: Connectionpool mantiene le connessioni fino allo shutdown tomcat (o al server delle applicazioni).Come arrestare il pool di connessione nel contesto di scaricamento?

Oggi ho creare il progetto di base ho potuto con questi quattro dipendenze:

org.springframework:spring-web 
org.springframework:spring-orm 
org.hibernate:hibernate-core 
c3p0:c3p0 

(più il driver JDBC specifica).

My web.xml crea solo un ContextLoaderListener che imposta il contesto dell'applicazione.

<context-param> 
    <param-name>contextConfigLocation</param-name> 
    <param-value> 
     /WEB-INF/applicationContext.xml 
    </param-value> 
</context-param> 

<listener> 
    <listener-class> 
     org.springframework.web.context.ContextLoaderListener 
    </listener-class> 
</listener> 

contesto di applicazione è costituito da due fagioli - DataSource e sessione di fabbrica:

<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> 
    <property name="dataSource" ref="dataSource" /> 
</bean> 

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> 
    <property name="driverClass"> 
     <value>org.postgresql.Driver</value> 
    </property> 
    <property name="jdbcUrl"> 
     <value>jdbc:postgresql://localhost/mydb</value> 
    </property> 
    <property name="user"> 
     <value>usr</value> 
    </property> 
    <property name="password"> 
     <value>pwd</value> 
    </property> 
</bean> 

Quando avvio il webapp e sia guardare in MBeans del JConsole o controllare le mie DBMS per le connessioni aperte ho notato i tre connessioni iniziali fatto da c3p0.

PROBLEMA: Quando dico a Tomcat di interrompere la webapp, rimangono comunque!

Ho creato un altro ServletContextListener che ha implementato il metodo contextDestroyed e che interrompe in modo programmatico sessionFactory (e cancella anche i driver JDBC che non vengono eseguiti automaticamente). Codice è:

@Override 
public void contextDestroyed(ServletContextEvent sce) { 

    ... 
    sessionFactory().close(); 

    // deregister sql driver(s) 
    Enumeration<Driver> drivers = DriverManager.getDrivers(); 
    while (drivers.hasMoreElements()) { 
     Driver driver = drivers.nextElement(); 
     try { 
      DriverManager.deregisterDriver(driver); 
      log.info("deregistering jdbc driver: " + driver); 
     } catch (SQLException e) { 
      log.error("error deregistering jdbc driver: " + driver, e); 
     } 
    } 
} 

Ma è davvero? Non c'è un meccanismo integrato di cui non sono a conoscenza?

risposta

12

Hai provato a specificare il metodo destroy?

<bean class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> 
+0

Non c'è nulla di prezioso come l'esperienza ... ha funzionato! Grazie (ma per quanto riguarda l'annullamento della registrazione del driver jdbc?) – realsim

+1

L'annullamento della registrazione dei driver li rimuove solo dall'elenco statico interno di 'DriverManager'. Quando la prossima volta che il pool di connessioni vuole acquisire una nuova risorsa, richiede 'DriverManager' per esso. Ma se la connessione è già stata acquisita e rimane nel pool, nulla impedisce di continuare a funzionare. A proposito, ciò comporta anche perdite di memoria del caricatore di classe perché i thread del pool di connessioni non consentivano la distruzione delle classi. Per favore, contrassegna la domanda come risolta se ritieni di non avere ulteriori domande. –

+0

@realsim: non dimenticare di accettare questa risposta! –

Problemi correlati