
Beginning Python (2005)
.pdf
Integrating Java with Python
horizontalAlignment=JLabel.CENTER)
frame.contentPane.add(label, BorderLayout.CENTER)
frame.contentPane.add(button, BorderLayout.WEST)
frame.setVisible(1)
When you run this script, you should see a window like the one shown in Figure 22-1.
Figure 22-1
Click the button to exit the application.
How It Works
This script shows how you can use Jython with the complex Swing APIs. While this example is almost all calls to Java APIs, it is much shorter than the corresponding Java program would be. That’s because of the handy built-in features that come with Python, such as support for tuples and setting properties.
The script starts by importing several classes in the AWT and Sing APIs. The JFrame class acts as a toplevel window in an application. You can create a JFrame widget with the following statements:
frame = JFrame(size=(500,100))
The size property on a JFrame widget is an instance of another Java class, java.awt.Dimension. In this example, you can make a Dimension object from a tuple and then pass this object to set the size property of the JFrame.
This shows how Jython can make working with the Swing APIs palatable. Creating a user interface with Swing usually involves a lot of tedious coding. Jython greatly reduces this effort.
You can use the Python support for tuples and the Jython-provided integration with Java APIs to set colors as well:
frame.background = 127,255,127
This sets the background color to a light green.
This example uses an eight-bit color definition, with values of zero to 255 for each of the red, green, and blue components of the color. Therefore, 255 means that the green value is set to all on, and the red and blue values are set to half on.
551
TEAM LinG

Chapter 22
Jython makes it easy to create interactive widgets on the screen. For example, the following code creates a JButton widget and sets the widget to call the function exitApp when the user clicks the button:
def exitApp(event): System.exit(0)
button = JButton(label=’Push to Exit’, actionPerformed=exitApp)
In this case, the exitApp function calls the Java method System.exit to exit the Java engine and therefore quit the application. Jython enables you to set Java properties to Python functions, such as exitApp in this example. In Java, you would need to make a class that implements the methods in the java.awt.event.ActionListener interface and then pass in an instance of this class as the action listener for the JButton. The Jython approach makes this much easier.
The example also creates a JLabel widget, which displays a text message, an image, or both. The jyswing.py script sets the horizontal alignment so that the text displays in the center of the widget’s bounds:
label = JLabel(text=’A Pythonic Swing Application’,
horizontalAlignment=JLabel.CENTER)
In this example, the value JLabel.CENTER is a constant on the JLabel class.
In Java terms, JLabel.CENTER is a public static final value on the class.
Once created, you need to place the widgets within a container. In the example script, you need to place the JButton and JLabel widgets in the enclosing JFrame widget, as shown by the following code:
frame.contentPane.add(label, BorderLayout.CENTER)
frame.contentPane.add(button, BorderLayout.WEST)
In Swing applications, you add widgets to the content pane of the JFrame, not directly to the JFrame itself.
Finally, the script makes the JFrame widget visible:
frame.setVisible(1)
Note that the Java setVisible method expects a Java Boolean value, but using the Python True would be flagged as a syntax error because the Java boolean objects aren’t 0 and 1, as they are in Python; they’re a class that gets used sometimes, while 0 and 1 get used at other times in Java. This is one area where Python data types and constants are not yet mapped to their Java equivalents.
Accessing Databases from Jython
JDBC, or Java Database Connectivity, provides a set of APIs to access databases in a consistent manner. Most, but not all, differences between databases can be ignored when working with JDBC.
Python has a set of database APIs as well, as described in Chapter 14. A large difference between the Python APIs and the Java APIs is that the Java JDBC drivers are almost all written entirely in Java.
552 |
TEAM LinG |

Integrating Java with Python
Furthermore, almost all JDBC drivers are written by the database vendors. Most Python DB drivers, such as the ones for Oracle, are written in C with a Python layer on top. Most are written by third parties, and not by the database vendors. The Java JDBC drivers, then, can be used on any platform that supports Java. The Python DB drivers, though, must be recompiled on each platform and may not work on all systems that support Python.
With Jython, the zxJDBC package provides a Python DB-compliant driver that works with any JDBC driver. That is, zxJDBC bridges between the Python and Java database APIs, enabling your Jython scripts to take advantage of the many available JDBC drivers and to use the simpler Python DB APIs.
When working with JDBC drivers, you need the value of four properties to describe the connection to the database, shown in the following table.
Property |
Holds |
|
|
JDBC URL |
Description of the connection to the database in a format defined by the |
|
driver |
User name |
Name of a user who has access rights to the database |
Password |
Password of the user. This is the password to the database, not to an |
|
operating system. |
Driver |
Name of the Java class that provides the JDBC driver |
|
|
You need to gather these four values for any database connection you need to set up using JDBC. The zxJDBC module requires these same values. To connect to a database using the zxJDBC driver, you can use code like the following:
from com.ziclix.python.sql import zxJDBC
url=’jdbc:hsqldb:hsql://localhost/xdb’
user=’sa’
pw=’’
driver=’org.hsqldb.jdbcDriver’
db = zxJDBC.connect(url, user, pw, driver)
The values shown here for the JDBC connection come from the default values for the HSqlDB database, covered in the section “Setting Up a Database.”
Working with the Python DB API
Once you have a connection, you can use the same techniques shown in Chapter 14. The zxJDBC module provides a DB 2.0 API–compliant driver. (Well, mostly compliant.) For example, you can create a database table using the following code:
cursor = db.cursor()
cursor.execute(“”” create table user
553
TEAM LinG

Chapter 22
(userid integer, username varchar, firstname varchar, lastname varchar,
phone varchar)
“””)
cursor.execute(“””create index userid on user (userid)”””)
After creating a table, you can insert rows using code like the following:
cursor.execute(“””
insert into user (userid,username,firstname,lastname,phone)
values (4,’scientist’,’Hopeton’,’Brown’,’555-5552’) “””)
Be sure to commit any modifications to the database:
db.commit()
You can query data using code like the following:
cursor.execute(“select * from user”) for row in cursor.fetchall():
print row
cursor.close()
See Chapter 14 for more on the Python DB APIs.
Setting Up a Database
If you already have a database that includes a JDBC driver, you can use that database. For example, Oracle, SQL Server, Informix, and DB2 all provide JDBC drivers for the respective databases.
Unfortunately, the Gadfly database used in Chapter 14 does not include a JDBC driver. You can use the Python DB API driver, though, if you wish.
If you have a database set up, try to use it. If you have no database, a handy choice is HSqlDB. HSqlDB provides a small, fast database. A primary advantage of HSqlDB is that because it is written in Java, you can run it on any platform that runs Java.
See http://hsqldb.sourceforge.net/ for more on the HSqlDB database. You can download this open-source free package from this site.
You’ll find installing HSqlDB quite simple. Just unzip the file you download and then change to the new hsqldb directory. To run the database in server mode, with the default parameters, use a command like the following:
$ java -cp ./lib/hsqldb.jar org.hsqldb.Server -database.0 mydb -dbname.0 xdb [Server@922804]: [Thread[main,5,main]]: checkRunning(false) entered [Server@922804]: [Thread[main,5,main]]: checkRunning(false) exited
554 |
TEAM LinG |

Integrating Java with Python
[Server@922804]: Startup sequence initiated from main() method [Server@922804]: Loaded properties from [/Users/ericfj/writing/python/chap22/server.properties] [Server@922804]: Initiating startup sequence...
[Server@922804]: Server socket opened successfully in 160 ms. [Server@922804]: Database [index=0, id=0, db=file:mydb, alias=xdb] opened sucessfully in 1168 ms.
[Server@922804]: Startup sequence completed in 1444 ms. [Server@922804]: 2005-03-12 20:09:33.417 HSQLDB server 1.7.3 is online [Server@922804]: To close normally, connect and execute SHUTDOWN SQL [Server@922804]: From command line, use [Ctrl]+[C] to abort abruptly
You can stop this database by typing Ctrl+C in the shell window where you started HSqlDB. You now have a database that you can connect to using the default properties shown in the following table.
Property |
Value |
|
|
JDBC URL |
driver.jdbc:hsqldb:hsql://localhost/xdb |
User name |
sa |
Password |
‘’ (two single quotes, an empty string) |
Driver |
org.hsqldb.jdbcDriver |
|
|
Working with JDBC drivers requires that you add the JDBC jar or jars to the Java classpath. The jython script doesn’t handle this case, so you need to modify the script. For example, to use the HSqlDB database, modify the script to add the hsqldb.jar jar file. For example:
#!/bin/sh
###############################################################################
#
# This file generated by Jython installer
java -Dpython.home=”/Users/ericfj/Documents/java/jython-2.1” \ -classpath \
“/Users/ericfj/Documents/java/jython-2.1/jython.jar:$CLASSPATH:./hsqldb.jar” \ “org.python.util.jython” “$@”
The bold text shows the additional jar file. This example assumes that the file hsqldb.jar will be located in the current directory. That may not be true. You may need to enter the full path to this jar file.
To pull all this together, try the following example, built using the HSqlDB database.
Try It Out |
Create Tables |
Enter the following script and name the file jyjdbc.py:
from com.ziclix.python.sql import zxJDBC
# Modify as needed for your database.
555
TEAM LinG

Chapter 22
url=’jdbc:hsqldb:hsql://localhost/xdb’
user=’sa’
pw=’’
driver=’org.hsqldb.jdbcDriver’
db = zxJDBC.connect(url, user, pw, driver)
cursor = db.cursor()
cursor.execute(“”” create table user
(userid integer, username varchar, firstname varchar, lastname varchar, phone varchar)
“””)
cursor.execute(“””create index userid on user (userid)”””)
cursor.execute(“””
insert into user (userid,username,firstname,lastname,phone) values (1,’ericfj’,’Eric’,’Foster-Johnson’,’555-5555’) “””)
cursor.execute(“””
insert into user (userid,username,firstname,lastname,phone) values (2,’tosh’,’Peter’,’Tosh’,’555-5554’)
“””)
cursor.execute(“””
insert into user (userid,username,firstname,lastname,phone) values (3,’bob’,’Bob’,’Marley’,’555-5553’)
“””)
cursor.execute(“””
insert into user (userid,username,firstname,lastname,phone) values (4,’scientist’,’Hopeton’,’Brown’,’555-5552’)
“””)
db.commit()
cursor.execute(“select * from user”) for row in cursor.fetchall():
print row
cursor.close()
db.close()
556 |
TEAM LinG |

Integrating Java with Python
When you run this script, you will see output like the following:
$ jython jyjdbc.py
(1, ‘ericfj’, ‘Eric’, ‘Foster-Johnson’, ‘555-5555’) (2, ‘tosh’, ‘Peter’, ‘Tosh’, ‘555-5554’)
(3, ‘bob’, ‘Bob’, ‘Marley’, ‘555-5553’)
(4, ‘scientist’, ‘Hopeton’, ‘Brown’, ‘555-5552’)
How It Works
This script is almost the same as the createtable.py script from Chapter 14. This shows the freedom the Python DB API gives you, as you are not tied to any one database vendor. Other than the code to establish the connection to the database, you’ll find your database code can work with multiple databases.
To establish a connection to HSqlDB, you can use code like the following:
from com.ziclix.python.sql import zxJDBC
# Modify as needed for your database. url=’jdbc:hsqldb:hsql://localhost/xdb’ user=’sa’
pw=’’
driver=’org.hsqldb.jdbcDriver’
db = zxJDBC.connect(url, user, pw, driver)
This code uses the default connection properties for HSqlDB for simplicity. In a real-world scenario, you never want to use the default user name and password. Always change the database administrator user and password. Furthermore, HSqlDB defaults to having no password for the administration user, sa (short for system administrator). This, of course, provides a large hole in security.
The following code, taken from Chapter 14, creates a new database table:
cursor = db.cursor()
cursor.execute(“”” create table user
(userid integer, username varchar,
firstname varchar, lastname varchar, phone varchar)
“””)
cursor.execute(“””create index userid on user (userid)”””)
While SQL does not standardize the commands necessary to create databases and database tables, this table sports a rather simple layout, so you should be able to use these commands with most SQL databases.
557
TEAM LinG

Chapter 22
The code to insert rows also comes from Chapter 14, as does the query code. In this, it is Python, with the DB 2.0 API, that provides this commonality. The Jython zxJDBC module follows this API. For example, the code to query all the rows from the user table follows:
cursor = db.cursor()
cursor.execute(“select * from user”) for row in cursor.fetchall():
print row
cursor.close()
The zxJDBC module, though, extends the Python DB API with the concept of static and dynamic cursors. (This ties to the concepts in the java.sql.ResultSet API.) In the Python standard API, you should be able to access the rowcount attribute of the Cursor object. In Java, a ResultSet may not know the full row count for a given query, which may have returned potentially millions of rows. Instead, the JDBC standard allows the ResultSet to fetch data as needed, buffering in the manner determined by the database vendor or JDBC driver vendor. Most Java code that reads database data will then iterate over each row provided by the ResultSet.
To support the Python standard, the zxJDBC module needs to read in all the rows to properly determine the rowcount value. This could use a huge amount of memory for the results of a query on a large table. This is what the zxJDBC documentation calls a static database cursor.
To avoid the problem of using too much memory, you have the option of getting a dynamic cursor. A dynamic cursor does not set the rowcount value. Instead, a dynamic cursor fetches data as needed. If you request a dynamic cursor, you cannot access the rowcount value, but, you can iterate through the cursor to process all the rows returned by the query. To request a dynamic cursor, pass a 1 to the cursor method:
cursor = db.cursor(1)
Dynamic cursors are not part of the Python DB API, so code using this technique will not work with any DB driver except for the Jython zxJDBC driver.
Database access is essential if you are writing enterprise applications. You also need it to be able to create robust Web applications.
Writing J2EE Servlets in Jython
Most Java development revolves around enterprise applications. To help (or hinder, depending on your view), Java defines a set of standards called J2EE, or Java 2 Enterprise Edition. The J2EE standards define an application server and the APIs such a server must support. Organizations can then choose application servers from different vendors, such as WebSphere from IBM, WebLogic from Bea, JBoss from the JBoss Group, and Tomcat from the Apache Jakarta project. Java developers write enterprise applications that are hosted on one of these application servers.
558 |
TEAM LinG |

Integrating Java with Python
A servlet is defined as a small server-based application. The term servlet is a play on applet, which describes a small application. Because in the Java arena applets always run on the client, the server equivalent needed a new name, hence servlet. Each servlet provides a small piece of the overall application, although the term small may be defined differently than you are used to, as most enterprise applications are huge.
Within a J2EE application server, servlets are passive request-response applications. The client, typically a web browser such as Internet Explorer or Firefox, sends a request to the application server. The application server passes the request to a servlet. The servlet then generates the response, usually an HTML document, that the server sends back to the client. In virtually all cases, the HTML document sent back to the client is created dynamically. For example, in a web ordering system, the HTML document sent back may be the results of a search or the current prices for a set of products.
The benefit of writing servlets is that J2EE provides a well-defined API for writing your servlets, and multiple vendors support this API. Contrast this situation with the Python situation where you can choose from many Python Web APIs, but you won’t find anywhere near the vendor support you find in the J2EE arena.
With Jython, you can write Java servlets in Python, simplifying your work immensely. To do so, though, you need an application server that supports servlets.
Setting Up an Application Server
If you already have a J2EE application server, use that. If not, try Tomcat. Tomcat, from the Apache Jakarta project, provides a free open-source servlet engine (called a servlet container in J2EE-speak).
Download Tomcat from http://jakarta.apache.org/tomcat/. Be careful which version you download. Starting with version 5.5, Tomcat requires a 1.5 Java Development Kit, or JDK. Only download a version of Tomcat that will work with the JDK you have installed. Download a Zip file of the binary (pre-built) release of the version you select.
To install, unzip the file you downloaded in a directory. You should see a Tomcat directory based on the version you downloaded, such as jakarta-tomcat-5.0.28. Change to this directory. In this directory, you will see a number of files and subdirectories. The two most important subdirectories are bin, which contains scripts for starting and stopping Tomcat, and webapps, which is where you need to place any Jython scripts you create (in a special subdirectory covered in the next section).
To run Tomcat, change to the bin subdirectory and run the startup.sh script (startup.bat on Windows). For example:
$ ./startup.sh |
|
Using CATALINA_BASE: |
/Users/ericfj/servers/jakarta-tomcat-5.0.28 |
Using CATALINA_HOME: |
/Users/ericfj/servers/jakarta-tomcat-5.0.28 |
Using CATALINA_TMPDIR: |
/Users/ericfj/servers/jakarta-tomcat-5.0.28/temp |
Using JAVA_HOME: |
/Library/Java/Home |
|
|
You must ensure that the JAVA_HOME environment variable is set, or Tomcat will not start. To verify Tomcat is running, enter the following URL into a Web browser: http://localhost:8080/. You should see a document like the one shown in Figure 22-2.
559
TEAM LinG

Chapter 22
Figure 22-2
Once you have an application server such as Tomcat running, the next step is to deploy an application — in this case, a special Python servlet called PyServlet.
Adding the PyServlet to an Application Server
Jython includes a class called org.python.util.PyServlet that acts as a front end for Python scripts. The PyServlet class will load Python scripts, compile these scripts, and then execute the scripts as if they were Java servlets (which, in fact, they are, as shown in the section “Extending HttpServlet,” following).
To make all this magic work, though, you need to create a bona fide J2EE Web application. Luckily, this isn’t that hard. Change to the directory in which you installed Tomcat and run the following commands, which create directories:
$ cd webapps
$ mkdir jython
This command creates a directory under webapps with the name of jython. This means the name of our Web application will be jython:
$ mkdir webapps/jython/WEB-INF
560 |
TEAM LinG |