IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

JDBC Java Discussion :

chargement dynamique driver jdbc


Sujet :

JDBC Java

  1. #1
    Membre habitué Avatar de Alt157
    Profil pro
    Inscrit en
    Février 2009
    Messages
    143
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 143
    Points : 146
    Points
    146
    Par défaut chargement dynamique driver jdbc
    Bonjour a tous,

    J'ai un petit problème, je souhaiterais pouvoir, via un fichier de propriétés me connecter à n'importe quelle base de données sans avoir a utiliser un classpath dans ma commande java.

    Pour se faire j'ai utilise un fichier de propriétés avec ces données :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    user	        = alt157
    mdp	        = **********   		
    base 	= mabase
    url            = jdbc:postgresql://192.168.0.11/mabase
    driver	= org.postgresql.Driver
    jar            = /usr/share/java/postgresql.jar
    Dans mon code je charge les classes de la sorte :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
     
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.util.Enumeration;
    import java.util.Properties;
    import java.io.InputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.net.URLClassLoader;
    import java.net.URL;
    import java.util.jar.JarFile;
     
    public class Test
    {
        public static void main ( String[] args)  throws Exception
        {
            Properties prop = new Properties();        
            InputStream file = new FileInputStream("config.txt");
            prop.load(file);        
            Connection con = null;
            String url = prop.getProperty("url");
            String user = prop.getProperty("user");
            String mdp = prop.getProperty("mdp");
            String jar = prop.getProperty("jar");
            File f = new File(jar);
            URLClassLoader loader = new URLClassLoader(new URL[] { f.toURL()  } );
            JarFile leJar = new JarFile(f.getAbsolutePath());
            Enumeration I = leJar.entries();
            while ( I.hasMoreElements() ) {
                String tmp = I.nextElement().toString();
                if ( tmp.endsWith(".class") ) {
                    tmp = tmp.substring(0,tmp.length()-6);
                    tmp = tmp.replaceAll("/",".");
                    System.out.println(tmp);
                    Class.forName(tmp ,true,loader);
                }
            }
            con = DriverManager.getConnection(url, user, mdp );
       }
    }
    Mais cela me renvoie une erreur :
    Exception in thread "main" java.sql.SQLException: No suitable driver found for jdbc:postgresql://192.168.0.11/mabase
    at java.sql.DriverManager.getConnection(DriverManager.java:640)
    at java.sql.DriverManager.getConnection(DriverManager.java:200)
    at Test.main(Test.java:40)
    Je ne vois vraiment pas ou il y a un probleme, j'ai tente de mettre le retour de Class.forName dans une variable de type Class et de l'afficher a l'écran. A priori il me charge bien toutes les classes de mon .jar...

    Je tiens juste a préciser que si j'utilise simplement la commande java :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    java -classpath /usr/share/java/postgresql.jar:. Test
    Cela fonctionne mais j'ai pas envie de m'embêter a gérer ce classpath car l'application devra être utilisable facilement et l'on devra pouvoir attaquer différentes bases sans avoir a changer le classapth ou a redémarrer l'application.

    Merci d'avance a vous tous

  2. #2
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Points : 48 804
    Points
    48 804
    Par défaut
    voilà normalement le code correct pour charger un driver depuis un jar non présent dans le classloader

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    String driverClass = .... // récupéré de ton properties
    String fichierJar = ..... // idem
    URLClassLoader loader = new URLClassLoader(new URL[] { new File(fichierJar).toURL()  } );
    Class.forName(driverClass,true,loader);
    con = DriverManager.getConnection(url, user, mdp );
    Pas besoin d'aller comme nu bourrin scanner le jar pour ça.

  3. #3
    Membre habitué Avatar de Alt157
    Profil pro
    Inscrit en
    Février 2009
    Messages
    143
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 143
    Points : 146
    Points
    146
    Par défaut
    Merci beaucoup d'avoir répondu rapidement.

    C'est vrai que c'était un peu bourrin comme technique mais je ne savais pas si il fallait charger toutes les classes du JAR ou seulement la driver pour l'utilisation donc j'aurais fait les test après.

    J'ai retiré ma boucle mais sur le principe c'est la même chose. Je n'arrivais pas à le charger dans ma boucle donc cela ne fonctionne toujours pas...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
     
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.util.Properties;
    import java.io.InputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.net.URLClassLoader;
    import java.net.URL;
     
    public class Test
    {
        public static void main ( String[] args)  throws Exception
        {
         	Properties prop = new Properties();
    	InputStream file = new FileInputStream("config.txt");
    	prop.load(file);
    	Connection con = null;
    	String url = prop.getProperty("url");
    	String user = prop.getProperty("user");
    	String mdp = prop.getProperty("mdp");
    	String jar = prop.getProperty("jar");
    	String driver = prop.getProperty("driver");
    	File f = new File(jar);
    	URLClassLoader loader = new URLClassLoader(new URL[] { f.toURL()  } );
    	Class.forName(driver, true, loader);
    	con = DriverManager.getConnection(url, user, mdp );
    	con.close();
        }
    }
    Merci encore.

    Et je ne comprends toujours pourquoi cela ne marche pas...

    Merci d'avance pour votre aide

  4. #4
    Expert éminent sénior
    Avatar de Baptiste Wicht
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2005
    Messages
    7 431
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Suisse

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2005
    Messages : 7 431
    Points : 21 324
    Points
    21 324
    Par défaut
    Tu es sûr que le chemin vers ton JAR est correct ?

  5. #5
    Membre habitué Avatar de Alt157
    Profil pro
    Inscrit en
    Février 2009
    Messages
    143
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 143
    Points : 146
    Points
    146
    Par défaut
    Il a l'air en tout cas...

    En lançant l'application avec le classpath je saisi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    java -classpath /usr/share/java/postgresql.jar:. Test
    Et cela fonctionne

    __________________________

    et en le lançant simplement
    en ayant mon fichier de configuration avec ces valeurs :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    user	=	alt157
    mdp	= 	
    base	=	maBase
    url	=	jdbc:postgresql://192.168.0.11/maBase
    driver	=	org.postgresql.Driver
    jar 	=	/usr/share/java/postgresql.jar
    Cela ne fonctionne pas
    ____________________________________

    Merci de vous intéresser au probleme.

  6. #6
    Expert éminent sénior
    Avatar de Baptiste Wicht
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2005
    Messages
    7 431
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Suisse

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2005
    Messages : 7 431
    Points : 21 324
    Points
    21 324
    Par défaut
    Est-ce que DriverManager va savoir comment chercher dans ce nouveau loader ?

    Il va logiquement chercher dans le class loader système qui ne va pas chercher dans ses enfants.

    Est-ce qu'ainsi il ne faudrait pas rajouter le jar directement dans le classloader système ?

  7. #7
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Points : 48 804
    Points
    48 804
    Par défaut
    Citation Envoyé par Baptiste Wicht Voir le message
    Est-ce que DriverManager va savoir comment chercher dans ce nouveau loader ?
    Le drivermanager en a rien à battre des classloader. C'est le driver qui enregistre une instance auprès du drivermanager en utilisant la méthode registerDriver, c'est pour ça qu'on utilise toujours la technique du Class.forName, avec dans le driver une initialisation statiquie qui fait en gros
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    static {
        DriverManager.registerDriver(new MonDriverAMoi());
    }
    Mais bon, les détails sont laissés à l'appréciation du driver en lui même?

    Es-tu sur qu'il n'y a pas des espace en trop dans tes valeurs? est-ce que f.exists() te retroune bien "true" ?

  8. #8
    Membre habitué Avatar de Alt157
    Profil pro
    Inscrit en
    Février 2009
    Messages
    143
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 143
    Points : 146
    Points
    146
    Par défaut
    Et bien un :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    System.out.println("Existe : " + f.exists() );
    me renvoie bien true

    Et j'ai afficher le toString de ma classe chargee:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    Class c = Class.forName(driver, true, loader);
    System.out.println("Classe : " + c);
    Et cela me renvoie bien : Classe : class org.postgresql.Driver

    Merci de votre aide

  9. #9
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Points : 48 804
    Points
    48 804
    Par défaut
    Apparement le drivermanager fait des check sur le classloader. En résultat, seul le code présent dans ton urlclassloader pourra utiliser le driver :/
    Avec des logs j'obtiens ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    *Driver.connect (jdbc:postgresql://192.168.0.11/maBase)
        skipping: driver[className=org.postgresql.Driver,org.postgresql.Driver@38cdedfd]


    Un workaround pas beau est celui-ci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    		URLClassLoader loader = new URLClassLoader(new URL[] { f.toURL()  });
    		Class<?> c = Class.forName(driver, true, loader);
    		Driver d = (Driver) c.newInstance();
    		Properties infos = new Properties();
    		if (user!=null)
    			infos.setProperty("user", user);
    		if (mdp!=null)
    			infos.setProperty("password", mdp);
    		con = d.connect(url, infos);
    		con.close();

  10. #10
    Membre habitué Avatar de Alt157
    Profil pro
    Inscrit en
    Février 2009
    Messages
    143
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 143
    Points : 146
    Points
    146
    Par défaut
    Merci beaucoup !

    En modifiant mon programme de la sorte tout fonctionne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
     
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.Driver;
    import java.util.Properties;
    import java.io.InputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.net.URLClassLoader;
    import java.net.URL;
     
    public class Test
    {
        public static void main ( String[] args)  throws Exception
        {
         	Properties prop = new Properties();
    	InputStream file = new FileInputStream("config.txt");
    	prop.load(file);
    	Connection con = null;
    	String url = prop.getProperty("url");
    	String user = prop.getProperty("user");
    	String mdp = prop.getProperty("mdp");
    	String jar = prop.getProperty("jar");
    	String driver = prop.getProperty("driver");
    	File f = new File(jar);
            URLClassLoader loader = new URLClassLoader(new URL[] { f.toURL()  } );
            Driver monDriver = (Driver)Class.forName(driver, true, loader).newInstance();
            Properties infos = new Properties();
            infos.setProperty("user", user);
            infos.setProperty("mdp", mdp);
            con = monDriver.connect(url, infos);
            con.close();
        }
    }
    Merci de votre aide et du temps que vous m'avez tous les deux consacré.

    Merci encore

  11. #11
    Expert éminent sénior
    Avatar de Baptiste Wicht
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2005
    Messages
    7 431
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Suisse

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2005
    Messages : 7 431
    Points : 21 324
    Points
    21 324
    Par défaut
    Citation Envoyé par tchize_ Voir le message
    Le drivermanager en a rien à battre des classloader. C'est le driver qui enregistre une instance auprès du drivermanager en utilisant la méthode registerDriver, c'est pour ça qu'on utilise toujours la technique du Class.forName, avec dans le driver une initialisation statiquie qui fait en gros
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    static {
        DriverManager.registerDriver(new MonDriverAMoi());
    }
    Mais bon, les détails sont laissés à l'appréciation du driver en lui même?
    Ah ok, je savais pas que ça fonctionnait par méthode statique

  12. #12
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Points : 48 804
    Points
    48 804
    Par défaut
    Citation Envoyé par Baptiste Wicht Voir le message
    Ah ok, je savais pas que ça fonctionnait par méthode statique
    sauf que j'ai parlé trop vite. Cf mon deuxième post, il fait des check en interne pour gerer les différents classloaders :/

  13. #13
    Expert éminent sénior
    Avatar de Baptiste Wicht
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2005
    Messages
    7 431
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Suisse

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2005
    Messages : 7 431
    Points : 21 324
    Points
    21 324
    Par défaut
    Citation Envoyé par tchize_ Voir le message
    sauf que j'ai parlé trop vite. Cf mon deuxième post, il fait des check en interne pour gerer les différents classloaders :/
    Juste

    J'ai répondu trop vite aussi

    Si on veut absolument le charger dans un classloader et ne pas utiliser directement la classe du Driver, on peut aussi le rajouter directement dans le classloader système alors ?

    Par contre, c'est encore plus moche que d'appeller directement le driver.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Problème de chargement du driver JDBC
    Par mklegn91 dans le forum Android
    Réponses: 7
    Dernier message: 13/03/2013, 14h03
  2. [JOnAS 5.0.4 / MySql] Chargement du driver JDBC
    Par MaxLaMenaX dans le forum JOnAS
    Réponses: 2
    Dernier message: 11/12/2010, 13h22
  3. Chargement dynamiquement Jar JDBC
    Par matla dans le forum JDBC
    Réponses: 6
    Dernier message: 14/11/2008, 14h55
  4. Probleme de chargement d'un driver JDBC
    Par agno dans le forum JOnAS
    Réponses: 3
    Dernier message: 25/04/2007, 22h30
  5. [debutant] probleme chargement driver (jdbc, mysql)
    Par ADSL[fx] dans le forum JDBC
    Réponses: 9
    Dernier message: 12/03/2006, 12h10

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo