Getting Down to Business
I'll start by looking at how to test the syntax of a core Java API class, java.lang.String. Jython relies upon the system classpath to know where to find and load Java class files. Therefore, to get at any of the core libraries requires a simple one-line import statement. In the code snippet below you'll see the import statement and also likely notice that to instantiate a String object in Jython doesn't require the use of the 'new' operator. I'm always in favor of less typing, however, this might trip you up initially if you're coding in Java on auto-pilot mode. Also, note that if the Jython interpreter likes what you've entered, it silently returns to the command prompt. If it doesn't like it, an error message will specify where you went wrong.
>>> from java.lang import String
>>> s=String("hello world Jython")
>>> from java.util import Kollections
Traceback (innermost last):
File "<console>", line 1, in ?
ImportError: cannot import name Kollections
>>> from java.util import Collections
>>>
To take this a step further you need to test your new String object. The String class'
substring( ) method requires the starting and ending position to break out, but are these arguments inclusive or exclusive? You can use Jython to test this out (shown in the next code snippet).
First, remind yourself of the value of the starting String object. In Jython simply typing the name of the variable pulls back its valueno need for
System.out.println( ). To extract the word 'world' from the String I count the letters to the initial 'w' and then to the end of the word and use them as my arguments to the
substring() method. Again, no class file or compile cycle is requiredin two seconds I see my results and know that my guessthat the substring starting point was inclusivewas incorrect. I make the adjustment and confirm the proper syntax for this method.
>>> s
hello world Jython
>>> s.substring()
Traceback (innermost last):
File "<console>", line 1, in ?
TypeError: substring(): expected 1-2 args; got 0
>>> s.substring(7,11)
'orld'
>>> s.substring(6,11)
'world'
>>>
If you've got a good memory and are very familiar with the core APIs, that probably didn't impress you very much, so now I'll move on to a more challenging third-party library. Recently, I had to do a little regular expression pattern matching and made use of the
Jakarta-Oro library. For those using JDK 1.4 day-to-day, pattern matching for regular expressions is available in the core API; for those of us using older SDKs, the Jakarta-Oro library works very well. It is worth mentioning that regular expressions are part of the core Python distribution in the
re module but I needed to write the code for this project in Java.
To gain access to the class files in the
jakarta-oro.jar file I have to make the Jython interpreter aware of its existence. As in Java, the
.jar file must be added to the classpath, however, I'll use Python syntax as a shortcut for doing this in the Jython environment.
The Python
sys library contains the "path" class that is used to add
.jar files to the runtime environment.
>>> import sys
>>> sys.path.append(r'C:\Documents and Settings\doug\javalib\jakarta-struts-1.1
\lib\jakarta-oro.jar')
Next I verify that the path is updated by querying its contents. Note that no print statement is required. Simply typing the variable returns its value.
>>> sys.path
['', 'C:\\jython-2.1b1\\.', 'C:\\jython-2.1b1\\Lib', 'c:\\jython-2.1b1\\jython-2
.1b1lib', 'C:\\jython-2.1b1', 'C:\\Documents and Settings\\doug\\javalib\\jakarta-struts
-1.1\\lib\\jakarta-oro.jar']
Now that I know that my
.jar file is on the path, I can access its classes just as I accessed the core library String class earlier.
>>> from org.apache.oro.text.regex import Pattern
*sys-package-mgr*: processing new jar, 'C:\Documents and Settings\gidat\javalib\
jakarta-struts-1.1\lib\jakarta-oro.jar'
Note that Jython very helpfully informs me that it is opening a new
.jar file to comply with my import request. I need some other imports so I'll specify those next.
>>> from org.apache.oro.text.regex import PatternCompiler
>>> from org.apache.oro.text.regex import PatternMatcher
>>> from org.apache.oro.text.regex import Perl5Compiler
>>> from org.apache.oro.text.regex import Perl5Matcher
Now I'm ready to start instantiating my objects so I can test out my regular expressions. In the snippet below I obtain a compiler object and as you can see from the class name, it is going to be compliant with the way the Perl 5 regex engine evaluates expressions. Next, I set up the pattern that I'll use for the matching. I'm looking for an ID that is six digits. The regex shorthand for a digit is
\d and I escape the backslash in the string with another backslash so it is evaluated correctly. The {6} specifies that I'm looking for exactly six digitsno more, no less. (For more information about the somewhat arcane syntax of regular expressions see Related Resources in the left column.)
>>> c=Perl5Compiler()
>>> p=c.compile("\\d{6}")
What I'm looking to do is fairly simple as regular expressions go, but I want to make sure I've got it right before I start coding my class. I get a little impatient though and type:
>>> p.match("777777")
Traceback (innermost last):
File "<console>", line 1, in ?
AttributeError: match
Not only do I have the incorrect method name but I am also attempting to use a method on the Pattern object that really exists in the Perl5Matcher class. I'll take another shot at it:
>>> s="777777"
>>> m=Perl5Matcher()
>>> m.match(s,p)
Traceback (innermost last):
File "<console>", line 1, in ?
TypeError: call of non-function ('None' object)
I'm getting closer but it appears that I have the method name wrong; a quick peek at the Javadoc sets me straight and I get a successful match.
>>> m.matches(s,p)
1
Jython returns a 1 value for '
true' and 0 for '
false'. Because the regular expression pattern I compiled is for exactly six consecutive digits, the code above evaluated to a match. Compare my successful matching effort to the lines below after I reassign variable s to a non-numeric string.
>>> s="aaaaaa"
>>> m.matches(s,p)
0
That's all there is to it: I can play around with my pattern matching without ever needing to compile a class or write a
main( ) method. I've used this technique with disparate libraries such as Alta Vista and Lotus Notes Java APIs among others and it has saved me countless hours of work.
Despite Jython's slight lag with the C Python implementation and current JDK, it is a robust and stable language for working with Java libraries. Jython's command line interactive interpreter can save you time when figuring out or testing an unfamiliar API and the interactive interpreter provides instantaneous feedback. Other open source tools such as Groovy or the new 'Scrap Page' feature in Eclipse 3.14 offer similar capabilities and are worth investigating too, but if you're familiar with Python, Jython offers substantial other functionality that ought to put it at the top of your tools list.