Getting a class defined in Jython using Java Class.forName()

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

Getting a class defined in Jython using Java Class.forName()

Richard Eckart de Castilho
Hi all,

I want to define a class in Jython and instantiate it in Java.

I am using a Java framework which allows users to create custom
components (classes implementing specific interfaces). The framework
is built in such a way that it instantiates these components itself
based on a description containing a class name and a set of parameters.

My goal is to define a new component within Jython and to use it with
the framework. Here some pseudocode:

class MyComponent(Component):
 def run(self, *args):
   // do something

run(createComponent(MyComponent))

(btw. in Java I would have written: run(createComponent(MyComponent.class))

That gives me an error along the lines of

InitializationException: Component class "org.python.proxies.__main__$MyComponent$1" was not found.

Reading a bit in [1], I now believe that what I want to do is not really
possible without modifying the framework that I am using because classes
defined in Jython do not actually have a java.lang.Class instance
associated with them and there is actually no classloader which would be able
to return such an instance when Class.forName("org.python.proxies.__main__$MyComponent$1")
is called.

Is this correct, or is there a way to do what I want to do?

Cheers,

-- Richard

[1] http://www.jython.org/jythonbook/en/1.0/JythonAndJavaIntegration.html
------------------------------------------------------------------------------
Put Bad Developers to Shame
Dominate Development with Jenkins Continuous Integration
Continuously Automate Build, Test & Deployment
Start a new project now. Try Jenkins in the cloud.
http://p.sf.net/sfu/13600_Cloudbees
_______________________________________________
Jython-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jython-users
Reply | Threaded
Open this post in threaded view
|

Re: Getting a class defined in Jython using Java Class.forName()

Alan Kennedy-2
Hi Richard,

Without seeing your java code, it's hard to state what exactly might be wrong.

But there is a simple conversion process that you need to go through to obtain a java object equivalent of a class implemented in jython.

The best way to illustrate this is with code that does it. Modjy is one example in the code base, that uses a servlet implemented in jython to provide WSGI capability to servlet containers.

The key piece of code is here.

http://hg.python.org/jython/file/45b3007473f9/src/com/xhaus/modjy/ModjyJServlet.java#l116

You should try that approach.

Alan.



On Tue, Apr 8, 2014 at 9:58 AM, Richard Eckart de Castilho <[hidden email]> wrote:
Hi all,

I want to define a class in Jython and instantiate it in Java.

I am using a Java framework which allows users to create custom
components (classes implementing specific interfaces). The framework
is built in such a way that it instantiates these components itself
based on a description containing a class name and a set of parameters.

My goal is to define a new component within Jython and to use it with
the framework. Here some pseudocode:

class MyComponent(Component):
 def run(self, *args):
   // do something

run(createComponent(MyComponent))

(btw. in Java I would have written: run(createComponent(MyComponent.class))

That gives me an error along the lines of

InitializationException: Component class "org.python.proxies.__main__$MyComponent$1" was not found.

Reading a bit in [1], I now believe that what I want to do is not really
possible without modifying the framework that I am using because classes
defined in Jython do not actually have a java.lang.Class instance
associated with them and there is actually no classloader which would be able
to return such an instance when Class.forName("org.python.proxies.__main__$MyComponent$1")
is called.

Is this correct, or is there a way to do what I want to do?

Cheers,

-- Richard

[1] http://www.jython.org/jythonbook/en/1.0/JythonAndJavaIntegration.html
------------------------------------------------------------------------------
Put Bad Developers to Shame
Dominate Development with Jenkins Continuous Integration
Continuously Automate Build, Test & Deployment
Start a new project now. Try Jenkins in the cloud.
http://p.sf.net/sfu/13600_Cloudbees
_______________________________________________
Jython-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jython-users


------------------------------------------------------------------------------
Put Bad Developers to Shame
Dominate Development with Jenkins Continuous Integration
Continuously Automate Build, Test & Deployment
Start a new project now. Try Jenkins in the cloud.
http://p.sf.net/sfu/13600_Cloudbees
_______________________________________________
Jython-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jython-users
Reply | Threaded
Open this post in threaded view
|

Re: Getting a class defined in Jython using Java Class.forName()

Jim Baker
This is the exact use case for Clamp. If interested, I have a write up that introduces this project; https://github.com/jimbaker/clamped, along with a talk, https://github.com/jimbaker/clamped/blob/master/talk.pdf

Among other things, Clamp ensures that your Python class, as wrapped by a Java proxy, can be resolved by Class.forName or be directly imported from Java. Clamp is also integrated with setuptools and is site-packages aware.

Here's an example of Clamp in action. Let's assume the BarClamp class is defined in the Python module clamped; then BarBase is setting it up so that the classname for Java will be ".".join(["bar", "clamped", "BarClamp"]) or bar.clamped.BarClamp. That prefix is arbitrary; it could be com.example.baz:

from java.io import Serializable
from java.util.concurrent import Callable
from clamp import clamp_base

BarBase = clamp_base("bar")  # metaclass to map to Java packages

class BarClamp(BarBase, Callable, Serializable):
    def call(self):
        return 42
To then use that clamped class, you can simply import it:


import bar.clamped.BarClamp;  // yes, you can now just import Python classes!

public class UseClamped {
    public static void main(String[] args) {
        BarClamp barclamp = new BarClamp();
        try {
            System.out.println("BarClamp: " + barclamp.call());
        } catch (Exception ex) {
            System.err.println("Exception: " + ex);
        }
    }
}

Clamp is under active development, but it's definitely stable enough for testing.

- Jim 


On Wed, Apr 9, 2014 at 11:03 AM, Alan Kennedy <[hidden email]> wrote:
Hi Richard,

Without seeing your java code, it's hard to state what exactly might be wrong.

But there is a simple conversion process that you need to go through to obtain a java object equivalent of a class implemented in jython.

The best way to illustrate this is with code that does it. Modjy is one example in the code base, that uses a servlet implemented in jython to provide WSGI capability to servlet containers.

The key piece of code is here.

http://hg.python.org/jython/file/45b3007473f9/src/com/xhaus/modjy/ModjyJServlet.java#l116

You should try that approach.

Alan.



On Tue, Apr 8, 2014 at 9:58 AM, Richard Eckart de Castilho <[hidden email]> wrote:
Hi all,

I want to define a class in Jython and instantiate it in Java.

I am using a Java framework which allows users to create custom
components (classes implementing specific interfaces). The framework
is built in such a way that it instantiates these components itself
based on a description containing a class name and a set of parameters.

My goal is to define a new component within Jython and to use it with
the framework. Here some pseudocode:

class MyComponent(Component):
 def run(self, *args):
   // do something

run(createComponent(MyComponent))

(btw. in Java I would have written: run(createComponent(MyComponent.class))

That gives me an error along the lines of

InitializationException: Component class "org.python.proxies.__main__$MyComponent$1" was not found.

Reading a bit in [1], I now believe that what I want to do is not really
possible without modifying the framework that I am using because classes
defined in Jython do not actually have a java.lang.Class instance
associated with them and there is actually no classloader which would be able
to return such an instance when Class.forName("org.python.proxies.__main__$MyComponent$1")
is called.

Is this correct, or is there a way to do what I want to do?

Cheers,

-- Richard

[1] http://www.jython.org/jythonbook/en/1.0/JythonAndJavaIntegration.html
------------------------------------------------------------------------------
Put Bad Developers to Shame
Dominate Development with Jenkins Continuous Integration
Continuously Automate Build, Test & Deployment
Start a new project now. Try Jenkins in the cloud.
http://p.sf.net/sfu/13600_Cloudbees
_______________________________________________
Jython-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jython-users


------------------------------------------------------------------------------
Put Bad Developers to Shame
Dominate Development with Jenkins Continuous Integration
Continuously Automate Build, Test & Deployment
Start a new project now. Try Jenkins in the cloud.
http://p.sf.net/sfu/13600_Cloudbees
_______________________________________________
Jython-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jython-users



------------------------------------------------------------------------------
Put Bad Developers to Shame
Dominate Development with Jenkins Continuous Integration
Continuously Automate Build, Test & Deployment
Start a new project now. Try Jenkins in the cloud.
http://p.sf.net/sfu/13600_Cloudbees
_______________________________________________
Jython-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jython-users
Reply | Threaded
Open this post in threaded view
|

Re: Getting a class defined in Jython using Java Class.forName()

Jim Baker
One more thing: it's a known problem that Clamp does not currently build jars correctly on Windows. Another issue seen on Windows is sys.executable does not get set. See the Clamp issues in https://github.com/jythontools/clamp/

To address both the Clamp issues and in Jython proper, as of yesterday I now have a MSDN license so that we can test in this environment. (This license is courtesy of a program Microsoft has for Python committers.) Hopefully this will help get us to better Windows support for Jython.

- Jim




On Wed, Apr 9, 2014 at 11:31 AM, Jim Baker <[hidden email]> wrote:
This is the exact use case for Clamp. If interested, I have a write up that introduces this project; https://github.com/jimbaker/clamped, along with a talk, https://github.com/jimbaker/clamped/blob/master/talk.pdf

Among other things, Clamp ensures that your Python class, as wrapped by a Java proxy, can be resolved by Class.forName or be directly imported from Java. Clamp is also integrated with setuptools and is site-packages aware.

Here's an example of Clamp in action. Let's assume the BarClamp class is defined in the Python module clamped; then BarBase is setting it up so that the classname for Java will be ".".join(["bar", "clamped", "BarClamp"]) or bar.clamped.BarClamp. That prefix is arbitrary; it could be com.example.baz:

from java.io import Serializable
from java.util.concurrent import Callable
from clamp import clamp_base

BarBase = clamp_base("bar")  # metaclass to map to Java packages

class BarClamp(BarBase, Callable, Serializable):
    def call(self):
        return 42
To then use that clamped class, you can simply import it:


import bar.clamped.BarClamp;  // yes, you can now just import Python classes!

public class UseClamped {
    public static void main(String[] args) {
        BarClamp barclamp = new BarClamp();
        try {
            System.out.println("BarClamp: " + barclamp.call());
        } catch (Exception ex) {
            System.err.println("Exception: " + ex);
        }
    }
}

Clamp is under active development, but it's definitely stable enough for testing.

- Jim 


On Wed, Apr 9, 2014 at 11:03 AM, Alan Kennedy <[hidden email]> wrote:
Hi Richard,

Without seeing your java code, it's hard to state what exactly might be wrong.

But there is a simple conversion process that you need to go through to obtain a java object equivalent of a class implemented in jython.

The best way to illustrate this is with code that does it. Modjy is one example in the code base, that uses a servlet implemented in jython to provide WSGI capability to servlet containers.

The key piece of code is here.

http://hg.python.org/jython/file/45b3007473f9/src/com/xhaus/modjy/ModjyJServlet.java#l116

You should try that approach.

Alan.



On Tue, Apr 8, 2014 at 9:58 AM, Richard Eckart de Castilho <[hidden email]> wrote:
Hi all,

I want to define a class in Jython and instantiate it in Java.

I am using a Java framework which allows users to create custom
components (classes implementing specific interfaces). The framework
is built in such a way that it instantiates these components itself
based on a description containing a class name and a set of parameters.

My goal is to define a new component within Jython and to use it with
the framework. Here some pseudocode:

class MyComponent(Component):
 def run(self, *args):
   // do something

run(createComponent(MyComponent))

(btw. in Java I would have written: run(createComponent(MyComponent.class))

That gives me an error along the lines of

InitializationException: Component class "org.python.proxies.__main__$MyComponent$1" was not found.

Reading a bit in [1], I now believe that what I want to do is not really
possible without modifying the framework that I am using because classes
defined in Jython do not actually have a java.lang.Class instance
associated with them and there is actually no classloader which would be able
to return such an instance when Class.forName("org.python.proxies.__main__$MyComponent$1")
is called.

Is this correct, or is there a way to do what I want to do?

Cheers,

-- Richard

[1] http://www.jython.org/jythonbook/en/1.0/JythonAndJavaIntegration.html
------------------------------------------------------------------------------
Put Bad Developers to Shame
Dominate Development with Jenkins Continuous Integration
Continuously Automate Build, Test & Deployment
Start a new project now. Try Jenkins in the cloud.
http://p.sf.net/sfu/13600_Cloudbees
_______________________________________________
Jython-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jython-users


------------------------------------------------------------------------------
Put Bad Developers to Shame
Dominate Development with Jenkins Continuous Integration
Continuously Automate Build, Test & Deployment
Start a new project now. Try Jenkins in the cloud.
http://p.sf.net/sfu/13600_Cloudbees
_______________________________________________
Jython-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jython-users




------------------------------------------------------------------------------
Put Bad Developers to Shame
Dominate Development with Jenkins Continuous Integration
Continuously Automate Build, Test & Deployment
Start a new project now. Try Jenkins in the cloud.
http://p.sf.net/sfu/13600_Cloudbees
_______________________________________________
Jython-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jython-users
Reply | Threaded
Open this post in threaded view
|

Re: Getting a class defined in Jython using Java Class.forName()

Richard Eckart de Castilho
Jim, Alan,

thanks for the hints.

> This is the exact use case for Clamp. If interested, I have a write up that introduces this project; https://github.com/jimbaker/clamped, along with a talk, https://github.com/jimbaker/clamped/blob/master/talk.pdf
>
> Among other things, Clamp ensures that your Python class, as wrapped by a Java proxy, can be resolved by Class.forName or be directly imported from Java. Clamp is also integrated with setuptools and is site-packages aware.


Jim, if I understand clamp correctly, it requires that the Jython code is compiled into class files at build time. I am looking for a solution that works at runtime without the need for special build tooling. I want people to be able to implement a simple Jython script and execute it. The script internally calls Java code which tries to instantiate a class defined in the script using Java reflection. Can clamp do that?

> The best way to illustrate this is with code that does it. Modjy is one example in the code base, that uses a servlet implemented in jython to provide WSGI capability to servlet containers.
>
> The key piece of code is here.
>
> http://hg.python.org/jython/file/45b3007473f9/src/com/xhaus/modjy/ModjyJServlet.java#l116

Alan, it sounds like the __tojava__ call might do what I want. I wonder, shouldn't the classloader that is used by the Jython scripts (the one which also can add additional JARs to the syspath) be able to transparently call that when a class object for a class defined in Jython is requested? Is it just that nobody implemented this so far, or is it because it is in fact not as straight forward as it seems in the sample code you offered?

Cheers,

-- Richard


------------------------------------------------------------------------------
Start Your Social Network Today - Download eXo Platform
Build your Enterprise Intranet with eXo Platform Software
Java Based Open Source Intranet - Social, Extensible, Cloud Ready
Get Started Now And Turn Your Intranet Into A Collaboration Platform
http://p.sf.net/sfu/ExoPlatform
_______________________________________________
Jython-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jython-users
Reply | Threaded
Open this post in threaded view
|

Re: Getting a class defined in Jython using Java Class.forName()

Richard Eckart de Castilho
On 24.04.2014, at 22:31, Richard Eckart de Castilho <[hidden email]> wrote:

>> The best way to illustrate this is with code that does it. Modjy is one example in the code base, that uses a servlet implemented in jython to provide WSGI capability to servlet containers.
>>
>> The key piece of code is here.
>>
>> http://hg.python.org/jython/file/45b3007473f9/src/com/xhaus/modjy/ModjyJServlet.java#l116
>
> Alan, it sounds like the __tojava__ call might do what I want. I wonder, shouldn't the classloader that is used by the Jython scripts (the one which also can add additional JARs to the syspath) be able to transparently call that when a class object for a class defined in Jython is requested? Is it just that nobody implemented this so far, or is it because it is in fact not as straight forward as it seems in the sample code you offered?

Looking at the code again, I believe it does not want I need. I do not want to access an object instantiated in Jython from Java. I want to access a class defined in Jython from Java as a java.lang.Class object which I can then use to instantiate said class from Java.

-- Richard
------------------------------------------------------------------------------
Start Your Social Network Today - Download eXo Platform
Build your Enterprise Intranet with eXo Platform Software
Java Based Open Source Intranet - Social, Extensible, Cloud Ready
Get Started Now And Turn Your Intranet Into A Collaboration Platform
http://p.sf.net/sfu/ExoPlatform
_______________________________________________
Jython-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jython-users
Reply | Threaded
Open this post in threaded view
|

Re: Getting a class defined in Jython using Java Class.forName()

Jim Baker
In reply to this post by Richard Eckart de Castilho
Richard,

Clamp does assume an ahead-of-time model in terms of its setuptools integration. However, you should just be able to use Clamp as is for your case, with a little ClassLoader work.

This is because of the two steps used by Clamp:

1. CustomMaker.makeClass, as seen in clamp.proxymaker - this ensures that class is built just once for a given name resolvable by Py.findClass. However this is not the same class loading resolution as Class.forName, so this is where you will have to do some extra work, as explained below.

2. CustomMaker.saveBytes uses the builder returned by clamp.build.get_builder, which by default - unless in a setuptools build step - is going to be a NullBuilder, which simply doesn't write out the proxy bytecode. This saveBytes step is ordinarily to ensure that you have class bytes for a jar you will distribute for say every node in your Storm cluster - not applicable in your case.

With that in mind, here's the small amount of extra work you should have to do. For your Java code to get Class.forName resolvability of clamped Python classes not built ahead-of-time, you will need to use Thread.setContextClassLoader (or something comparable, class loading has a number of entry points) and set it to the same ClassLoader that Py.findClassInternal would choose. If you look at that code in org.python.core.Py, it's quite straightforward, so I'm not certain why don't expose it directly.

Hope that helps!

- Jim


On Thu, Apr 24, 2014 at 2:31 PM, Richard Eckart de Castilho <[hidden email]> wrote:
Jim, Alan,

thanks for the hints.

> This is the exact use case for Clamp. If interested, I have a write up that introduces this project; https://github.com/jimbaker/clamped, along with a talk, https://github.com/jimbaker/clamped/blob/master/talk.pdf
>
> Among other things, Clamp ensures that your Python class, as wrapped by a Java proxy, can be resolved by Class.forName or be directly imported from Java. Clamp is also integrated with setuptools and is site-packages aware.


Jim, if I understand clamp correctly, it requires that the Jython code is compiled into class files at build time. I am looking for a solution that works at runtime without the need for special build tooling. I want people to be able to implement a simple Jython script and execute it. The script internally calls Java code which tries to instantiate a class defined in the script using Java reflection. Can clamp do that?

> The best way to illustrate this is with code that does it. Modjy is one example in the code base, that uses a servlet implemented in jython to provide WSGI capability to servlet containers.
>
> The key piece of code is here.
>
> http://hg.python.org/jython/file/45b3007473f9/src/com/xhaus/modjy/ModjyJServlet.java#l116

Alan, it sounds like the __tojava__ call might do what I want. I wonder, shouldn't the classloader that is used by the Jython scripts (the one which also can add additional JARs to the syspath) be able to transparently call that when a class object for a class defined in Jython is requested? Is it just that nobody implemented this so far, or is it because it is in fact not as straight forward as it seems in the sample code you offered?

Cheers,

-- Richard




------------------------------------------------------------------------------
Start Your Social Network Today - Download eXo Platform
Build your Enterprise Intranet with eXo Platform Software
Java Based Open Source Intranet - Social, Extensible, Cloud Ready
Get Started Now And Turn Your Intranet Into A Collaboration Platform
http://p.sf.net/sfu/ExoPlatform
_______________________________________________
Jython-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jython-users