|
Jython is a pure Java implementation of the popular scripting language Python. Implemented entirely in Java, Jython runs under any compliant JVM. For its part, Python is a high-level, dynamic, object-oriented scripting language that has enjoyed considerable popularity with developers from all disciplines of software engineering. The features of the Python language enable the writing of scripts that are far shorter than the equivalent code implemented in Java. The features of the Python language include the following:
This melding of the J2SE platform and Python has resulted in an exciting symbiosis. Jython harnesses the strength of the Python scripting language and offers crossplatform capabilities by virtue of the JVM under which it runs. Jython is also designed to integrate with Java, making it possible to access Java classes from within a script. Consequently, developers have the best of both worlds: access to the full services of the J2SE platform as well as the extensive set of libraries Python encompasses. Jython's features include the following:
In the next sections, we cover the major points regarding Jython and the Jython scripting language:
The first step is to download and install Jython. Installing JythonJython, along with a comprehensive set of documentation, is available for download from http://www.jython.org. The site details the installation steps and provides a few basic tutorials. Note that Jython initially started out in life as JPython. The P has since been dropped in order to sidestep some tricky licensing issues. Jython is open source and available for free download and use. Nevertheless, as is the case with all software used within this book, you should carefully read the licensing terms before using any of the software covered. Documentation The Jython site contains information that specifically relates to Jython, and not the Python language. For extensive documentation on the Python syntax, including a library reference and complete tutorial, visit the Python Web site at http://www.python.org. Running ScriptsThere are several ways to execute Jython scripts. Starting the Jython interpreter in interactive mode allows Jython statements to be entered and executed directly from the Jython shell. Launch the Jython interpreter using the appropriate command file found in the bin directory of the Jython installation. On a Windows platform, this is jython.bat. Entering jython.bat at a command prompt starts Jython in interactive mode. Jython 2.1 on java1.4.1_02 (JIT: null) Type "copyright", "credits" or "license" for more information. >>> x = 1 >>> if x: ... print 'Hello World' ... Hello World >>> The interpreter accepts commands at the primary prompt, identified by the three greater-than signs: >>>. The secondary prompt accepts continuation commands and is identified by three dots: .... Jython also executes Jython statements as scripts and exits the interpreter on completion. Jython script files typically have an extension of .py, and are submitted to the Jython interpreter for execution from the command line: jython myscript.py Now that we know how to run Jython programs and execute Jython statements, let's examine the rudimentary elements of the Jython language. The Jython LanguageTo appreciate the brevity of the Jython syntax, we look at a complete example that demonstrates reading from a file. Manipulating files and file contents is a common use for scripting languages, so it is a good place to start. Here, the code opens a text file and displays the length of each word within the file. f=open('sample.txt') for word in f.read().split(): print word, len(word) f.close() The code shown isn't a code snippet; it is a complete example. Firing up the Jython interpreter and entering the above statements gives the following output: Monty 5 Python's 8 Flying 6 Circus 6 Notice that it isn't necessary to define a class or even a main method. Furthermore, Jython's type-less syntax means the example is devoid of any type declarations, keeping the code very succinct. Statements are also grouped by indentation and not by curly braces, as in Java, thereby keeping the script short and concise. Note Python isn't named after a snake but after the famous BBC comedy Monty Python's Flying Circus. The file parsing example relies on Jython's intrinsic support for compound data types such as lists and maps. The strip() function in the example transforms the contents of the file from a string to a list. The for statement then iterates over the elements of the list. List processing is a powerful concept in Jython, making for a highly expressive syntax. Defining both lists and maps in Jython is very easy. Note Jython uses the term dictionary for lists that hold key/value pairs. list = ['The', 'Life', 'of', 'Brian'] map = {10: 'The', 20:'Meaning', 30:'of', 40:'Life'} The same declarations in Java are slightly more verbose: List list = new LinkedList(); list.add("The"); list.add("Life"); list.add("of"); list.add("Brian"); Map map = new HashMap(); map.put(new Integer(10), "The"); map.put(new Integer(20), "Meaning"); map.put(new Integer(30), "of"); map.put(new Integer(40), "Life"); Jython wouldn't be object-oriented without the ability to define classes. Here is a class declaration of type Customer, with methods update() and total(). # Customer class declaration # class Customer: def update(self, value): self.amount = value def total(self): return self.amount The def keyword defines a function or method. The self parameter is important because it represents the equivalent of the this reference in Java. Jython implicitly passes this reference each time a method on an instance of the object is called. Note Jython is not tied to the object-oriented paradigm, and unlike Java, allows the declaration of functions outside of the scope of a class. Instantiating the Customer class uses another terse piece of syntax. Here is how to create an object and invoke its methods: obj = Customer() # Create Customer instance obj.update(10) print obj.total() The first line creates an instance of the Customer class. Note that there is no requirement in Jython to use Java's equivalent of the new keyword or to define the type of the object being referenced by the obj variable. Jython only discovers whether the update() and total() methods actually exist on the obj reference when the interpreter attempts to execute those lines of code. Integration with JavaNow that you have been introduced to some of the basics of the Jython syntax, it's time to move onto something more interesting. Up until this point, all the examples could have been completed using Python, the scripting language on which Jython is based. The advantage of choosing Jython over Python, or over alternative scripting languages such as Perl or Ruby, is the ability of Jython to integrate seamlessly with existing Java classes. To demonstrate this integration capability, we create a standard Java class and use it from a Jython script. Listing 9-1 shows the Person class. Listing 9-1. Person Java Class Declarationpublic class Person { private String name; private int age; /** * Default constructor */ public void Person() { } /* * Getter and setter methods for class properties */ public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } } Before the Person class can be accessed from within a Jython script, you must set the CLASSPATH environment variable so Jython can find the new classes to load. Optionally, you may write an alternate Jython startup file that sets the classpath for the interpreter accordingly. The following is a three-line script that creates and initializes an instance of the Person class and prints out its properties. import Person obj = Person(name = 'Bill', age = 20) print obj.name, obj.age The import statement pulls the Person module into the script's namespace. If the classpath is set incorrectly, Jython will report an error at this point. Once the class is loaded into the script, an instance of the class is created. The syntax used to initialize the object is a shorthand form. On loading the class, Jython scans the class for common patterns and can recognize JavaBean-compliant getters and setters. Jython represents these methods as properties and allows them to be set through the constructor using the notation Person(name = 'Bill', age = 20) With an instance of the Person class created, the final line prints out the two properties name and age. Again, note the convenience of being able to use property notation rather than formal method semantics. Like Java, Jython supports inheritance, making it possible for classes to derive from both other Jython classes and Java classes. Jython supports inheritance through the syntax Class DerivedClass(BaseClass1, BaseClass2, BaseClassN): From the syntax, you can see that Jython goes beyond Java's single inheritance and supports multiple inheritance. However, when Jython classes inherit from Java classes, only a single Java class can be included in the inheritance hierarchy of a Jython class. Listing 9-2 shows a Jython script that has the Customer class extend the Person Java class. The integration between the two class types is seamless, with the main function accessing methods from both the superclass and the deriving Customer class. Listing 9-2. Script PersonDemo.py# Import Person Java class # import Person # Customer class declaration # class Customer(Person): def update(self, value): self.amount = value def total(self): return self.amount # Main function # def main(): # Create instance of Customer # obj = Customer(name = 'Bill', age = 20) # Using Customer properties # print obj.name, obj.age # Using Person methods # obj.update(99); print obj.total() # Entry point for script # if __name__ == '__main__': main() Now that we have introduced Jython's syntax and integration support for Java, the next sections provide examples of some uses for Jython scripts. User-Interface PrototypingScripting languages are ideal candidates for constructing exploratory prototypes of user interfaces. Using Jython's integration capabilities with Java enables the development of user-interface prototypes with familiar Java class libraries, such as AWT and Swing. Listing 9-3 illustrates a simple user interface written in Jython and using Swing classes. Listing 9-3. User-Interface Script listbox.pyimport java.lang as lang import javax.swing as swing import java.awt as awt def exit(event): lang.System.exit(0) win = swing.JFrame("Jython Example", windowClosing=exit) win.contentPane.layout = awt.GridLayout(2, 1) win.contentPane.add(swing.JList(['Rapid','J2EE','Development'])) win.contentPane.add(swing.JButton('Close',actionPerformed=exit)) win.pack() win.show() The source file listbox.py can be executed directly from the command prompt by invoking jython listbox.py. Figure 9-1 displays the output from the script. Figure 9-1. Output from listbox.py.
Jython also makes a very good glue language. If server-side business components are already in place, Jython can serve as a rapid development language for building user interfaces that expose the underlying business services to the end users. Creating a Jython ServletThe Jython installation provides a special servlet that loads and executes Jython scripts within a Web server's servlet engine. This handy utility allows servlets to be written and deployed as Jython scripts. Servlets are ideal candidates for use in rapid prototyping. They are easily built and deployed, and can operate independently of the server's EJB container. Using Java, however, servlets still need to be compiled, deployed, and configured. This is not so for the Jython servlet script; it only needs to be deployed. Listing 9-4 provides an example of a servlet implemented in Jython. Listing 9-4. Jython Servlet Script params.py# params.py import java, javax, sys class params(http.HttpServlet): def doGet(self, request, response): response.setContentType("text/html") out = response.getWriter() out.println("<HTML>") out.println("<HEAD><TITLE>Jython Servlet Example</TITLE></HEAD>") out.println("<BODY>") out.println("<TABLE BORDER=\"1\" WIDTH=\"100%\">") for name in request.headerNames: out.println("<TR><TD>" + name + "</TD>"); out.println("<TD>" + request.getHeader(name) + "</TD></TR>") out.println("</TABLE>") out.println("</BODY></HTML>") Running the servlet first requires configuring and deploying Jython's PyServlet. This servlet is responsible for loading and executing Jython scripts on the fly. The servlet is configured in the Web application's web.xml deployment descriptor, as shown in Listing 9-5. Listing 9-5. PyServlet Configuration in web.xml <servlet> <servlet-name>pyservlet</servlet-name> <servlet-class>org.python.util.PyServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>pyservlet</servlet-name> <url-pattern>*.py</url-pattern> </servlet-mapping> You can test out the Jython servlet with a suitable servlet container such as Apache's Tomcat. First, create a new directory structure for the servlet under the webapps directory: <TOMCAT_HOME>/webapps/<context>. If necessary, copy one of the example Web applications that come with the Tomcat installation. Modify the web.xml deployment descriptor so it contains an entry for PyServlet, as shown in Listing 9-5. You also need to copy jython.jar to the lib directory of the Web application: <context>/WEB-INF/lib. The jython.jar is needed to load the Jython interpreter. Alternatively, the servlet parameter python.home can be set, which specifies the location of the jython.jar. If this parameter is not defined in the deployment descriptor, PyServlet assumes <context>/WEB-INF/lib by default. The final step is to copy the Jython script, in this case, params.py, into the newly created <context> directory structure. Start Tomcat and test the servlet by accessing http://<host_name>:8080/<context>/params.py Figure 9-2 shows the output from the servlet. Figure 9-2. Output from servlet params.py.Jython is not the only scripting language to provide such good support for Java. Another scripting language worthy of consideration is Groovy, a Java-centric scripting language that is rapidly growing in popularity. |
|