How to Use JPype

Date March 31, 2008 by Isaac

Background

I love Python and my personal experience has shown that testers are about 4x more productive when using Python than when using Java. However, at work I am a tester on a Java application. I've been looking for a way to bridge that gap and allow me to write my tests in Python but test a Java application.

I've looked into Jython and while it had many advantages it has one major drawback that I can't live with: Jython only implements Python 2.2. Most of the time this is fine, but there are times where I use Python 2.4 or 2.5 features and don't want to create a workaround just so I can use an older Python standard. If I had the money I would pay someone to bring Jython up to date. But, that's not a possibility.

I did find another alternative that so far seems to work great. It is still in development, but JPype seems to be working fairly well. JPype differs in philosophy from Jython in a fundamental way: Jython is a complete reimplementation of Python in Java, whereas JPype is a bridge between CPython and native Java.

Kicking The Tires

This article is a "how to," so let's get down to business. I'm going to create a Java class that I would like to access from Python. Here is Java class:

 
package org.wg3i.test;
 
class Test {
    private String msg;
 
    public Test() {
    }
 
    public void speak(String msg) {
	System.out.println(msg);
    }
 
    public void setString(String s) {
	msg = s;
    }
 
    public String getString() {
	return msg;
    }
}

The class is simple enough, but it will illustrate the basic JPype usage. For my testing I compiled this and placed it into a jar file. Feel free to leave it as a class file if you wish. I'll show you how to deal with both situations below.

For reference, here is my ant build file:

<?xml version="1.0"?>
<project name="TestProject"
 basedir="."
 default="jar">

  <property name="src.dir" value="src"/>
  <property name="build.dir" value="build"/>
  <property name="classes.dir" value="${build.dir}/classes"/>
  <property name="jar.dir" value="${build.dir}/jar"/>
 
  <target name="clean">
    <delete dir="build"/>
  </target>
 
  <target name="compile">
    <mkdir dir="${classes.dir}"/>
    <javac srcdir="${src.dir}" destdir="${classes.dir}"/>
  </target>
 
  <target name="jar" depends="compile">
    <mkdir dir="${jar.dir}"/>
    <jar destfile="${jar.dir}/${ant.project.name}.jar"
 basedir="${classes.dir}"/>
  </target>
 
  <target name="clean-build" depends="clean,jar">
  </target>
</project>

After creating a jar file you are ready to go. Here is the Python code to utilize a jar file and create an instance of the Java class.

 
# Simple little JPype test.  Note: This test assumes
# that the jar file is in the build/jar directory
# relative to the current directory
import jpype
import os.path
 
jarpath = os.path.join(os.path.abspath('.'), 'build/jar')
jpype.startJVM(jpype.getDefaultJVMPath(), "-Djava.ext.dirs=%s" % jarpath)
Test = jpype.JClass('org.wg3i.test.Test')  # get the class
t = Test()  # create an instance of the class
t.speak("This is a test message")  # try to call one of the class methods
t.setString("Hello, World")  # set a string
s = t.getString()  # get the string back
print s
jpype.shutdownJVM()

In a nutshell that's it. I promised to show you how to initialize JPype when you have class files and not jar files. Here's a Python example that shows that This example also shows the use of the JPackage method, which gets a package, not a class.

 
import jpype
import os.path
 
classpath = os.path.join(os.path.abspath('.'), 'build/classes')
jpype.startJVM(jpype.getDefaultJVMPath(), "-Djava.class.path=%s" % classpath)
testPkg = jpype.JPackage('org').wg3i.test  # get the package
Test = testPkg.Test # get the class
t = Test()  # create an instance of the class
t.speak("This is a test message")  # try to call one of the class methods
t.setString("Hello, World")  # set a string
s = t.getString()  # get the string back
print s
jpype.shutdownJVM()

Conclusion

There are many things I have not covered, such as passing arrays back and forth, types other than strings, exceptions, etc. However, this should be enough to get you started using JPype. I'd be interested in hearing your own experiences or suggestions.

12 Responses to “How to Use JPype”

  1. AvatarKen
    1

    Thanks, this was a helpful introduction. The jpype.getDefaultJVMPath() call didn’t work properly on my Ubuntu Linux system, so I just hard-coded the path, which in my case is /usr/lib/jvm/java-1.5.0-sun/jre/lib/i386/client/libjvm.so

    Reply to this comment.
  2. AvatarIsaac
    2
    Author Comment

    Thanks, this was a helpful introduction. The jpype.getDefaultJVMPath() call didn’t work properly on my Ubuntu Linux system, so I just hard-coded the path, which in my case is /usr/lib/jvm/java-1.5.0-sun/jre/lib/i386/client/libjvm.so

    More than likely your JAVA_HOME was not set. If you set this environment variable then JPype should be able to determine your runtime library correctly.

    Reply to this comment.
  3. AvatarSuprabhath
    3

    Thank you for this introduction. But, I got a Type Error in python. And I could not fix it.

    TypeError: Package org.wg3i.test.Test is not Callable

    Can you give any advice on how to fix this error.

    Reply to this comment.
  4. AvatarIsaac
    4
    Author Comment

    Thank you for this introduction. But, I got a Type Error in python. And I could not fix it.

    TypeError: Package org.wg3i.test.Test is not Callable

    Can you give any advice on how to fix this error.

    Can you post your python code? Are you trying to use the class before creating an instance of it?

    Reply to this comment.
  5. AvatarJohn Malich
    5
    Thank you for this introduction. But, I got a Type Error in python. And I could not fix it.
    TypeError: Package org.wg3i.test.Test is not Callable
    Can you give any advice on how to fix this error.

    Can you post your python code? Are you trying to use the class before creating an instance of it?

    I believe Suprabhath is just running the class file example. I am getting the same result.

    Reply to this comment.
  6. AvatarNaveen
    6

    introduction is really helpful. I have a query , i want to user jpype.rmi functions to access a java applicaiton and get bac information from that java application. How can i do that using jpype. What are the inbuilt funcitons available with jpype.rmi . Any documentation or any sample code describing use of rmi. Anyhelp regardin this will be appericiated. Thanks a lot

    Regards
    Naveen

    Reply to this comment.
  7. AvatarIsaac
    7
    Author Comment
    Thank you for this introduction. But, I got a Type Error in python. And I could not fix it.
    TypeError: Package org.wg3i.test.Test is not Callable
    Can you give any advice on how to fix this error.

    Can you post your python code? Are you trying to use the class before creating an instance of it?

    I believe Suprabhath is just running the class file example. I am getting the same result.

    Hmmm….I’m not sure what to tell you. I just copied and pasted the code from above and it runs just fine on my system. If it makes a difference I am using Sun Java 1.6 and Python 2.6.

    Reply to this comment.
  8. AvatarIsaac
    8
    Author Comment

    introduction is really helpful. I have a query , i want to user jpype.rmi functions to access a java applicaiton and get bac information from that java application. How can i do that using jpype. What are the inbuilt funcitons available with jpype.rmi . Any documentation or any sample code describing use of rmi. Anyhelp regardin this will be appericiated. Thanks a lot

    Regards
    Naveen

    Unfortunately, I have never done any Java RMI programming so I can’t give you any pointers.

    Reply to this comment.
  9. AvatarRajkumar
    9

    ###TypeError: Package org.wg3i.test.Test is not Callable

    ###Can you give any advice on how to fix this error.

    Please Have Handle or Interface to the Class and create object like following

    like this :

    self.package = jpype.JPackage(“com.lowagie.text”)

    ObjDocDocument=self.package.Document ## Here taking an interface to the class
    print “type:”,type(ObjDocDocument)
    ObjDocDocument1=ObjDocDocument() ## After that creating Object
    print “type:”,type(ObjDocDocument1)

    it works with iText.

    Tip: Use “public static methods or properties” in the Java Code….

    Reply to this comment.
  10. AvatarRajkumar
    10

    Sample program:
    Dont Copy the Entire program. Please use this as sample to your step by step guide.

    import jpype

    class DocExport:
    def __init__(self):
    import os
    print “current path:”,os.getcwd()

    if __Cat__.jpype==0:
    jpype.startJVM(jpype.getDefaultJVMPath(), “-ea”, “-Djava.class.path=jars/iText-2.1.6.jar;jars/jxl.jar;jars/iText-rtf.jar”)
    __Cat__.jpype=1
    else:
    pass
    ## jpype.startJVM(jpype.getDefaultJVMPath(), “-ea”, “-Djava.class.path=jars/iText-2.1.6.jar;jars/iText-rtf.jar”)

    ###Init All Packages Here

    #self.Document=jpype.JPackage(“com.lowagie.text”)
    self.package = jpype.JPackage(“com.lowagie.text”)#com.xsolutions.cat
    self.DocPack=jpype.JPackage(“com.lowagie.text.rtf”)
    self.AWT=jpype.JPackage(“java.awt”)
    self.ObjIO=jpype.JPackage(“java.io”)#com.xsolutions.cat
    self.iUtil=jpype.JPackage(“java.util”)

    print “API:”,dir(self.package)

    #self.iFontFactory=self.package.FontFactory

    #print “JPype API:”,dir(jpype)

    def Test(self):

    ### Init Document

    ObjDocDocument=self.package.Document
    print “type:”,type(ObjDocDocument)
    ObjDocDocument1=ObjDocDocument()
    print “type:”,type(ObjDocDocument1)

    ObjIONewFile=self.ObjIO.FileOutputStream(“new.Doc”)
    print “type:”,type(ObjIONewFile)

    ### Init Doc Writer
    iDocWriter=self.package.rtf.RtfWriter2
    ObjDocDocWriter1=iDocWriter.getInstance(ObjDocDocument1,ObjIONewFile)
    print “API:”,dir(ObjDocDocWriter1),type(ObjDocDocWriter1)

    ### Insert Footer
    iFont=self.package.Font
    ObjFont=iFont()
    print “ObjFont API:”,dir(ObjFont)
    iFontFactory=self.package.FontFactory
    print “iFontFactory API:”,dir(iFontFactory),type(iFontFactory)
    ResFont=iFontFactory.getFont(iFontFactory.HELVETICA,jpype.JFloat(8),ObjFont.NORMAL)
    iChunk=self.package.Chunk
    ObjChunk=iChunk(“XOU Solutions Ltd”,ResFont)
    iPhrase=self.package.Phrase
    ObjPhrase=iPhrase(ObjChunk)
    iHeaderFooter=self.package.HeaderFooter
    ObjHeaderFooter=iHeaderFooter(ObjPhrase,False)
    ObjDocDocument1.setFooter(ObjHeaderFooter)

    iRectangle=self.package.Rectangle
    ObjHeaderFooter.setAlignment(iRectangle.ALIGN_CENTER)
    ObjHeaderFooter.setBorder(iRectangle.NO_BORDER)

    ### Open Document
    try :
    ObjDocDocument1.open()
    except Exception, ex :
    print “Caught the runtime exception : “,ex

    ### Insert Image
    iImage=self.package.Image
    ObjImage=iImage.getInstance(“Images/xou.png”)
    ObjImage.setAlignment(iImage.LEFT)
    ObjDocDocument1.add(ObjImage)

    #### Insert Simple Text

    ObjDocParagraph=self.package.Paragraph(“\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nHello World”)
    ObjDocDocument1.add(ObjDocParagraph)

    iPhrase=self.package.Phrase
    ObjPhrase=iPhrase()

    iChunk= self.package.Chunk
    ObjChunk1=iChunk(“\nThis is Bold Value “,iFontFactory.getFont(iFontFactory.HELVETICA,jpype.JFloat(12),ObjFont.BOLD))
    ObjChunk2=iChunk(“This is Bold Value “,iFontFactory.getFont(iFontFactory.HELVETICA,jpype.JFloat(14),ObjFont.BOLD))
    ObjPhrase.add(ObjChunk1)
    ObjPhrase.add(ObjChunk2)

    ObjDocDocument1.add(ObjPhrase)
    ## phrase = new Phrase();
    ## phrase.add(new Chunk(((String)headerList.get(headerCount)).trim()+” “,FontFactory.getFont(FontFactory.HELVETICA, 10, Font.BOLD)));
    ## phrase.add(new Chunk(systemuptime,FontFactory.getFont(FontFactory.HELVETICA, 10, Font.NORMAL)));
    ## document.add(new Paragraph(phrase));

    iTable=self.package.Table

    ObjDocPTable=iTable(1,1)
    print “Dir:”,dir(ObjDocPTable)

    iRectangle=self.package.Rectangle
    ObjDocPTable.setAlignment(iRectangle.ALIGN_LEFT)
    #ObjDocPTable.setPadding(jpype.JFloat(8));

    #ObjDocPTable.setWidth(jpype.JFloat(100));

    ## ObjDocPTable.setSpacingBefore(jpype.JFloat(15))
    ## ObjDocPTable.setWidthPercentage(jpype.JFloat(100))
    iPhrase=self.package.Phrase
    ObjPhrase=iPhrase()
    iChunk= self.package.Chunk
    ObjChunk3=iChunk(“Heading”,iFontFactory.getFont(iFontFactory.HELVETICA,jpype.JFloat(12),ObjFont.BOLD))
    ObjPhrase.add(ObjChunk3)
    iDocPCell=self.package.Cell
    ObjDocPCell=iDocPCell(ObjPhrase)
    ObjDocPTable.addCell(ObjDocPCell)
    ObjDocDocument1.add(ObjDocPTable);

    iPhrase=self.package.Phrase
    ObjPhrase=iPhrase()

    iChunk= self.package.Chunk
    ObjChunk1=iChunk(“\b”,iFontFactory.getFont(iFontFactory.HELVETICA,jpype.JFloat(12),ObjFont.BOLD))
    ObjPhrase.add(ObjChunk1)

    ObjDocDocument1.add(ObjPhrase)

    ObjDocPTable=iTable(2,2)
    print “Dir:”,dir(ObjDocPTable)

    iRectangle=self.package.Rectangle
    ObjDocPTable.setAlignment(iRectangle.ALIGN_LEFT)
    ## ObjDocPTable.setSpacingBefore(jpype.JFloat(15))
    ## ObjDocPTable.setWidthPercentage(jpype.JFloat(100))

    iPhrase=self.package.Phrase
    ObjPhrase=iPhrase()
    iChunk= self.package.Chunk
    ObjChunk3=iChunk(“Datax \n DataY\n Data1″,iFontFactory.getFont(iFontFactory.HELVETICA,jpype.JFloat(12),ObjFont.BOLD))
    ObjPhrase.add(ObjChunk3)
    iDocPCell=self.package.Cell
    ObjDocPCell=iDocPCell(ObjPhrase)
    ObjDocPTable.addCell(ObjDocPCell)

    iPhrase=self.package.Phrase
    ObjPhrase=iPhrase()
    iChunk= self.package.Chunk
    ObjChunk3=iChunk(“Data1″,iFontFactory.getFont(iFontFactory.HELVETICA,jpype.JFloat(12),ObjFont.BOLD))
    ObjPhrase.add(ObjChunk3)
    iDocPCell=self.package.Cell
    ObjDocPCell=iDocPCell(ObjPhrase)

    iColor=self.AWT.Color
    ObjDocPCell.setBackgroundColor(iColor.orange);

    ObjDocPTable.addCell(ObjDocPCell)

    iPhrase=self.package.Phrase
    ObjPhrase=iPhrase()
    iChunk= self.package.Chunk
    iColor=self.AWT.Color
    ObjChunk3=iChunk(“Data1″,iFontFactory.getFont(iFontFactory.HELVETICA,jpype.JFloat(12),ObjFont.BOLD,iColor.red))
    ObjPhrase.add(ObjChunk3)
    iDocPCell=self.package.Cell
    ObjDocPCell=iDocPCell(ObjPhrase)
    ObjDocPTable.addCell(ObjDocPCell)

    iPhrase=self.package.Phrase
    ObjPhrase=iPhrase()
    iChunk= self.package.Chunk
    iColor=self.AWT.Color
    ObjChunk3=iChunk(“\nData New Data”,iFontFactory.getFont(iFontFactory.HELVETICA,jpype.JFloat(12),ObjFont.BOLD,iColor.red))
    ObjPhrase.add(ObjChunk3)
    iDocPCell=self.package.Cell
    ObjDocPCell=iDocPCell(ObjPhrase)
    ObjDocPTable.addCell(ObjDocPCell)

    def __del__(self):
    shutdownJVM()

    Docexportobject=DocExport()
    Docexportobject.Test()

    Reply to this comment.
  11. AvatarRajkumar
    11
  12. AvatarDave Rissanen
    12

    I am new to Python and have never used jpype. I tried to execute the hello world sample program in the Jpype user’s guide 0.4. I received no syntax errors and the program called startJVM and shutdownJVM but the hello world messsage did not appear in the Python shell window. Help! If I can’t get this trivial snippet of code working I will never get more complex code to work. Please advise.

    Reply to this comment.