1

The following explains my attempts at trying to make a hybrid PyDev/Eclipse plugin project. I have since discovered that even if I make a separate PyDev project, I cannot use my PyDev Jython-based Java classes by referencing the project in a plug-in project. On the other hand, I can use the PyDev Java classes in a separate project that is NOT a plugin project.

I've got an eclipse plugin that I've also set as a PyDev project. I built it based on Jython Book v1.0 documentation chapter 10 and chapter 11.

When I run Main as seen below, I see

1 BUIDING-A 100 MAIN ST

When I try to do the same thing within a plug-in project that is set as a PyDev project (right click on project->Pydev->Set as Pydev Project), I get an ImportError: no module named Building. It seems like the plugin nature of the project is trumping the PyDev nature of the project.

Any ideas?

I've put the Main function below followed by some support code.

package org.jython.book;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jython.book.interfaces.BuildingType;
import org.jython.book.util.JythonObjectFactory;

public class Main {

    public static void main(String[] args) {

    // Obtain an instance of the object factory
    JythonObjectFactory factory = JythonObjectFactory.getInstance();

    // Call the createObject() method on the object factory by
    // passing the Java interface and the name of the Jython module
    // in String format. The returning object is casted to the the same
    // type as the Java interface and stored into a variable.
    BuildingType building = (BuildingType) factory.createObject(
        BuildingType.class, "Building");
    // Populate the object with values using the setter methods
    building.setBuildingName("BUIDING-A");
    building.setBuildingAddress("100 MAIN ST.");
    building.setBuildingId(1);
    System.out.println(building.getBuildingId() + " " + building.getBuildingName() + " " +
        building.getBuildingAddress());

    }

}

Here is the JythonObjectFactory which should be exactly like what is in [Jython Book v1.0 documentation chapter 10][3], with typos corrected, of course :-)

package mypackage.files.util;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.python.core.PyObject;
import org.python.util.PythonInterpreter;

/**
 * Object factory implementation that is defined
 * in a generic fashion.
 *
 */

public class JythonObjectFactory {
    private static JythonObjectFactory instance = null;
    private static PyObject pyObject = null;

    protected JythonObjectFactory() {

    }
    /**
     * Create a singleton object. Only allow one instance to be created
     */
    public static JythonObjectFactory getInstance(){
        if(instance == null){
            instance = new JythonObjectFactory();
        }

        return instance;
    }

    /**
     * The createObject() method is responsible for the actual creation of the
     * Jython object into Java bytecode.
     */
    public static Object createObject(Object interfaceType, String moduleName){
        Object javaInt = null;
        // Create a PythonInterpreter object and import our Jython module
        // to obtain a reference.
        PythonInterpreter interpreter = new PythonInterpreter();
        interpreter.exec("from " + moduleName + " import " + moduleName);

        pyObject = interpreter.get(moduleName);

        try {
            // Create a new object reference of the Jython module and
            // store into PyObject.
            PyObject newObj = pyObject.__call__();
            // Call __tojava__ method on the new object along with the interface name
            // to create the java bytecode
            javaInt = newObj.__tojava__(Class.forName(interfaceType.toString().substring(
                        interfaceType.toString().indexOf(" ")+1,
                        interfaceType.toString().length())));
        } catch (ClassNotFoundException ex) {
            Logger.getLogger(JythonObjectFactory.class.getName()).log(Level.SEVERE, null, ex);
        }

        return javaInt;
    }

}
MrMas
  • 1,143
  • 2
  • 14
  • 28
  • I printed out sys.path from the non-plugin and plugin projects: the non-plugin version shows ['/home/myhome/jdk1.7.0_03/jython2.5.3/Lib', 'classpath', 'pyclasspath__/'] while the plugin version shows ['/home/myhome/eclipse/plugins/jython_2.2.1.v200907291313/Lib', '__classpath']. I'm bothered that they use different jython/Lib directories, but I think the bigger issue is __pyclasspath__/ is missing. That's likely why it's not working, but why isn't it there? – MrMas Oct 24 '12 at 19:59
  • Based on the path above, I'm wondering if the problem is because I have a pretty old version of PyDev (1.5 -- came pre-installed with my instance of eclipse). As you can see above, I'm using Jython 2.5.3 interpreter (jython2.5.3/jython.jar). After updating, I tried to configure my interpreter to use the Jython interpreter that came with the plugin (org.python.pydev.jython_2.7.1.2012100913/pydev-jython.jar) and I'm getting the same error mentioned in [link](http://stackoverflow.com/questions/10195111/eclipse-pydev-and-python-configuration-error). Is this .jar meant to be used as my interpreter? – MrMas Oct 24 '12 at 20:43
  • For reference, I'm running on Linux RHEL6.3, Eclipse 3.6, and I'm using version 2.6.6 of python and jdk1.7.0_03. – MrMas Oct 24 '12 at 20:44
  • The short answer is YES. The problem was the OSGi context. I had to add a class loader to PySystemState.initialize. See http://stackoverflow.com/questions/13499216/how-can-i-get-an-eclipse-product-configuration-to-do-the-same-class-loading-as-a for more information. – MrMas Nov 26 '12 at 20:54

1 Answers1

1

If you have multiple natures added to the project, all builders related to those projects will be invoked by Eclipse. So if the build fails with some PyDev related error message, this really indicates a problem with the PyDev part, not with PDE. Maybe you are missing some additional files or project settings for that project?

Generally speaking, you should avoid mixing multiple natures in one project. This often leads to trouble, because most builders and other extensions expect that they are "the one and only" tinkering with a project. And almost all use cases involving multiple natures can more easily be solved by having two different projects, where one project references the other project (and can then access resources of that referenced project). See Project properties -> Referenced Projects for that.

Bananeweizen
  • 21,797
  • 8
  • 68
  • 88
  • Thanks for the response. I tried your suggestion. As I stated previously, I already had working code in a non-plugin PyDev project. I created a TestJython class in my plugin project, now referencing my non-plugin PyDev project. I actually found the result entertaining: it behaved the same as when I tried to create a PyDev project from a plugin project: "ImportError: no module named" and sys.path is ['/home/myhome/eclipse/plugins/jython_2.2.1.v200907291313/Lib', '__classpath']. Something in the plugin seems to be blocking something PyDev is trying to do. – MrMas Oct 25 '12 at 15:38
  • So that was the result of trying to run a Java class in a plugin project. I tried the same on a non-plugin project -- that is, I referenced my non-plugin PyDev project from a non-PyDev project. That worked. Just for kicks, I tried referencing a PyDev plugin project in my non-plugin, non-PyDev project. Not surprisingly, that didn't work. But what is surprising is that it didn't work and yet my classpath looked correct, i.e., ['classpath', 'pyclasspath__/', '/home/myhome/jdk1.7.0_03/jython2.5.3/Lib'] – MrMas Oct 25 '12 at 15:56
  • I sorted out my problems (which were many). Once they were taken care of, it was easy to push the Jython/PyDev stuff into a separate project. But I still made it a plugin which I think is still necessary since I need to set up the Jython paths in the OSGi context. – MrMas Nov 27 '12 at 19:29
  • Actually, I need it to be a plugin project, but I don't need it to by a PyDev project any longer. I'm just using jython.jar libraries. – MrMas Nov 27 '12 at 20:24