2012-01-17 3 views
2

J'essaie d'implémenter jdbc-pool dans une application web autonome (autonome - ne comptant pas sur server.xml) afin qu'elle puisse être déplacée vers des installations tomcat antérieures à 7.0.fuite de mémoire d'implémentation jdbc-pool autonome

Je me connecte à MSSQL Server avec le pilote sourceforge (net.sourceforge.jtds.jdbc.Driver)

Tout fonctionne bien sauf pour cette erreur:

SEVERE: The web application [/jdbc-pool] appears to have started a thread named [[Pool-Cleaner]:Tomcat Connection Pool[1-12524859]] but has failed to stop it. This is very likely to create a memory leak.

Sur la base this j'ai déterminé que Je dois fermer la source de données jdbc-pool. Je ne parviens pas à cette dernière ligne de ce poste si:

>> If it is configured in the application context, then this simply means you forgot to call DataSource.close on the connection pool when your web application is stopped.

> This is confusing advice because javax.sql.DataSource doesn't have a close() method.

In order to call close, one has to cast it to what ever the data source you are using.

Comment puis-je savoir quel type de source de données que je utilise et où est la classe pour elle? Puis-je l'extraire du pot de pilote en quelque sorte?

En plus d'une servlet qui utilise le pool, j'utilise un ServletContextListener afin que je puisse commencer avec des connexions groupées immédiatement à partir de la méthode contextInitialized. Je commencé à ajouter le code pour tuer la connexion dans la méthode contextDestroyed de cette ServletContextListener mais je me suis accroché où les points d'interrogation sont:

import java.sql.Driver; 
import java.sql.DriverManager; 
import java.sql.SQLException; 
import java.util.Enumeration; 

import javax.naming.Context; 
import javax.naming.InitialContext; 
import javax.naming.NamingException; 
import javax.servlet.ServletContext; 
import javax.servlet.ServletContextEvent; 
import javax.servlet.ServletContextListener; 
import javax.sql.DataSource; 

public class JdbcPoolListener implements ServletContextListener { 

    @Override 
    public void contextInitialized(ServletContextEvent myServletContextEvent) { 

     // initialize jdbc-pool datasource to start out with pooled connections 
     try { 
      Context myContext = (Context) new InitialContext().lookup("java:comp/env"); 
      DataSource myDataSource = (DataSource) myContext.lookup("jdbc/db"); 
      myServletContextEvent.getServletContext().setAttribute("JdbcPool", myDataSource); 
     } catch (NamingException e) { 
      System.out.println("Error initializing jdbc-pool datasource"); 
      e.printStackTrace(); 
     } 
    } 

    @Override 
    public void contextDestroyed(ServletContextEvent myServletContextEvent) { 

     // failed attempt to close the data source 
     ServletContext myServletContext = myServletContextEvent.getServletContext(); 
     //DataSource myDataSource = (DataSource) myServletContext.getAttribute("JdbcPool"); 
     DataSource dataSource = (DataSource)((???) myServletContext.getAttribute(contextAttribute)).getConfiguration().getEnvironment().getDataSource(); 
     dataSource.close(); 
     myServletContext.removeAttribute("JdbcPool"); 

     // deregister JDBC driver to prevent Tomcat 7 from complaining about memory leaks 
     Enumeration<Driver> drivers = DriverManager.getDrivers(); 
     while (drivers.hasMoreElements()) { 
      Driver driver = drivers.nextElement(); 
      try { 
       DriverManager.deregisterDriver(driver); 
       System.out.println(String.format("Deregistering jdbc driver: %s", driver)); 
      } catch (SQLException e) { 
       System.out.println(String.format("Error deregistering driver %s", driver)); 
       e.printStackTrace(); 
      } 
     } 
    } 
} 
+0

dans votre cas particulier, il est plus probable net.sourceforge.jtds.jdbcx.JtdsDataSource et essayer de jouer avec les paramètres socketTimeout se ferme connexion si elle tourne au ralenti. plus dans les docs du conducteur. –

Répondre

2

Résolue, je remarque que la tomcat.jdbc.pool.DataSourceProxy avait une méthode proche, donc je jetai la datasource comme DataSourceProxy, puis appelé fermé sur elle. Je ne reçois plus l'erreur de fuite de mémoire Tomcat dans le journal maintenant.

SOLUTION:

import java.sql.Driver; 
import java.sql.DriverManager; 
import java.sql.SQLException; 
import java.util.Enumeration; 

import javax.naming.Context; 
import javax.naming.InitialContext; 
import javax.naming.NamingException; 
import javax.servlet.ServletContext; 
import javax.servlet.ServletContextEvent; 
import javax.servlet.ServletContextListener; 
import javax.sql.DataSource; 

import org.apache.tomcat.jdbc.pool.DataSourceProxy; 

public class JdbcPoolListener implements ServletContextListener { 

    @Override 
    public void contextInitialized(ServletContextEvent myServletContextEvent) { 

     // initialize jdbc-pool datasource to start out with pooled connections 
     try { 
      Context myContext = (Context) new InitialContext().lookup("java:comp/env"); 
      DataSource myDataSource = (DataSource) myContext.lookup("jdbc/cf"); 
      myServletContextEvent.getServletContext().setAttribute("JdbcPool", myDataSource); 
     } catch (NamingException e) { 
      System.out.println("Error initializing jdbc-pool datasource"); 
      e.printStackTrace(); 
     } 
    } 

    @Override 
    public void contextDestroyed(ServletContextEvent myServletContextEvent) { 

    // close datasource from proxy? 
    ServletContext myServletContext = myServletContextEvent.getServletContext(); 
     DataSourceProxy myDataSource = (DataSourceProxy) myServletContext.getAttribute("JdbcPool"); 
     myDataSource.close();  
     myServletContext.removeAttribute("JdbcPool"); 

     // deregister JDBC driver to prevent Tomcat 7 from complaining about memory leaks 
     Enumeration<Driver> drivers = DriverManager.getDrivers(); 
     while (drivers.hasMoreElements()) { 
      Driver driver = drivers.nextElement(); 
      try { 
       DriverManager.deregisterDriver(driver); 
       System.out.println(String.format("Deregistering jdbc driver: %s", driver)); 
      } catch (SQLException e) { 
       System.out.println(String.format("Error deregistering driver %s", driver)); 
       e.printStackTrace(); 
      } 
     } 
    } 
} 
+2

Je suppose que si vous aviez utilisé la classe org.apache.tomcat.jdbc.pool.DataSource vous obtiendriez le même résultat car il étend le DataSourceProxy et le DataSourceProxy implémente le PoolConfiguration et le DataSourceProxy a la méthode close() pour fermer le pool . –

+0

@Sergey Benner Merci pour la clarification – Geronimo