javapythonimportexecutable-jarjpype

Jpype import cannot find module in jar


I have received the task, at work, to find a way to use some methods from an existent jar file in a Python project. I have very limited experience in Python, but I have worked with that specific jar file before (it is part of a project we are working on). I am not allowed to modify much of both projects, and they are required to be as independent as possible.

I have researched multiple ways to include the jar methods in Python. So far, I have tried Jython (which I cannot use because the Python project uses PyQt among other libraries, which force the use of CPython, if my understanding is correct), Pyjnius and JPype. JPype seems the most promising, but I cannot get it working either. I have pasted the my code below, slightly censored because I don't know how much I am allowed to share.

from jpype import *
import jpype.imports

try:
    jpype.addClassPath("jars/sdk.jar") #the relative path to the jar file
    jpype.startJVM(convertStrings=False)
    java.lang.System.out.println(jpype.getClassPath()) #printing the classpath to check, the path is correctly pointing to the sdk.jar file

    java.lang.System.out.println("Hello world") #just to check if jpype is installed correctly, works

    jpype.imports.registerDomain("a")
    from a.b.c.d.e.f.g.h import SomeClass #fails here

except OSError as err:
    print(err)  # ToDo: Remove print when done
    pass

The error I am getting is that the module a.b.c.d.e.f.g.h.SomeClass could not be found. I have tried different ways to give the path (absolute path, relative path, place the jar in different places in the project and outside of it), but that doesn't seem to be the problem, as the path printed is the correct absolute path to the jar file.

Also, the jar is used in other (Java) projects and it works. It is created using maven package (using IntelliJ, if it is relevant, and the same Java version as the one used by the JPype JVM). In the Java projects, the import would be:

import a.b.c.d.e.f.g.h.SomeClass;

I have copied this and just transformed the syntax into Python.

I have also tried to create the class with JObject (which I probably didn't do right anyway) and also tried the older syntax (to my understanding) with JPackage. For the JPackage way, I am getting the exception that the package a.b.c.d.e.f.g.h.SomeClass.someMethod is not Callable, which to my understanding is an equivalent exception to the one I'm getting using jpype imports. I have already gone through all the questions I could find here with similar problems, but none of those solutions have helped me.

Can anyone suggest some possible solution? Or can anyone see what I'm doing wrong? Suggestions of other possibilities to replace JPype are also welcomed. If there is any clarification needed, I will edit the question.


Solution

  • The only thing that seems likely if the jar is on the classpath and failed to import would be for there to be some missing dependency. You have two other ways to try loading the class which may provide additional diagnostics.

    jpype.JClass("a.b.c.d.e.f.g.h.SomeClass")
    

    and

    jpype.JClass("java.lang.Class").forName("a.b.c.d.e.f.g.h.SomeClass")
    

    The first is manually loading a class by full class specification. It is mechanically what is happening under the import. The second is calling for Java to load the class (bypassing all of JPype). It returns a java.lang.Class which can be passed to JClass to make a wrapper.

    Common failures include missing a jar or native library, attempting to start JPype from within a module and having the wrong relative path, error in initialization of the class due to missing resource. JPype is just calling JNI calls, so if everything is fine on Java end it should work. Given that you checked the java.class.path System variable, it has to be something to do with class resources.

    The JPype user manual has an alternatives section if you would like to try to find another package. Most of the alternatives with the exception of PyJnius appear to be unmaintained.