Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Beginning Python (2005)

.pdf
Скачиваний:
177
Добавлен:
17.08.2013
Размер:
15.78 Mб
Скачать

Integrating Java with Python

This command creates a WEB-INF directory. The name and case of this directory are very important. In J2EE, the WEB-INF directory contains the libraries and deployment information about your Web application:

$ mkdir webapps/jython/WEB-INF/lib

The lib subdirectory holds any jar files needed by your Web application. You need one jar file, jython. jar, from the Jython installation. Copy this file into the webapps/jython/WEB-INF/lib directory that you just created.

Next, you need to create a file named web.xml in the webapps/jython/WEB-INF directory. Enter the following text into web.xml:

<?xml version=”1.0” encoding=”ISO-8859-1”?> <web-app>

<servlet> <servlet-name>PyServlet</servlet-name>

<servlet-class>org.python.util.PyServlet</servlet-class> <init-param>

<param-name>python.home</param-name> <param-value>/Users/ericfj/Documents/java/jython-2.1</param-value>

</init-param> </servlet> <servlet-mapping>

<servlet-name>PyServlet</servlet-name> <url-pattern>*.py</url-pattern>

</servlet-mapping> </web-app>

Change the path in bold to the full path to the directory in which you installed Jython.

You should now have two files in your new Web application:

webapps/jython/WEB-INF/lib/jython.jar

webapps/jython/WEB-INF/web.xml

These two files are essential. Next, you need to create some Python scripts within the new Web application.

This chapter presents a whirlwind introduction to J2EE, a frightfully complicated subject. If you’re not familiar with J2EE, you can look up more information in a J2EE tutorial, such as the one located at http://java.sun.com/j2ee/1.4/docs/tutorial/doc/index.html.

Extending HttpServlet

The javax.servlet.http.HttpServlet class provides the main hook for J2EE developers to create servlets. J2EE developers extend HttpServlet with their own classes to create servlets. With the PyServlet class, you can do the same with Jython. With Jython, however, this task becomes a lot easier than writing everything in Java.

561

TEAM LinG

Chapter 22

Use the following code as a template for creating your servlet classes in Jython:

from javax.servlet.http import HttpServlet

class verify(HttpServlet):

def doGet(self, request, response): self.handleRequest(request, response)

def doPost(self, request, response): self.handleRequest(request, response)

def handleRequest(self, request, response): response.setContentType(“text/html”); out = response.getOutputStream()

print >>out, “YOUR OUTPUT HERE” out.close()

return

Your classes must inherit from HttpServlet. In addition, you need to create two methods, doGet and doPost, as described in the following table.

Method

Usage

 

 

DoGet

Handles GET requests, which place all the parameters on the URL

DoPost

Handles POST requests, usually with data from a form

 

 

In virtually all cases, you want both methods to perform the same task. Any differences in these methods only serve to make your Web applications harder to debug. Therefore, write another method that both can call, such as the handleRequest method shown in the previous template.

In your handleRequest method, you must perform a number of tasks. All must be correct, or you will see an error or no output. These tasks include the following:

Set the proper content type on the response object. In most cases, this will be text/html.

Get an output stream from the response object.

Write all output to this stream.

Close the stream.

The following example shows how to create a real servlet from this code template.

Try It Out

Writing a Python Servlet

Enter the following and save the file as webapps/jython/verify.py:

import sys

from javax.servlet.http import HttpServlet

class verify(HttpServlet):

562

TEAM LinG

Integrating Java with Python

def doGet(self, request, response): self.handleRequest(request, response)

def doPost(self, request, response): self.handleRequest(request, response)

def handleRequest(self, request, response): response.setContentType(“text/html”);

out = response.getOutputStream()

print >>out, “<html><head><title>”

print >>out, “Jython Is Running</title></head>” print >>out, “<body>”

print >>out, “<h2>Jython is running</h2>” print >>out, “<p>”

print >>out, “Version:”, sys.version, “ verified.” print >>out, “</p>”

print >>out, “</body></html>” out.close()

return

You must place this file within your Web application in the webapps/jython directory. After saving the file, stop and then restart Tomcat to ensure that your changes are recognized.

Test your new servlet by entering the following URL in your Web browser: http://localhost:8080/ jython/verify.py. Figure 22-3 shows the results you should see.

Figure 22-3

How It Works

Three crucial parts make this servlet work:

Tomcat must be running.

You must have the correct directory structure and contents for your Web application.

The URL must name a Python script in your Web application. The script must have a .py filename extension.

563

TEAM LinG

Chapter 22

In the web.xml file created previously, you registered the servlet PyServlet for all files ending with a

.py extension. Thus, with a URL of http://localhost:8080/jython/verify.py, Tomcat will direct the servlet PyServlet to handle the request. The following table splits this URL into its important components.

Component

Usage

 

 

http://

Defines the protocol used, HTTP in this case

jython

This is the name of your Web application (it could be any name you wanted).

 

With Tomcat, there must be a webapps/jython directory.

verify.py

Name of a file within the Web application. The .py extension signals that the

 

PyServlet should handle the request.

 

 

The actual servlet class itself is rather small and follows the code template shown previously. The main action of this servlet occurs in the handleRequest method:

def handleRequest(self, request, response): response.setContentType(“text/html”);

out = response.getOutputStream() print >>out, “<html><head><title>”

print >>out, “Jython Is Running</title></head>” print >>out, “<body>”

print >>out, “<h2>Jython is running</h2>” print >>out, “<p>”

print >>out, “Version:”, sys.version, “ verified.” print >>out, “</p>”

print >>out, “</body></html>” out.close()

return

Most of this method is a number of print statements, sending HTML-formatted text to the output stream. Compare this method for creating Web applications with the technologies introduced in Chapter 21.

As you can see, you really need to know both Python and Java, at least a bit, to be able to work with Jython. That’s why choosing the right tools is important.

Choosing Tools for Jython

Because Jython focuses on working with Java as well as Python, the best choice for Jython tools comes from the Java arena. The following tools can help with your Jython work:

The jEdit text editor (www.jedit.org/) includes a number of plugins for working with Python. The editor highlights Python syntax, whether you are working with Python or Jython. In addition, the JythonInterpreter plugin includes an embedded Jython interpreter. See http:// plugins.jedit.org/ for more on jEdit plugins.

564

TEAM LinG

Integrating Java with Python

The Eclipse Integrated Development Environment, or IDE, provides excellent support for Java development. In addition, two Eclipse plugins stand out for Jython usage: PyDev, for working with Python, at http://sourceforge.net/projects/pydev/; and the RedRobin Jython development tools plugin, at http://home.tiscali.be/redrobin/jython/. The latter plugin focuses specifically on Jython. Download Eclipse itself from www.eclipse.org.

Whichever tools you choose, all you really need is a text editor and a command-line shell. Furthermore, the tools you choose can help with testing, especially testing Java applications.

Testing from Jython

Because Jython provides an interactive environment on top of the Java platform, Jython makes an excellent tool for interactive testing. The following examples show how you can use Jython’s interactive mode to explore your Java environment.

Try It Out

Exploring Your Environment with Jython

Enter the following commands to see information on the Java Map interface:

$ jython

Jython 2.1 on java1.4.2_05 (JIT: null)

Type “copyright”, “credits” or “license” for more information.

>>>from java.util import Map

>>>print dir(Map)

[‘clear’, ‘containsKey’, ‘containsValue’, ‘empty’, ‘entrySet’, ‘equals’, ‘get’, ‘hashCode’, ‘isEmpty’, ‘keySet’, ‘put’, ‘putAll’, ‘remove’, ‘size’, ‘values’]

>>>

How It Works

This example uses the Python dir function to display information about the java.util.Map interface in Java. You can list information on any Java class or interface.

As another example, you can examine the JNDI, or Java Naming and Directory Interface, classes such as

InitialContext, as shown here:

$ jython

Jython 2.1 on java1.4.2_05 (JIT: null)

Type “copyright”, “credits” or “license” for more information.

>>>from javax.naming import InitialContext

>>>print dir(InitialContext)

[‘bind’, ‘composeName’, ‘createSubcontext’, ‘destroySubcontext’, ‘getNameParser’, ‘list’, ‘listBindings’, ‘lookup’, ‘lookupLink’, ‘rebind’, ‘rename’, ‘unbind’]

>>>

Combine this technique with an embedded Jython interpreter to examine a running application. See the following section, “Embedding the Jython Interpreter,” for more information on embedding the Jython interpreter.

565

TEAM LinG

Chapter 22

In addition to using Jython’s interactive mode, you can also write tests in Jython.

Many organizations shy away from open-source software such as Jython. You may find it much easier to introduce Jython just for writing tests, something that will not go into production. Once your organization gains some experience with Jython, people may be more receptive to using Jython in more areas.

The examples so far have all used the jython script to run Jython scripts, except for the PyServlet servlet example. With the PyServlet class, you have a Java class with the Jython interpreter. You can add the Jython interpreter to your own classes as well.

Embedding the Jython Interpreter

By embedding the Jython interpreter in your own Java classes, you can run scripts from within your application, gaining control over the complete environment. That’s important because few Java applications run from the command line.

You can find the Jython interpreter in the class org.python.util.PythonInterpreter.

You can use code like the following to initialize the Jython interpreter:

Properties props = new Properties();

props.put(“python.home”, pythonHome);

PythonInterpreter.initialize(

System.getProperties(),

props,

new String[0]);

interp = new PythonInterpreter(null, new PySystemState());

Note that this is Java code, not Python code.

You must set the python.home system property.

Calling Jython Scripts from Java

After initializing the interpreter, you can execute a Jython script with a call to the execfile method. For example:

interp.execfile(fileName);

You need to pass the full name of the file to execute. You can see this in action with the following example.

566

TEAM LinG

Integrating Java with Python

Try It Out

Embedding Jython

Enter the following Java program and name the file JyScriptRunner.java:

package jython;

import java.util.Properties;

import org.python.util.PythonInterpreter; import org.python.core.PySystemState;

/**

* Runs Jython scripts. */

public class JyScriptRunner {

private PythonInterpreter interp;

/**

* Initializes the Jython interpreter. */

public void initialize(String pythonHome) { Properties props = new Properties();

props.put(“python.home”, pythonHome);

PythonInterpreter.initialize(

System.getProperties(),

props,

new String[0]);

interp = new PythonInterpreter(null, new PySystemState());

}

/**

* Runs the given script. */

public void run(String fileName) { interp.execfile(fileName);

}

public static void main(String[] args) { String fileName = args[0];

JyScriptRunner runner = new JyScriptRunner();

String pythonHome = System.getProperty(“python.home”);

runner.initialize(pythonHome);

runner.run(fileName);

}

}

567

TEAM LinG

Chapter 22

Because this is a Java program, you will need to compile the program with a command like the following:

$ javac -classpath ./jython.jar JyScriptRunner.java

When you run this Java program, you will see output like the following:

$ java -cp ./jython.jar:. \ -Dpython.home=”/Users/ericfj/Documents/java/jython-2.1” \ jython.JyScriptRunner jystring.py

The platform is: java1.4.2_05 time for an omelette. Home directory: /Users/ericfj

Some numbers: 44.1, 42 (‘Red’, ‘Green’, ‘Blue’, 255, 204, 127) User home directory: /Users/ericfj

This example runs the jystring.py example script. You will need to change the -Dpython.home setting to the location where you have installed Jython. Also change the ./jython.jar to the location where you have the file jython.jar.

How It Works

The program expects the caller to pass two values: the setting for the python.home system property and the name of a script to execute. You must have the jython.jar located in the current directory (or change the command line to refer to the location of your jython.jar file).

The JyScriptRunner class includes a main method, called when you run the program. The main method extracts the system property python.home as well as the filename from the command line (held in the args array). The main method then instantiates a JyScriptRunner object.

The main method initializes the JyScriptRunner object and then calls the run method to execute the script. Any errors encountered in the Jython script will result in exceptions that stop the program.

This is probably about the simplest Jython interpreter you can create. In your applications, you’ll likely want to control the location of the Python home directory, perhaps placing this under an application directory.

Compiling Python Code to Java

You can use the jythonc script to compile your Jython code into Java code, and then, into Java .class files. At its simplest, you can call jythonc with the following arguments:

jythonc --package package_name file.py

568

TEAM LinG

Integrating Java with Python

This will create a directory called jpywork, and inside that directory, .java and .class files. For example, you can compile the jystring.py script introduced previously in this chapter with a command like the following:

$ jythonc --package jy jystring.py processing jystring

Required packages: java.lang

Creating adapters:

Creating .java files: jystring module

Compiling .java to .class...

Compiling with args: [‘/System/Library/Frameworks/JavaVM.framework/Versions/1.4.2/Home/bin/javac’, ‘-classpath’, ‘/Users/ericfj/Documents/java/jython- 2.1/jython.jar::./hsqldb.jar:./jpywork:: /Users/ericfj/Documents/java/jython2.1/Tools/jythonc: /Users/ericfj/writing/python/chap22/.: /Users/ericfj/Documents/java/jython-2.1/Lib’,

‘./jpywork/jy/jystring.java’]

0

When complete, you should see the following files in the jpywork directory:

$ ls jpywork/jy

jystring$_PyInner.class jystring.java jystring.class

Handling Differences between C Python and Jython

The C Python platform creates a complete environment based on Python standards and conventions. Jython, on the other hand, tries to create a complete Python environment based on the Java platform. Because of this, there are bound to be differences between the two implementations. These differences are compounded when you mix Java code into your Jython scripts.

The Jython interpreter will attempt to convert Python types into the necessary Java types to call methods on Java classes. Wherever possible, the Jython interpreter tries to do the right thing, so in most cases you don’t have to pay much attention to these type conversions. If you are unsure which Python types are needed to call a particular Java method, look at the types listed in the following table.

569

TEAM LinG

Chapter 22

Python Type

Java Type

 

 

None

Null

Integer (any non-zero

Boolean

value is true)

 

Integer

short, int, long, byte

String

byte[], char[], java.lang.String

String of length 1

Char

Float

float, double

String

java.lang.Object, converted to java.lang.String

Any

java.lang.Object

Class or JavaClass

java.lang.Class

Array (must contain

Array of a particular type

objects of a given type

 

or subclasses of the

 

given type)

 

 

 

For example, if a Java method expects a type of java.lang.Object and you pass a Python String, Jython will convert the Python String to a java.langString object. Jython will pass any other Python object type unchanged.

You can do many more things with Jython beyond the introduction provided in this chapter. For example, you can create classes in Jython and then call those classes from Java. (Look in the source code for the PyServlet class to see an example of this.)

Summar y

Jython provides the capability to combine the scripting power of Python with the enterprise infrastructure of Java. Using Jython can make you a much more productive Java developer, especially in organizations where Python is not accepted but Java is.

Jython allows you to do the following:

Run Python scripts from the Java platform. Because these scripts differ from Python, they are usually called Jython scripts.

Call on Java code and classes from within your scripts. This enables you to take advantage of the rich set of Java libraries from Jython scripts.

Create user interfaces with the Java Swing API. Jython scripts can use Python’s tuple and property support to dramatically reduce the code required to create Swing-based user interfaces.

Compile Jython code to Java .class files with the jythonc script.

570

TEAM LinG