From: John G. <jgo...@co...> - 2001-11-07 20:22:09
|
Hi, I am accessing some python code from Java. When I try to use interp.get() (where inter is a PythonInterpreter object), I get an error saying it can't convert my object to the appropriate Java one. However! My object is a python subclass of the Java object I want it to be. IE, in Java I'm saying: ListBO newobj = (ListBO) interp.get("cl", this.getClass()); ("this" is a ListBO instance) In Python, cl is a variable that holds an instance of a ListBOFoo class, which is defined: class ListBOFoo(quovix.business.util.ListBO): ... The code seems to work (quovix is imported properly, etc). It's just that calling "get" on it returns the conversion problem. I'm not sure where to go to fix this. Ideas? -- John -- John Goerzen <jgo...@co...> GPG: 0x8A1D9A1F www.complete.org |
From: John G. <jgo...@co...> - 2001-11-07 20:51:28
|
And as an additional data point: If I request an object of type java.lang.Object from get(), get() works. What's more, newobj.getClass().getSuperclass().getName() returns quovix.business.util.ListBO! However, casting newobj from Object to ListBO fails with a java.lang.ClassCastException on ListBOFoo$ListBOFoo$0! I'm rather mystified now. John Goerzen <jgo...@co...> writes: > Hi, > > I am accessing some python code from Java. When I try to use > interp.get() (where inter is a PythonInterpreter object), I get an > error saying it can't convert my object to the appropriate Java one. > > However! > > My object is a python subclass of the Java object I want it to be. > > IE, in Java I'm saying: > > ListBO newobj = (ListBO) interp.get("cl", this.getClass()); > > ("this" is a ListBO instance) > > In Python, cl is a variable that holds an instance of a ListBOFoo > class, which is defined: > > class ListBOFoo(quovix.business.util.ListBO): > ... > > The code seems to work (quovix is imported properly, etc). It's just > that calling "get" on it returns the conversion problem. > > I'm not sure where to go to fix this. Ideas? > > -- John > > -- > John Goerzen <jgo...@co...> GPG: 0x8A1D9A1F www.complete.org > > _______________________________________________ > Jython-users mailing list > Jyt...@li... > https://lists.sourceforge.net/lists/listinfo/jython-users -- John Goerzen <jgo...@co...> GPG: 0x8A1D9A1F www.complete.org |
From: Jeff E. <je...@ad...> - 2001-11-08 16:23:52
|
This seems a little more familiar since you are loading the java class with a custom class loader. When this has worked for me before, I have always used the system default class loader. Try finding the classloader for the superclass, as jython sees it. Something like this: interp.exec("super=mod.ListBO"); Object pySuperClass = interp.get("super",Object.class); System.out.println(pySuperClass); System.out.println( ((Class)pySuperClass).getClassLoader().getClass().getName()); I suspect that the jython super is not loaded by the same classloader and that is the root of your problems. I'm not sure if there is a way to tell the jython interpreter to use your custom classloader without having to rewrite your scripts. Samuele Pedroni would probably be able to answer that right off. You might be able to set your custom classloader in the interpreter's name space and rewrite your scripts to use that. Something like this: In Java: interp.set("classloader",this.getClass().getClassLoader()); In Python: # Replace normal Python import syntax with this: ListBO=classloader.loadClass("quovix.business.util.ListBO") class ListBOFoo(ListBO): # The rest as usual It certainly would be preferable to hook into the jython import mechanism instead. I don't know how to do that. John Goerzen wrote: > OK. I did: > > System.out.println(this.getClass().getClassLoader().getClass().getName()); > System.out.println(newobj.getClass().getClassLoader().getClass().getName()); > > Resulting in: > > com.lutris.classloader.MultiClassLoader > org.python.core.BytecodeLoader1 > > MultiClassLoader is a subclass of java.lang.ClassLoader adding in > functionality such as loading classes from URLs, ZIPs, etc. (This is > an Enhydra servlet). > > Interestingly, this is JDK 2 but it's using Jython's JDK 1 > BytecodeLoader. > > Let me show you exactly what I'm trying to do: > > In Java: (before adding the printlns and other debug stuff) > > PythonInterpreter interp = new PythonInterpreter(); > interp.exec("mod = __import__('" + brob + "')"); > interp.exec("cl = mod." + brob + "()"); > Object newobj = interp.get("cl", Object.class); > return (ListBO) newobj; > > In this case, 'brob' is ListBOFoo, and it's loading this Python code: > > from quovix.business.util import * > > class ListBOFoo(ListBO): > def getDescription(self): > desc = ListBO.getDescription(self) # Superclass call > return "Foo_" + desc > > Very simple stuff. I have it working with jythonc but I'm trying to > eliminate jythonc from the picture so it can be loaded 100% > dynamically. > > Thanks for your assistance! > > -- John > > > Jeff Emanuel <je...@ad...> writes: > > >>The java class Class has a method to return its ClassLoader. >>You can do something like this: >> >> System.out.println(this.getClass().getClassLoader()); >> System.out.println(newobj.getClass().getClassLoader()); >> >>If they are different, the classes are in effect not equal. >>I'm not sure why that would be or how to work around it. I've >>done things as you are trying and it worked. If we know >>what the classloaders are, perhaps we can discover why they >>are different, or what action to take. >> >>You can also try newobj.getClass().isAssignableFrom(this.getClass()) >> >>That is likely to be false since you know you can't do the cast. >> >> >> >>John Goerzen wrote: >> >> >>>Jeff Emanuel <je...@ad...> writes: >>> >>> >>>>It is likely that your ListBO class was loaded by two different class >>>>loaders. Try printing out the classloaders for your Java this instance >>>>and your newobj. Even if the classes are the same, if they were loaded >>>>by different loaders, then they really aren't equal. >>>> >>>> >>>OK this is unfamiliar territory for me. I don't know what a class >>> >>>loader is or how to print it. If the loaders are different, how would >>>I go about resolving the problem? One is the regular static stuff >>>loaded as usual with classes generated by javac; the other, Python. >>>Ideas? >>>Thanks! >>> >>>-- John >>> >> >> > |
From: John G. <jgo...@co...> - 2001-11-08 17:17:53
|
Jeff Emanuel <je...@ad...> writes: > This seems a little more familiar since you are loading the java > class with a custom class loader. When this has worked for me > before, I have always used the system default class loader. Oddly enough, I didn't even realize that class loaders even existed until your message yesterday, and certainly not that a non-default loader was already being used. Alas, I fear that I have no control over what loader is being used at the moment. > Try finding the classloader for the superclass, as jython sees it. > Something like this: I tried this, just from Python at the top of the module: print "Superclass loader: " + ListBO.getClassLoader().getClass().getName() Prior to your suggested hack below, this printed out org.python.core.SyspathJavaLoader. > I suspect that the jython super is not loaded by the same classloader and This is true... > that is the root of your problems. I'm not sure if there is a way to ... but it doesn't seem to be the root of my problems. > You might be able to set your custom classloader in the interpreter's > name space and rewrite your scripts to use that. Something like this: [ snip ] I had to hack it to get the variable into the module, but I got it to do that. > ListBO=classloader.loadClass("quovix.business.util.ListBO") Now, the above print displays com.lutris.classloader.MultiClassLoader -- the same as for my code in static Java. But -- I still get the same ClassCastException in Java as before -- probably because the ListBOFoo object is still being loaded by Python's loader (ByteLoader1). -- John |
From: Jeff E. <je...@ad...> - 2001-11-08 21:40:52
|
I tried replicating what you are doing with a little stand-alone java program, but I can't seem to get the conversion to fail. Here's another hack you could try. Instead of passing the classloader to the script, pass the superclass. Java: interp.set("ListBO", this.getClass()); Python: # Omit import, ListBO is in namespace from above. class ListBOFoo(ListBO): # etc... John Goerzen wrote: > Jeff Emanuel <je...@ad...> writes: > > >>This seems a little more familiar since you are loading the java >>class with a custom class loader. When this has worked for me >>before, I have always used the system default class loader. >> > > Oddly enough, I didn't even realize that class loaders even existed > until your message yesterday, and certainly not that a non-default > loader was already being used. Alas, I fear that I have no control > over what loader is being used at the moment. > > >>Try finding the classloader for the superclass, as jython sees it. >>Something like this: >> > > I tried this, just from Python at the top of the module: > > print "Superclass loader: " + ListBO.getClassLoader().getClass().getName() > > Prior to your suggested hack below, this printed out > org.python.core.SyspathJavaLoader. > > >>I suspect that the jython super is not loaded by the same classloader and >> > > This is true... > > >>that is the root of your problems. I'm not sure if there is a way to >> > > ... but it doesn't seem to be the root of my problems. > > >>You might be able to set your custom classloader in the interpreter's >>name space and rewrite your scripts to use that. Something like this: >> > > [ snip ] > > I had to hack it to get the variable into the module, but I got it to > do that. > > >> ListBO=classloader.loadClass("quovix.business.util.ListBO") >> > > Now, the above print displays com.lutris.classloader.MultiClassLoader > -- the same as for my code in static Java. But -- I still get the > same ClassCastException in Java as before -- probably because the > ListBOFoo object is still being loaded by Python's loader (ByteLoader1). > > > -- John > > _______________________________________________ > Jython-users mailing list > Jyt...@li... > https://lists.sourceforge.net/lists/listinfo/jython-users > |
From: John G. <jgo...@co...> - 2001-11-08 21:54:32
|
Tried, still didn't help.. Of note: when I print the loader of ListBO from within Python, it says com.lutris.classloader.MultiClassLoader. When I print the loader of the superclass of ListBOFoo from within Java (that superclass is the same ListBO), it says sun.misc.Launcher$AppClassLoader! More and more puzzling. I feel that I'm SO CLOSE! Also: I'm now pulling the *class* from python to Java, not an instance of it. That seems to help, maybe... -- John Jeff Emanuel <je...@ad...> writes: > I tried replicating what you are doing with a little stand-alone > java program, but I can't seem to get the conversion to fail. > > Here's another hack you could try. Instead of passing the > classloader to the script, pass the superclass. > > > Java:I p > interp.set("ListBO", this.getClass()); > > Python: > > # Omit import, ListBO is in namespace from above. > > class ListBOFoo(ListBO): # etc... > > > John Goerzen wrote: > > > Jeff Emanuel <je...@ad...> writes: > > > > >>This seems a little more familiar since you are loading the java > >>class with a custom class loader. When this has worked for me > >>before, I have always used the system default class loader. > >> > > Oddly enough, I didn't even realize that class loaders even existed > > > until your message yesterday, and certainly not that a non-default > > loader was already being used. Alas, I fear that I have no control > > over what loader is being used at the moment. > > > > >>Try finding the classloader for the superclass, as jython sees it. > >>Something like this: > >> > > I tried this, just from Python at the top of the module: > > > print "Superclass loader: " + > > ListBO.getClassLoader().getClass().getName() > > > Prior to your suggested hack below, this printed out > > > org.python.core.SyspathJavaLoader. > > > > >>I suspect that the jython super is not loaded by the same classloader and > >> > > This is true... > > > > > >>that is the root of your problems. I'm not sure if there is a way to > >> > > ... but it doesn't seem to be the root of my problems. > > > > > >>You might be able to set your custom classloader in the interpreter's > >>name space and rewrite your scripts to use that. Something like this: > >> > > [ snip ] > > > I had to hack it to get the variable into the module, but I got it to > > > do that. > > > > >> ListBO=classloader.loadClass("quovix.business.util.ListBO") > >> > > Now, the above print displays com.lutris.classloader.MultiClassLoader > > > -- the same as for my code in static Java. But -- I still get the > > same ClassCastException in Java as before -- probably because the > > ListBOFoo object is still being loaded by Python's loader (ByteLoader1). > > -- John > > > _______________________________________________ > > > Jython-users mailing list > > Jyt...@li... > > https://lists.sourceforge.net/lists/listinfo/jython-users > > > > > -- John Goerzen <jgo...@co...> GPG: 0x8A1D9A1F www.complete.org |
From: <bc...@wo...> - 2001-11-08 22:28:53
|
[John Goerzen] >Tried, still didn't help.. > >Of note: when I print the loader of ListBO from within Python, it says >com.lutris.classloader.MultiClassLoader. When I print the loader of >the superclass of ListBOFoo from within Java (that superclass is the >same ListBO), it says sun.misc.Launcher$AppClassLoader! More and more >puzzling. That is because the BytecodeLoaders happens to search the SyspathJavaLoader before searching the referent class loaders. It's a bug. > I feel that I'm SO CLOSE! Try calling Py.getSystemState().setClassLoader(this.getClass().getClassLoader()); It will effectively disable attempts to import java classes from sys.path and instead only try to load them from the MultiClassLoader. >Also: I'm now pulling the *class* from python to Java, not an instance of it. >That seems to help, maybe... Nah. regards, finn |
From: John G. <jgo...@co...> - 2001-11-09 14:16:11
|
bc...@wo... (Finn Bock) writes: > That is because the BytecodeLoaders happens to search the > SyspathJavaLoader before searching the referent class loaders. It's a > bug. [snip] > Try calling > > Py.getSystemState().setClassLoader(this.getClass().getClassLoader()); > > It will effectively disable attempts to import java classes from > sys.path and instead only try to load them from the MultiClassLoader. Hmm. It didn't work. (I tried setting it both before and after instantiating my PythonInterpreter object in Java; didn't work either way). Interesting data points: * In Python, I printed: print Py.getSystemState().getClassLoader().getClass().getName() result: com.lutris.classloader.MultiClassLoader which is correct. * Java still claims that the loader for the base class of my Python class is sun.misc.Launcher$AppClassLoader. I at least have it -- through MANY hacks -- showing the correct loader. * I just noticed that, somewhere along the line, Java shows the superclass of my ListBOFoo as being PyFunctionTable. Eep! I don't quite know where that changed from ListBO. Somewhere in my testing I guess. Sigh. Also: Is it possible to tell Jython where to create the .class files that it generates on the fly? -- John > > >Also: I'm now pulling the *class* from python to Java, not an instance of it. > >That seems to help, maybe... > > Nah. > > regards, > finn -- John Goerzen <jgo...@co...> GPG: 0x8A1D9A1F www.complete.org |
From: <bc...@wo...> - 2001-11-09 14:35:38
|
[John Goerzen] >Is it possible to tell Jython where to create the .class files that it >generates on the fly? Try the option python.options.proxyDebugDirectory=d:\\temp\\myproxies Added to your ~/.jython file or the registry file or specified in the properties to the PythonInterpreter.initialize(...) method or specified as system properties on the commandline when starting java. Which to use depends on your environment. When embedding, I suggest the initialize(..) argument way, as in >http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/jython/jython/org/python/util/PyServlet.java?annotate=1.11#73 regards, finn |
From: John G. <jgo...@co...> - 2001-11-09 14:44:53
|
bc...@wo... (Finn Bock) writes: > Try calling > > Py.getSystemState().setClassLoader(this.getClass().getClassLoader()); > > It will effectively disable attempts to import java classes from > sys.path and instead only try to load them from the MultiClassLoader. Almost there!! (Thanks to you and Jeff Emanuel for all your help). I have thinks WORKING! but only if I use Jeff's trick of: interp.set("ListBO", this.getClass()). If I try to "import quovix" or "from quovix.business.util import ListBO" from Python after setting the classloader per your instructions, Python gives an "ImportError: no module named quovix". Oddly, it can import things like java.util.Date. I'm unsure why it can't find my own classes -- obviously the MultiClassLoader can because all this stuff is being called from ListBO itself. So it's a bit strange. But I can work around that certainly. Also I'm curious why this works: interp.exec("import ListBOFoo"); Class pclass = (Class) interp.eval("ListBOFoo.ListBOFoo").__tojava__(Class.class); But this doesn't: interp.exec("mod = __import__('ListBOFoo')"); Class pclass = (Class) interp.eval("mod.ListBOFoo").__tojava__(Class.class); The second dies on the eval claiming that there is no such symbol in Python. Not a biggie but a weird thing anyway. Thanks for all your help! -- John |
From: <bc...@wo...> - 2001-11-09 15:11:19
|
[John Goerzen] >bc...@wo... (Finn Bock) writes: > >> Try calling >> >> Py.getSystemState().setClassLoader(this.getClass().getClassLoader()); >> >> It will effectively disable attempts to import java classes from >> sys.path and instead only try to load them from the MultiClassLoader. > >Almost there!! > >(Thanks to you and Jeff Emanuel for all your help). > >I have thinks WORKING! but only if I use Jeff's trick of: >interp.set("ListBO", this.getClass()). If I try to >"import quovix" or "from quovix.business.util import ListBO" from >Python after setting the classloader per your instructions, Python >gives an "ImportError: no module named quovix". That is because java have no solid way of querying a classloader about which java packages it can serve. To load a java package from from sys.path, we have to do a directory listning to discover the available java directories. When disabling java loading from sys.path (by setting the classloader) we also disable this method of java package discovery. Take another look at the PyServlet example: > http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/jython/jython/org/python/util/PyServlet.java?annotate=1.11#73 and notice the calls to sys.add_package(..) and sys.add_classdir(..). These calls will give some hints to the package manager that one of the custom classloaders in the environment is able to serve additional java packages. It is important to know that the sys.add_XXX() methods does not enable loading of java classes from these sources. The methods only allow loading of java packages. >Oddly, it can import things like java.util.Date. Not odd at all. Jython scans the rt.jar file for all java classes and build a list of available java package from this list. >I'm unsure why it can't find my own >classes -- obviously the MultiClassLoader can because all this stuff >is being called from ListBO itself. So it's a bit strange. But I can >work around that certainly. > >Also I'm curious why this works: > >interp.exec("import ListBOFoo"); >Class pclass = (Class) interp.eval("ListBOFoo.ListBOFoo").__tojava__(Class.class); > >But this doesn't: > >interp.exec("mod = __import__('ListBOFoo')"); >Class pclass = (Class) interp.eval("mod.ListBOFoo").__tojava__(Class.class); > >The second dies on the eval claiming that there is no such symbol in >Python. Not a biggie but a weird thing anyway. Which symbol? Do you have a stacktrace? >Thanks for all your help! You's welcome. regards, finn |
From: Samuele P. <ped...@bl...> - 2001-11-10 17:06:58
|
> [John Goerzen] > > >Tried, still didn't help.. > > > >Of note: when I print the loader of ListBO from within Python, it says > >com.lutris.classloader.MultiClassLoader. When I print the loader of > >the superclass of ListBOFoo from within Java (that superclass is the > >same ListBO), it says sun.misc.Launcher$AppClassLoader! More and more > >puzzling. > > That is because the BytecodeLoaders happens to search the > SyspathJavaLoader before searching the referent class loaders. It's a > bug. No, I would'nt say it is a bug. The problem is that the guilty class is loadable both by MultiClassLoader and probably from classpath. In those cases it is better if the user dis-entangle that, because , yes we can with good-will, change the order, but the only safe solution is to avoid that at all. Without knowing the specific up to the details, I will not change the actual order. regards. |
From: <bc...@wo...> - 2001-11-08 19:10:19
|
[John Goerzen] >And as an additional data point: > >If I request an object of type java.lang.Object from get(), get() >works. What's more, newobj.getClass().getSuperclass().getName() >returns quovix.business.util.ListBO! However, casting newobj from >Object to ListBO fails with a java.lang.ClassCastException on >ListBOFoo$ListBOFoo$0! I'm rather mystified now. The return value from PythonInterpreter.get() is always a PyObject instance. You need to explicit convert the returned PyObject instance to an instance of your java class like this: Object tmp = interp.get("cl").__tojava__(ListBO.class); if (tmp != Py.NoConversion) { ListBO newobj = (ListBO) tmp; } If the "cl" variable can't be converted to a ListBO, the constant value of Py.NoConversion is returned. regards, finn |
From: John G. <jgo...@co...> - 2001-11-08 19:19:28
|
bc...@wo... (Finn Bock) writes: > The return value from PythonInterpreter.get() is always a PyObject > instance. You need to explicit convert the returned PyObject instance to > an instance of your java class like this: There are two PythonInterpeter.get() methods; one of which takes two parameters (the second the Java class to convert to) and returns a java.lang.Object. It is my understanding that this is equivolent to the code you showed. I was using this one, and got the mentioned error. > > Object tmp = interp.get("cl").__tojava__(ListBO.class); > if (tmp != Py.NoConversion) { > ListBO newobj = (ListBO) tmp; > } > > If the "cl" variable can't be converted to a ListBO, the constant value > of Py.NoConversion is returned. > > regards, > finn -- John Goerzen <jgo...@co...> GPG: 0x8A1D9A1F www.complete.org |