Quantcast

using jdbc driver in a task fails

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

using jdbc driver in a task fails

phaseless
I'm trying to do some Sql stuff and added

>import groovy.sql.Sql

but when I try to use the Sql class with a line like the following in a gradle task

>sql = Sql.newInstance("jdbc:oracle:thin:@srv:1521:database","usr","pswrd","oracle.jdbc.OracleDriver")

I get a 'Class Not Found Exception'.
To resolve the drive dependencies I added the following lines at the beginning of the build.gradle script:

>buildscript {
>    repositories {
>        flatDir name: 'localRepository', dirs: 'lib'
>    }
>    dependencies {
>        classpath  name: 'ojdbc14'
>    }
>}

and put the oracle driver 'ojdbc14.jar' into the directory '$rootDir/lib' which seems to be correctly resolved.
Even with these lines the driver class is not found.

Also other attempts to advice the DriverManager to register the oracle driver like
>   Class.forName("oracle.jdbc.OracleDriver")
do not work, although the driver can be instanciated like this:
>  def oracleDriver = new oracle.jdbc.OracleDriver()
>  println "hello jdbc: " + oracleDriver.toString()
>  java.sql.DriverManager.registerDriver ( oracleDriver )
Registration seems not to be successful, since  
> java.sql.DriverManager.getDrivers().each { println "Driver: " + it.name }
does not respond anything.

I think, that there is a problem with the classLoader but can't figure out, what!

Can anybody help?
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: using jdbc driver in a task fails

Philip Crotwell
This may not be exactly what you want, but I use this to allow running
a class in my project within the gradle build. Probably just need to
add the oracle jar to this same classloader.

    def classLoader = new GroovyClassLoader(Project.class.classLoader)
    classLoader.addURL(new File('build/classes/main').toURL())
    configurations.default.each { File file -> classLoader.addURL(file.toURL())}
    def myCodeHere = classLoader.loadClass('com.example.MyClass').newInstance()


Philip

On Mon, Oct 5, 2009 at 10:37 AM, phaseless <[hidden email]> wrote:

>
> I'm trying to do some Sql stuff and added
>
>>import groovy.sql.Sql
>
> but when I try to use the Sql class with a line like the following in a
> gradle task
>
>>sql =
> Sql.newInstance("jdbc:oracle:thin:@srv:1521:database","usr","pswrd","oracle.jdbc.OracleDriver")
>
> I get a 'Class Not Found Exception'.
> To resolve the drive dependencies I added the following lines at the
> beginning of the build.gradle script:
>
>>buildscript {
>>    repositories {
>>        flatDir name: 'localRepository', dirs: 'lib'
>>    }
>>    dependencies {
>>        classpath  name: 'ojdbc14'
>>    }
>>}
>
> and put the oracle driver 'ojdbc14.jar' into the directory '$rootDir/lib'
> which seems to be correctly resolved.
> Even with these lines the driver class is not found.
>
> Also other attempts to advice the DriverManager to register the oracle
> driver like
>>   Class.forName("oracle.jdbc.OracleDriver")
> do not work, although the driver can be instanciated like this:
>>  def oracleDriver = new oracle.jdbc.OracleDriver()
>>  println "hello jdbc: " + oracleDriver.toString()
>>  java.sql.DriverManager.registerDriver ( oracleDriver )
> Registration seems not to be successful, since
>> java.sql.DriverManager.getDrivers().each { println "Driver: " + it.name }
> does not respond anything.
>
> I think, that there is a problem with the classLoader but can't figure out,
> what!
>
> Can anybody help?
>
> --
> View this message in context: http://www.nabble.com/using-jdbc-driver-in-a-task-fails-tp25752010p25752010.html
> Sent from the gradle-user mailing list archive at Nabble.com.
>
>
> ---------------------------------------------------------------------
> To unsubscribe from this list, please visit:
>
>    http://xircles.codehaus.org/manage_email
>
>
>

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: using jdbc driver in a task fails

phaseless
Thanks for the reply Philip, but this does neither work.
I think I wil give it up for now, since I spent the too much time for it.
I'll use an ordinary groovy script ...

Christoph



Philip Crotwell wrote
This may not be exactly what you want, but I use this to allow running
a class in my project within the gradle build. Probably just need to
add the oracle jar to this same classloader.

    def classLoader = new GroovyClassLoader(Project.class.classLoader)
    classLoader.addURL(new File('build/classes/main').toURL())
    configurations.default.each { File file -> classLoader.addURL(file.toURL())}
    def myCodeHere = classLoader.loadClass('com.example.MyClass').newInstance()


Philip



---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: using jdbc driver in a task fails

Adam Murdoch-2
In reply to this post by phaseless


phaseless wrote:
I'm trying to do some Sql stuff and added

  
import groovy.sql.Sql
    

but when I try to use the Sql class with a line like the following in a
gradle task

  
sql =
    
Sql.newInstance("jdbc:oracle:thin:@srv:1521:database","usr","pswrd","oracle.jdbc.OracleDriver")

I get a 'Class Not Found Exception'.
To resolve the drive dependencies I added the following lines at the
beginning of the build.gradle script:

  
buildscript {
   repositories {
       flatDir name: 'localRepository', dirs: 'lib'
   }
   dependencies {
       classpath  name: 'ojdbc14'
   }
}
    

and put the oracle driver 'ojdbc14.jar' into the directory '$rootDir/lib'
which seems to be correctly resolved.
Even with these lines the driver class is not found.

Also other attempts to advice the DriverManager to register the oracle
driver like 
  
  Class.forName("oracle.jdbc.OracleDriver")
    
do not work, although the driver can be instanciated like this:
  
 def oracleDriver = new oracle.jdbc.OracleDriver()
 println "hello jdbc: " + oracleDriver.toString()
 java.sql.DriverManager.registerDriver ( oracleDriver )
    
Registration seems not to be successful, since  
  
java.sql.DriverManager.getDrivers().each { println "Driver: " + it.name }
    
does not respond anything.

I think, that there is a problem with the classLoader but can't figure out,
what!

Can anybody help?

  

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
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: using jdbc driver in a task fails

phaseless
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?
- 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?

Perhaps my knowledge of gradle i to limited yet. 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.
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
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: using jdbc driver in a task fails

Adam Murdoch-2


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 | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: using jdbc driver in a task fails

phaseless
Hello Adam,

thank you very much for your explication.
Unfortunately
        loader.addURL ( new File('lib/ojdbc.jar').*toURI().*toURL() )
doesn't work.
But I got some new insight into the work of classLoaders within gradle.

Go on making the impossible possible ...

Thanks again

Christoph


Adam Murdoch-2 wrote

Using a file should work - perhaps try

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


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