phaseless wrote:
Hello Adam,

thank you very much. This really works!!!
However, I'm curious to understand why, but don't do it in detail.
Here is my code, that works:
configurations {
    driver
}

repositories {
  flatDir name: 'localRepository', dirs: 'lib'
}

dependencies {
    driver name: 'ojdbc14'
}

task sql << {
        URLClassLoader loader = GroovyObject.class.classLoader
        
        configurations.driver.each {File file ->
            loader.addURL(file.toURL())
        }
        Class driverClass = loader.loadClass('oracle.jdbc.OracleDriver')
        
        // You might need one or both of these as well
        Driver driverInstance = driverClass.newInstance()
        java.sql.DriverManager.registerDriver(driverInstance)

Sql sql = Sql.newInstance("jdbc:oracle:thin:@server:1521:SID","usr","pswd") }

There are two things, I'm interested in:
- I tried similar with  
   'URLClassLoader loader = this.class.classLoader'
instead of 'URLClassLoader loader = GroovyObject.class.classLoader'
  but it did not work. I know about the different phases of gradle but why
does GroovyObject make the big difference?

Groovy is loaded in a shared ClassLoader (along with the Gradle API, and so on). Each project build script gets it's own ClassLoader with the shared one as parent. So, GroovyObject.class.classLoader refers to the ClassLoader which contains Groovy, and this.class.classLoader refers to the build script ClassLoader.

When you call Sql.newInstance(), it calls DriverManager.createConnection(), which will only allow access to the drivers loaded by the same ClassLoader as the caller. Because Sql is part of Groovy, it is in the Groovy ClassLoader. This means you must add the driver classes to the Groovy ClassLoader so that they are visible to Sql. If you use the build script ClassLoader, the driver classes won't be visible.

- The second thing is: Why does it make a difference to have the
configuration 'driver', although this
   is not used anywhere in the task? Does this mean that all files of all
defined configurations add
   up to a big 'Classpath' supplied to the tasks of 'build.gradle'?
The alternative formulation loader.addURL ( new File('lib/ojdbc.jar').toURL() )
   instead of the configurations.driver.each-Closure does not work!!! Why
not?

Using a file should work - perhaps try

loader.addURL ( new File('lib/ojdbc.jar').*toURI().*toURL() )


Perhaps my knowledge of gradle i to limited yet.

I suspect its more due to DriverManager's awkward API.

 May be the actual
documentation lacks in a general
introductory chapter about the meaning  of configurations, dependencies,
artifacts ... for those
who do not come as a Maven or Ivy adept.

I think that's true.

Nevertheless I want to say that I admire the consice and straight forward
style of the documentation
and that I'm very happy about the agility and velocity of the develoment.
Thank you very much

Christoph



Adam Murdoch-2 wrote:
DriverManager will only let you access drivers which have been loaded by the calling class' classloader. In the build script, the caller to DriverManager isn't actually the build script, it is Groovy. So, you need to load the driver in the same classloader as Groovy.

Here is an example. It uses H2, but should work with the Oracle driver
too.

configurations {
    driver
}

dependencies {
    driver "com.h2database:h2:1.2.120"
}

URLClassLoader loader = GroovyObject.class.classLoader
configurations.driver.each {File file ->
    loader.addURL(file.toURL())
}
Class driver = loader.loadClass('org.h2.Driver')
// You might need one or both of these as well
// Driver instance = driver.newInstance()
// DriverManager.registerDriver(instance)

Sql sql = Sql.newInstance("jdbc:h2:$buildDir/test", "sa", "")


--
Adam Murdoch
Gradle Developer
http://www.gradle.org





--
Adam Murdoch
Gradle Developer
http://www.gradle.org

Reply via email to