2010-06-10 20 views
15

¿Cómo puedo agregar controladores JDBC en tiempo de ejecución a Jython? El uso de CLASSPATH funciona, pero el uso de sys.path no funciona con zxJDBC aunque la clase se importa bien y se puede manipular desde el intérprete de Jython.Jython CLASSPATH, sys.path y controladores JDBC

¿Por qué este trabajo:

$ CLASSPATH=/tmp/jtds\-1.2.5.jar ./jython 
*sys-package-mgr*: processing new jar, '/private/tmp/jtds-1.2.5.jar' 
Jython 2.5.1 (Release_2_5_1:6813, Sep 26 2009, 13:47:54) 
[Java HotSpot(TM) 64-Bit Server VM (Apple Inc.)] on java1.6.0_20 
Type "help", "copyright", "credits" or "license" for more information. 
>>> from java.lang import Class 
>>> Class.forName('net.sourceforge.jtds.jdbc.Driver') 
<type 'net.sourceforge.jtds.jdbc.Driver'> 

Pero esto no es así?

$ ./jython 

Jython 2.5.1 (Release_2_5_1:6813, Sep 26 2009, 13:47:54) 
[Java HotSpot(TM) 64-Bit Server VM (Apple Inc.)] on java1.6.0_20 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import sys 
>>> sys.path.extend(['/tmp/jtds-1.2.5.jar']) 
>>> from java.lang import Class 
>>> Class.forName('net.sourceforge.jtds.jdbc.Driver') 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
     at java.net.URLClassLoader$1.run(URLClassLoader.java:202) 
     at java.security.AccessController.doPrivileged(Native Method) 
     at java.net.URLClassLoader.findClass(URLClassLoader.java:190) 
     at java.lang.ClassLoader.loadClass(ClassLoader.java:307) 
     at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301) 
     at java.lang.ClassLoader.loadClass(ClassLoader.java:248) 
     at java.lang.Class.forName0(Native Method) 
     at java.lang.Class.forName(Class.java:169) 
     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
     at java.lang.reflect.Method.invoke(Method.java:597) 

java.lang.ClassNotFoundException: java.lang.ClassNotFoundException: net.sourceforge.jtds.jdbc.Driver 
>>> sys.path 
['', '/home/me/pkg/jython2.5.1/Lib/site-packages/distribute-0.6.13-py2.5.egg', '/home/me/pkg/jython2.5.1/Lib', '__classpath__', '__pyclasspath__/', '/home/me/pkg/jython2.5.1/Lib/site-packages', '/home/me/pkg/jython2.5.1/Lib/site-packages/setuptools-0.6c11-py2.5.egg-info', '/tmp/jtds-1.2.5.jar'] 
>>> import net.sourceforge.jtds.jdbc.Driver as Driver 
>>> drv = Driver() 
>>> drv 
jTDS 1.2.5 

¿Tiene algo que ver con el cargador de clases?

Respuesta

5

La solución es complicada, pero todo se explica here.

+1

Parece que la razón es porque el JDBC DriverManager solo usa controladores cargados usando el cargador de clases del sistema, aunque lo que está registrado es una instancia del controlador, no una clase. Gracias por su enlace. Para cualquier otra lectura, http://stackoverflow.com/questions/288828/how-to-use-a-jdbc-driver-from-an-arbitrary-location y http://www.kfu.com/~nsayer/ Java/dyn-jdbc.html puede ser útil. – lmz

+4

-1 Enlace muerto, por lo que la solución se ha perdido. – brice

+0

El enlace funciona bien. – hhhhhh

19

Parece que incluso el enlace actualizado ya no funciona (al menos con jython-2.5.3b3).

Aquí hay una versión de trabajo:

def importJar(jarFile): 
    ''' 
    import a jar at runtime (needed for JDBC [Class.forName]) 

    adapted from http://forum.java.sun.com/thread.jspa?threadID=300557 
    Author: SG Langer Jan 2007 translated the above Java to Jython 
    Author: [email protected] simplified and updated for jython-2.5.3b3 

    >>> importJar('jars/jtds-1.2.5.jar') 
    >>> import java.lang.Class 
    >>> java.lang.Class.forName('net.sourceforge.jtds.jdbc.Driver') 
    <type 'net.sourceforge.jtds.jdbc.Driver'> 
    ''' 
    from java.net import URL, URLClassLoader 
    from java.lang import ClassLoader 
    from java.io import File 
    m = URLClassLoader.getDeclaredMethod("addURL", [URL]) 
    m.accessible = 1 
    m.invoke(ClassLoader.getSystemClassLoader(), [File(jarFile).toURL()]) 

if __name__ == '__main__': 
    import doctest 
    doctest.testmod() 

sigo this Gist actualizado con mi versión de producción.

+0

El código del enlace actualizado de arriba no funcionó, ¡pero esto fue así! (Tuve que sacar los comentarios) – bobfet1

+0

El código en el libro de Jython 1.0 no funcionó para mí tampoco en Jython 2.5.2, pero lo hizo importJar. Gracias ! – David