2010-03-23 18 views
2

J'ai hérité du code qui utilise les pools de connexions Apache commons-dbcp dans un ensemble OSGi. Ce code fonctionne très bien avec Eclipse/Equinox OSGi version 3.4.3 (R34x_v20081215), commons-dbcp 1.2.2 et les paquets postgres jdbc3 8.3.603 de springsource.org. Je voulais moderniser, peut-être c'était ma première erreur! Lorsque j'utilise la nouvelle version des noyaux OSGI Felix ou Equinox avec les nouveaux bundles JDBC3 ou JDBC4 postgresql avec la dernière version de commons-dbcp (1.4.1), j'éprouve un problème de chargement de la classe. J'ai fait de nombreuses recherches et ai trouvé que le code de commons-dbcp devrait avoir un correctif DBCP-214, mais il semble toujours échouer.OSGI & Apache Commons-DBCP Classloading Problème

J'ai essayé de placer l'org.postgresql sur la ligne d'import-package commons-dbcp MANIFEST.MF, mais cela ne fonctionnait pas non plus.

J'ai écrit un test simple dans un activateur qui fait d'abord un basic.forName() et DriverManager.getConnection(), cela fonctionne très bien, mais quand j'ajoute BasicDataSource() et configure la connexion avec BasicDataSource.getConnection (), J'obtiens le ClassNotFoundException. Voir l'exemple de code ci-dessous.

Merci à l'avance pour toute aide, suggestions, ...

Sau!

// This one fails with an exception 
public void dsTest() { 
    BasicDataSource bds = new BasicDataSource(); 
    ClassLoader cl; 

    try { 
     logger.debug("ContextClassLoader: {}", 
     Thread.currentThread().getContextClassLoader().toString()); 
     cl = this.getClass().getClassLoader(); 
     logger.debug("ClassLoader: {}", cl); 

     if (bds.getDriverClassLoader() != null) { 
      logger.debug(bds.getDriverClassLoader().toString()); 
     } 
     // The failure is the same with and with the setDriverClassLoader() line 
     bds.setDriverClassLoader(cl); 
     bds.setDriverClassName("org.postgresql.Driver"); 
     bds.setUrl("jdbc:postgresql://127.0.0.1/dbname"); 
     bds.setUsername("user"); 
     bds.setPassword("pword"); 
     Class.forName("org.postgresql.Driver").newInstance(); 
     conn = bds.getConnection(); 
     Statement st = conn.createStatement(); 
     ResultSet rs = st.executeQuery("SELECT COUNT(*) FROM table"); 
     conn.close(); 
     logger.debug("Closed DataSource Test"); 
    } catch (Exception ex) { 
     ex.printStackTrace(); 
     logger.debug("Exception: {} ", ex.getMessage()); 
    } 
} 

// This one works 
public void managerTest() { 
    ClassLoader cl; 
    try { 
     cl = this.getClass().getClassLoader(); 
     logger.debug("ClassLoader: {}", cl); 
     Class.forName("org.postgresql.Driver").newInstance(); 
     String url = "jdbc:postgresql://127.0.0.1/dbname"; 
     conn = DriverManager.getConnection(url, "user", "pword"); 

     Statement st = conn.createStatement(); 
     ResultSet rs = st.executeQuery("SELECT COUNT(*) FROM table"); 
     conn.close(); 
     logger.debug("Closed Manger Test"); 
    } catch (Exception ex) { 
     ex.printStackTrace(); 
     logger.debug("Exception: {} ", ex.getMessage()); 
    } 
} 

Répondre

3

cela est dû au fait que le faisceau commons-DBCP ne peut pas regarder la classe du pilote réel, en raison du chargeur de classe OSGi. La solution consiste à attacher un fragment à la classe commons-dbcp avec Dynamic Import *. Les en-têtes réels que vous avez besoin dans votre MANIFESTE sont les suivantes:

Fragment-hôte: org.apache.commons.dbcp DynamicImport-Package: *

Après cela, le code que vous avez mentionné travaillé. J'espère que cela n'arrive pas trop tard.