I had originally tried Jeff's code but there were a lot of things missing that I wasn't sure how to replace. After digging down, I figured out how to get it running. After all is said and done: just needed the following code from Jeff (modified/simplified slightly for my case):

_bundlesClassLoader = new BundlesClassLoader(context.getBundles(),

PySystemState.initialize(System.getProperties(), null,
new String[]{""}, _bundlesClassLoader);

I don't need to search through the packages -- just needed to give PySystemState an appropriate bundle loader. 

What I don't understand is why it worked in the standalone Java application. Does Eclipse supply a classloader that is acting behind the scenes?

In any case, thanks for the code, Jeff!


On Mon, Nov 26, 2012 at 10:46 AM, Mason Wardle <masonwardle@gmail.com> wrote:
In looking at Jeff's snippets, if I'm not mistaken, they are searching all the available bundles for classes and I'm trying to understand if it applies to my issue at hand. I only have two plugins (I'm running with Equinox in Eclipse) -- one contains jython.jar and the other contains all my Jython code and the Java class that's trying to instantiate a Jython class, so I'm not certain this is related to bundle loading.

Let me give you some more background.

It works as a normal Java app so I think I have the code right, but it doesn't work in the OSGi context. I'm using the JythonObjectFactory described in chapter 10 of the Jython book on jython.org The name of my Jython module is FileValidatorJ and it contains a class FileValidatorJ which implements a Java interface called FileValidator.

Let me give you the key pieces of code. First, here is the object factory.

public class JythonObjectFactoryEfficient {

 private final PyObject klass;

 public JythonObjectFactoryEfficient(PySystemState state, 
Class<?> interfaceType, 
String moduleName, 
String className) 
     PyObject importer = state.getBuiltins().__getitem__(Py.newString("__import__"));

     PyObject module = importer.__call__(Py.newString(moduleName));
     klass = module.__getattr__(className);
     System.out.println("module =\n" + module + "\nclass =\n" + klass);

 public Object createObject() {
     return klass.__call__().__tojava__(interfaceType);

And here is a snippet of code I'm using to import my Jython class into Java:
JythonObjectFactoryEfficient validateFactory = new JythonObjectFactoryEfficient(
new PySystemState(),
FileValidator joe = (FileValidator) validateFactory.createObject();

Here is the output when I run the snippet as a Java app (the first four lines are from the factory constructor and the final line is from the snippet):
module =
<module 'FileValidatorJ' from '__pyclasspath__/FileValidatorJ.py'>
class =
<class 'FileValidatorJ.FileValidatorJ'>

When I run in an OSGi context, I get the following output:
module =
<module 'FileValidatorJ' from '/home/mbw/eclipse-3.8.1/workspace/org.myorg.files/src/FileValidatorJ$py.class'>
class =
<class 'FileValidatorJ.FileValidatorJ'>


org.python.core.PySingleton cannot be cast to org.myorg.files.interfaces.FileValidator
java.lang.ClassCastException: org.python.core.PySingleton cannot be cast to org.myorg.files.interfaces.FileValidator


It seems like it's more along the lines properly setting up my paths in my bundle. I have modified my Run Configuration to define CLASSPATH and JYTHONPATH. Once I do that, I get past most of my errors. (I would prefer to be able to set it up in a product configuration...but I think that may be a little off subject as of yet). 

Adding the CLASSPATH and JYTHONPATH to the Run Configuration allows me to import the Jython class with errors and in turn, import the Java interface inside of Jython without errors. I'm now getting tripped up because my PySystemState doesn't seem to be configured properly.

I could be barking up the wrong tree...but if any have seen these issues, I would love to know how to address them.

Best Regards and Thanks for your time,

On Wed, Nov 21, 2012 at 9:32 AM, Benoît Thiébault <thiebault@artenum.com> wrote:
Thanks Jeff, that's exactly what I was looking for!
... and it works!

Le 21/11/2012 17:00, Jeff Emanuel a écrit :
I've included code snippets below.  getBundles() returns the Bundles that
I want to allow access to from Jython.  I don't deal with Bundle
unloading or reloading. 

    Bundle[] bundles = getBundles(context);
    _bundlesClassLoader = new BundlesClassLoader(bundles,

    // Later for each required interpreter:

                               new String[]{""}, bundlesClassLoader);

      _interp = new PythonInterpreter();

      // Add packages from plugin to interpreter.  These are packages available
      // to the bundlesClassLoader.
      String[] packageNames = plugin.getPackageNames();  // _packageNames below.
      for (int i=0;i<packageNames.length;++i) {

  private String[] _packageNames;
  private void savePackageNames(Bundle[] bundles) {
    ArrayList<String> names = new ArrayList<String>();
    for (int i=0;i<bundles.length;++i) {
      Dictionary headers = bundles[i].getHeaders();
      String packages=(String)headers.get("Provide-Package");
    _packageNames = names.toArray(new String[names.size()]);

class BundlesClassLoader extends ClassLoader {

  private Bundle[] _bundles;
  public BundlesClassLoader(Bundle[] bundles, ClassLoader parent) {
  protected Class findClass(String className)
    throws ClassNotFoundException {
    try {
      return super.findClass(className);
    } catch (ClassNotFoundException e) {
      // Look for the class from the bundles.
      for (int i=0;i<_bundles.length;++i) {
        try {
          return _bundles[i].loadClass(className);
        } catch (ClassNotFoundException e2) {         
      // Didn't find the class anywhere, rethrow e.
      throw e;

Monitor your physical, virtual and cloud infrastructure from a single
web console. Get in-depth insight into apps, servers, databases, vmware,
SAP, cloud infrastructure, etc. Download 30-day Free Trial.
Pricing starts from $795 for 25 servers or applications!
Jython-users mailing list