Jdbc driver class cannot be loaded with gradle 2.0 (but worked with 1.12)


(mw) #1

to get a jdbc connection in a gradle script, this hack was needed:

//we need this hack to satisfy the classloader conditions for javax.sql.DriverManager
URLClassLoader loader = GroovyObject.class.classLoader
configurations.jdbcdriver.each {File file ->
 loader.addURL(file.toURI().toURL())
}
//Class.forName() is part of the above hack
println "jdbc drivers: "+Class.forName("org.h2.Driver")+", "+Class.forName("org.postgresql.Driver")

It works fine with gradle 1.12 but gradle 2.0 throws a ClassNotFoundException


(Luke Daley) #2

How are you trying to actually use the driver? Ant? Directly in build script?

If you can provide a sample that I can play I can more than likely make it work.


(mw) #3

Thanks for your reply. Here is the sample:

import groovy.sql.Sql
apply plugin: 'groovy'
   repositories {
 mavenCentral()
}
  configurations {
 jdbcdriver
}
  dependencies {
 jdbcdriver 'com.h2database:h2:1.3.173','org.postgresql:postgresql:9.3-1100-jdbc41'
 }
  task loadDB << {
 //we need this hack to satisfy the classloader conditions for javax.sql.DriverManager
 URLClassLoader loader = GroovyObject.class.classLoader
 configurations.jdbcdriver.each {File file ->
  loader.addURL(file.toURI().toURL())
 }
 //Class.forName() is part of the above hack
 println "jdbc drivers: "+Class.forName("org.h2.Driver")+", "+Class.forName("org.postgresql.Driver")
 println "connecting to database"
 def sql= Sql.newInstance("jdbc:h2:mem:test", "sa", "sa")
 sql.execute("create table users (id int primary key, name varchar(40), email varchar(40))")
 sql.execute("insert into users (id, name,email) values (1,'mick', 'mick@test.com')")
 sql.close()
}

(Luke Daley) #4

Here’s a version that works:

<code>
import groovy.sql.Sql
repositories {
  jcenter()
}

configurations {
  jdbcdriver
}

dependencies {
  jdbcdriver ‘com.h2database:h2:1.3.173’
}

task loadDB << {
  configurations.jdbcdriver.files.each {
    Sql.classLoader.addURL(it.toURI().toURL())
  }
  
  def sql = Sql.newInstance(“jdbc:h2:mem:test”, “sa”, “sa”)
  sql.execute(“create table users (id int primary key, name varchar(40), email varchar(40))”)
  sql.execute(“insert into users (id, name,email) values (1,‘mick’, ‘mick@test.com’)”)
  sql.close()
}
</code>


(mw) #5

Same problem:

* What went wrong:
Execution failed for task ':loadDB'.
> No suitable driver found for jdbc:h2:mem:test

Here is my version output:

gradle -v
  ------------------------------------------------------------
Gradle 2.0
------------------------------------------------------------
  Build time:
 2014-07-01 07:45:34 UTC
Build number: none
Revision:
   b6ead6fa452dfdadec484059191eb641d817226c
  Groovy:
     2.3.3
Ant:
        Apache Ant(TM) version 1.9.3 compiled on December 23 2013
JVM:
        1.8.0_11 (Oracle Corporation 25.11-b03)
OS:
         Linux 3.15.8-200.fc20.x86_64 amd64

[RESOLVED] Dynamically Loading Classes via Plugin
(Marcin Erdmann) #6

You either need to register your driver:

import java.sql.DriverManager
  DriverManager.registerDriver(loader.loadClass("org.h2.Driver").newInstance())

or use explicit driver in Sql.newInstance() without having to load the class:

def sql= Sql.newInstance("jdbc:h2:mem:test", "sa", "sa", "org.h2.Driver")

(mw) #7

Thank you very much, works excellent! I made one adjustment to the DriverManager solution:

configurations.jdbcdriver.files.each {
 Sql.classLoader.addURL(it.toURI().toURL())
  }
  DriverManager.registerDriver(Sql.classLoader.loadClass("org.h2.Driver").newInstance())

(Luke Daley) #8

Right, I had that in then took it out – but it kept working when I took it out because I was using the daemon and DriverManager uses static state (so it still had the registration from the last build).