PyServlet
A great advantage of HttpServlet programming for Jython programmers is that the Jython distribution comes with the Servlet org.python.util. PyServlet. This Servlet loads, executes and caches Jython files so that you can write and view a Jython Servlet without any compiling step in the middle. This works with a Servlet mapping. A Servlet mapping is an association between a specific Servlet, PyServlet in this case, and a certain URL pattern, such as *.py. With a proper web.xml file, Jython's PyServlet class is mapped to all *.py files, so as requests for *.py files arrive, the PyServlet class loads, caches, and invokes methods in the *.py files as needed to respond.
PyServlet's design creates some restrictions on the Jython files it serves. A Jython file must contain a class that subclasses javax.servlet.http. HttpServlet. The name of that class must match the name of the file without the .py extension. In other words, the file Test.py must contain the class Test, which must be a subclass of javax.servlet.http.HttpServlet. Additionally, it is unsafe to use module-global identifiers other than the one class which subclasses HttpServlet.
A note on naming: With Servlets, PyServlet, and Jython modules that implement servlets, names get a bit confusing. To clarify any confusion, the term servlet appears in a generic sense regardless of which language implements it. PyServlet refers to the specific Servlet org.python.util.PyServlet. The confusion arises with those Jython modules that PyServlet actually serves. Files matching the *.py pattern within the context that are loaded, executed, and cached by PyServlet, need a name of their own to distinguish them. There is no precedence for any such term, but dubbed jylets they are for the sake of this chapter.
Installing PyServlet
All that is required to install the PyServlet is to define a Servlet mapping and make sure the jython.jar file is in the context's lib directory. A Servlet mapping is defined in the context's deployment descriptor file: web.xml. The web.xml file for the Jython context belongs in the location $TOMCAT_HOME/ webapps/jython/WEB-INF/web.xml. In Tomcat, the default web.xml file from $TOMCAT_HOME/conf/web.xml is used for all the settings that are not explicitly included in the context's web.xml. Therefore, there may not be a web.xml file in your context yet, and you need not define all properties in that context because default values already exist.
Listing 12.5 is an example deployment descriptor for the Jython context, which establishes PyServlet as the handler for context requests matching the *.py pattern. The essential additions to the web.xml file are a Servlet definition for PyServlet and a Servlet mapping that associates URLs with the PyServlet. Because Tomcat has default values for items not defined, Listing 12.5 is a sufficiently complete web.xml file for the Tomcat server.
Listing 12.5 A Sample Deployment Descriptor for PyServlet
<web-app> <servlet> <servlet-name>PyServlet</servlet-name> <servlet-class> org.python.util.PyServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>PyServlet</servlet-name> <url-pattern>*.py</url-pattern> </servlet-mapping> </web-app>
The Servlet definition defines the Servlet name and the Servlet's class. Listing 12.5 defines the name as PyServlet and the class as org.python.util.PyServlet. The class is the full package-class hierarchy that uniquely identifies the Servlet class: PyServlet. The actual class resides in the jython.jar file, which should be in the context's lib directory.
The Servlet definition for PyServlet may optionally include initialization parameters (init-params). PyServlet uses such parameters in the initialization of Jython; therefore, this is where you would place any of the Jython property settings such as python.home, python.path, python.respectJavaAccessibility or any of the other properties normally set in Jython's registry file. Listing 12.6 is a web.xml file supplies a python.home and python.path value as init-params.
Listing 12.6 PyServlet init-params in web.xml
<web-app> <servlet> <servlet-name>PyServlet</servlet-name> <servlet-class> org.python.util.PyServlet </servlet-class> <load-on-startup>1</load-on-startup> <init-param> <param-name>python.home</param-name> <param-value>c:\jython-2.1</param-value> </init-param> <init-param> <param-name>python.path</param-name> <param-value> c:\jython-2.1\lib\site-packages </param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>PyServlet</servlet-name> <url-pattern>*.py</url-pattern> </servlet-mapping> </web-app>
Properties that define locations of Jython resources, such as python.home and python.path are of special concern. These affect whether a context is self contained and affect cross-platform portability. If the python.home property points outside the context, or if the python.path property includes a directory outside the context, the context is no longer self contained. Additionally, the property values must be platform-specific paths. Notice the python.home and python.path properties in Listing 12.6. They would not work on other platforms, and there is no mechanism to create platform-neutral paths for these property values. Fortunately, PyServlet has a default value for the python.home property that creates both a self-contained and a platform-neutral context.
The default python.home value for PyServlet is the context's lib directory. This makes the default python.home value for the Jython context one of the following (depending on platform).
%TOMCAT_HOME\webapps\jython\WEB-INF\lib $TOMCAT_HOME/webapps/jython/WEB-INF/lib
Additionally, Jython's lib directory automatically becomes one of the following:
%TOMCAT_HOME%\webapps\jython\WEB-INF\lib\Lib $TOMCAT_HOME/webapps/jython/WEB-INF/lib/Lib
This keeps all of Jython's resources within the context, keeping it self contained. The additional advantage is that PyServlet adds the default python.home path in a platform-independent manner, making those contexts that use the default value platform independent.
Testing PyServlet
You con confirm that the Servlet mapping is working by starting Tomcat and viewing a simple jylet (Jython-Servlet) in a browser. Below is a simple test jylet:
# File ServletMappingTest.py from javax.servlet.http import HttpServlet class ServletMappingTest(HttpServlet): def doGet(self, req, res): out = res.writer res.contentType = "text/html" print >> out, "Greetings from a jylet."
Save this test file as %TOMCAT_HOME%\webapps\jython\ServletMappingTest.py, then point your browser to http://localhost:8080/jython/ServletMappingTest.py. If you see the greeting message, the PyServlet mapping is correct. To complete the installation, create Jython's lib directory %TOMCAT_HOME%\webapps\jython\WEB-INF\lib\Lib. This is the directory where you will place any Jython modules used in your jylets. After that, installation is complete.