2017-02-04 3 views
2

Ich versuche, ein externes jar zur Laufzeit hinzuzufügen und dann dieses jar zu verwenden, um eine Verbindung zu einer Datenbank herzustellen (anstatt es zu müssen) Fügen Sie dem Pom viele Treiber hinzu, das Ziel ist es, dem Benutzer die Möglichkeit zu geben, einen beliebigen Treiber-Jar zur Laufzeit zu laden. Ich benutze ein Springboot-Projekt und ich versuche, Spring Boots DataSourceBuilder zu verwenden, um die Datenquelle zu erstellen.JDBC-Treiber zur Laufzeit hinzufügen - verursacht durch: java.lang.ClassNotFoundException: com.mysql.jdbc.Driver

Die Antworten und Anregungen in Loading JDBC Driver at Runtime und Loading jars at runtime scheinen nicht für den folgenden Code zu arbeiten:

@Component 
public class DriverLoader { 

    private static final String URL = "jdbc:mysql://localhost:3306/sakila?useSSL=false"; 
    private static final String USER = "root"; 
    private static final String ADMIN = "admin"; 
    private static final String DRIVER_JAR = "C:\\Users\\Sander\\Downloads\\mysql-connector-java-5.1.40.jar"; 

    @PostConstruct 
    private void loadDriver() throws Exception { 
     File file = new File(DRIVER_JAR); 
     if (file != null) { 
      URLClassLoader URLClassLoader = new URLClassLoader(new URL[] {file.toURI().toURL()}, System.class.getClassLoader()); 
      String driverName = DatabaseDriver.fromJdbcUrl(URL).getDriverClassName(); 
      System.out.println(driverName); 

      // lets try to load the class 
      Class<?> driverClass = URLClassLoader.loadClass(driverName); 
      Driver actualDriver = (Driver) driverClass.newInstance(); 
      URLClassLoader.close(); 

      // Throws: Caused by: java.lang.ClassNotFoundException: com.mysql.jdbc.StringUtils 
      /*Properties properties = new Properties(); 
      properties.put("user", USER); 
      properties.put("password", ADMIN); 
      Connection con = actualDriver.connect(URL, properties);*/   

      DataSource dataSource = createNewDataSource(URL, USER, ADMIN); 

      if (dataSource != null) { 
       // lets try to connect 
       // Throws: Caused by: java.lang.ClassNotFoundException: com.mysql.jdbc.Driver 
       dataSource.getConnection().isValid(1); 
      }   
     }  
    } 

    public DataSource createNewDataSource(String url, String username, String password) { 
     return DataSourceBuilder 
       .create() 
       .url(url)  
       .username(username) 
       .password(password) 
       .build(); 
    }  
} 

Snippet des pom Ich verwende:

<parent> 
     <groupId>org.springframework.boot</groupId> 
     <artifactId>spring-boot-starter-parent</artifactId> 
     <version>1.5.1.RELEASE</version> 
     <relativePath/> <!-- lookup parent from repository --> 
    </parent> 

    <properties> 
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 
     <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> 
     <java.version>1.8</java.version> 
    </properties> 

    <dependencies> 
     <dependency> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-starter</artifactId> 
     </dependency> 
     <dependency> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-starter-jdbc</artifactId>   
     </dependency> 
     <dependency> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-starter-test</artifactId> 
      <scope>test</scope> 
     </dependency> 
    </dependencies> 

Wie kann ich die DataSourceBuilder verwenden können erfolgreich eine Verbindung mit einer Datenquelle herstellen, wenn die JAR-Datei zur Laufzeit hinzugefügt wurde?

Voll Stack-Trace:

2017-02-04 20:13:22.201 ERROR 12528 --- [   main] o.a.tomcat.jdbc.pool.ConnectionPool  : Unable to create initial connections of pool. 

java.sql.SQLException: Unable to load class: com.mysql.jdbc.Driver from ClassLoader:[email protected];ClassLoader:[email protected] 
    at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:283) ~[tomcat-jdbc-8.5.11.jar:na] 
    at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:203) ~[tomcat-jdbc-8.5.11.jar:na] 
    at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:732) [tomcat-jdbc-8.5.11.jar:na] 
    at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:664) [tomcat-jdbc-8.5.11.jar:na] 
    at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:479) [tomcat-jdbc-8.5.11.jar:na] 
    at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) [tomcat-jdbc-8.5.11.jar:na] 
    at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) [tomcat-jdbc-8.5.11.jar:na] 
    at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) [tomcat-jdbc-8.5.11.jar:na] 
    at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) [tomcat-jdbc-8.5.11.jar:na] 
    at nl.mierasmade.driver.DriverLoader.loadDriver(DriverLoader.java:54) [classes/:na] 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_112] 
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_112] 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_112] 
    at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_112] 
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:366) [spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE] 
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:311) [spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE] 
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:134) [spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE] 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:409) [spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE] 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1620) [spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE] 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555) [spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE] 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483) [spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE] 
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) [spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE] 
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) [spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE] 
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) [spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE] 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) [spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE] 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761) [spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE] 
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:866) [spring-context-4.3.6.RELEASE.jar:4.3.6.RELEASE] 
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:542) [spring-context-4.3.6.RELEASE.jar:4.3.6.RELEASE] 
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:737) [spring-boot-1.5.1.RELEASE.jar:1.5.1.RELEASE] 
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:370) [spring-boot-1.5.1.RELEASE.jar:1.5.1.RELEASE] 
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:314) [spring-boot-1.5.1.RELEASE.jar:1.5.1.RELEASE] 
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1162) [spring-boot-1.5.1.RELEASE.jar:1.5.1.RELEASE] 
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1151) [spring-boot-1.5.1.RELEASE.jar:1.5.1.RELEASE] 
    at nl.mierasmade.JdbcRuntimeDriverApplication.main(JdbcRuntimeDriverApplication.java:10) [classes/:na] 
Caused by: java.lang.ClassNotFoundException: Unable to load class: com.mysql.jdbc.Driver from ClassLoader:[email protected];ClassLoader:[email protected] 
    at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:56) ~[tomcat-jdbc-8.5.11.jar:na] 
    at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:271) ~[tomcat-jdbc-8.5.11.jar:na] 
    ... 33 common frames omitted 
Caused by: java.lang.ClassNotFoundException: com.mysql.jdbc.Driver 
    at java.net.URLClassLoader.findClass(Unknown Source) ~[na:1.8.0_112] 
    at java.lang.ClassLoader.loadClass(Unknown Source) ~[na:1.8.0_112] 
    at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source) ~[na:1.8.0_112] 
    at java.lang.ClassLoader.loadClass(Unknown Source) ~[na:1.8.0_112] 
    at java.lang.Class.forName0(Native Method) ~[na:1.8.0_112] 
    at java.lang.Class.forName(Unknown Source) ~[na:1.8.0_112] 
    at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:38) ~[tomcat-jdbc-8.5.11.jar:na] 
    ... 34 common frames omitted 
+0

Versuchen Sie, nicht in der Nähe URLClassLoader, was passiert? – cybersoft

+0

Gleiche Ausnahme. Die Dokumentation besagt, dass "auch alle Klassen oder Ressourcen, die bereits geladen sind, weiterhin zugänglich sind." Daher sollte das Schließen nicht das Problem sein. –

+0

Nicht alle Klassen konnten aus diesem Jar geladen werden, daher könnte das Schließen auch der Grund sein ... Es ist seltsam, dass das Laden der Klasse und das Erstellen einer neuen Instanz in Ordnung ist, aber nicht nach dem Schließen – cybersoft

Antwort

2

Ich war in der Lage zu bekommen, wie dies funktioniert:

@Bean 
    public DataSource dynamicDataSource() { 
    ClassLoader classLoader = new URLClassLoader(new URL[]{new URL("file:///C:/Users/xxxx/Desktop/h2-1.4.193.jar")}, Thread.currentThread().getContextClassLoader()); 
    Thread.currentThread().setContextClassLoader(classLoader); 
    DataSource dataSource = DataSourceBuilder.create().url('jdbc:h2:mem:test;DB_CLOSE_DELAY=-1').build(); 
    dataSource.getConnection().isValid(10); 
    return dataSource; 
    } 
0

versuchen this.getClass().getClassLoader() oder Thread.getContextClassLoader() statt Systems Klassenlader zu verwenden. Siehe this Abschnitt E.5.2 System-Classloader

+0

Beide this.getClass(). GetClassLoader() 'als' Thread.currentThread(). getContextClassLoader() 'wirf die Klasse nicht gefunden Ausnahme. Danke für den Link. –

Verwandte Themen