- Jython Servlet Containers
- Defining Simple Servlet Classes
- More About GenericServlet
- HttpServlet
- PyServlet
- Cookies
- Sessions
- Databases and Servlets
- JSP
More About GenericServlet
Listing 12.2 inherits from javax.Servlet.GenericServlet. This class is just what its name implies: a Servlet class that is not specific to any protocol. The HttpServlet class is more common for web programming because it is specific to the HTTP protocol; however, GenericServlet is HttpServlet's superclass, and its methods are important to know. Table 12.1 has a summary of Java method signatures for GenericServlet and examples of how a Jython subclass of GenericServlet would use those methods. These are not all the methodsjust those easily used from Jython. Table 12.1 lists methods in two categories:
Methods overridden in the Jython subclass, noted by the def statements.
Superclass methods invoked from the Jython subclass, noted by qualifying the method with self.
Table 12.1 GenericServlet Methods
Java Signature |
Usage in Jython Subclass |
Methods You Subclass: |
|
public void init(ServletConfig config) throws ServletException; |
def init(self, config): |
public void destroy(); |
def destroy(self): |
public abstract void service(ServletRequest request, ServletResponse response) throws Servletexception, IOException; |
def service(self, request, response): |
public String getServletInfo(); |
def getServletInfo(self): return "Info string" |
Methods You Use with the self.Method Syntax: |
|
public void log(String message); |
self.log("message") |
public ServletConfig getServletConfig(); |
config = self.getServletConfig() |
public java.util.enumeration getInitParameterNames(); |
nameList = self.getInitParameterNames() |
public String getInitParameter(String name) |
param = self.getInitParameter("paramName") |
public ServletContext getServletContext() |
context = self.getServletContext |
You have already seen an example of overloading the public abstract void service() method in Listing 12.2. The other methods available for overloading get attention in the following hit counter Servlet.
A hit counter Servlet is almost as obligatory as a Hello World application in the pedagogy of programming. Here it is in the name of tradition. The hitCounter Servlet (see Listing 12.3) shows the use of the init, service, and destroy methods. A discussion of each of these methods appears following the listing.
Listing 12.3 HitCounter Servlet
# filename: HitCounter.py from javax import servlet from time import time, ctime import os class HitCounter(servlet.GenericServlet): def init(self, cfg=None): if cfg: servlet.GenericServlet.init(self, cfg) else: servlet.GenericServlet.init(self) # Construct a path + filename to file storing hit data contextRoot = self.servletContext.getRealPath(".") self.file = os.path.join(contextRoot, "counterdata.txt") if os.path.exists(self.file): lastCount = open(self.file, "r").read() try: # within 'try' just in case the file is empty self.totalHits = int(lastCount) except: self.totalHits = 0 else: self.totalHits = 0 def service(self, req, res): res.setContentType("text/html") toClient = res.getWriter() toClient.println("<html><body>") toClient.println("Total Hits: %i<br>" % (self.totalHits,)) self.totalHits += 1 toClient.println("</body></html>") def destroy(self): f = open(self.file, "w") f.write(str(self.totalHits)) f.close()
Place the HitCounter.py in the context's classes directory (%TOMCAT_HOME%\webapps\jython\WEB-INF\classes), and compile it with jythonc from within the same directory.
jythonc w . deep HitCounter.py
Test the HitCounter Servlet by pointing you browser to http://localhost:8080/jython/servlet/HitCounter. You should see the message "Total Hits: 0" The first time you visit this URL. Each subsequent hit increments the count. If you shut down Tomcat with %TOMCAT_HOME%\bin\shutdown.bat ($TOMCAT_HOME/bin/shutdown.sh for bash) and restart Tomcat, the hit count should continue at its last number.
The three methods init, service, and destroy are essential to Servlets, and each one matches a stage of a Servlet's life cycle. A Servlet is first loaded and initialized: the init() method. A Servlet then handles client requests: the service() method. A Servlet handles requests until it is unloaded or removed from the Servlet container(): the destroy method.
init(ServletConfig) Method
The init() method is called at Servlet startup, and only called that one time. This makes it useful for time-intensive tasks such as setting up database connections, compiling regular expressions or loading ancillary files. The purpose of including an init() method in Listing 12.3 is to establish the file that stores the hit information, and to set the counter to the last stored integer in that file. This implementation ensures that the hit counter is not reset to 0 unless the Servlet is restarted and the counter.txt file is missing.
The 2.2 version of the Servlet API has two init() methods: a parameterless version and one that accepts an instance of the ServletConfig class. Listing 17.3 uses the variable cfg for this object. It's important to remember that when Jython overrides a Java method, it overrides all methods with that name. This means that defining an init() method in a Jython Servlet overrides both the parameterless init() and the init(ServletConfig cfg) methods. Listing 17.3 handles the functionality of both methods by specifying a default argument of None for the cfg variable, then testing for None to determine if that cfg variable should be used when calling the superclass's init() method.
service(ServletRequest, ServletResponse) Method
This is the method called in response to each client request. A Servlet must define this method because it is abstract in GenericServlet. The arguments passed to this method are the ServletRequest and the ServletResponse objects. ServletRequest contains client information sent in the request to the server such as the request headers, request method, and request parameters. ServletResponse is used for sending the response stream in the appropriate mime-encoded format back to the client.
destroy() Method
This is called when shutting down or unloading a Servlet. Cleanup code goes here, including closing database connections, flushing and closing files, and so on.
The destroy method in Listing 12.3 writes the hit counter value to a file so that the information is not lost when the Servlet is unloaded. This isn't the best means of persistence, however. The hit count value only gets stored if the server is shutdown politely. If the Servlet container is not shutdown properly, the destroy method may not be called. When you are using Tomcat, you usually start and stop the server with the startup and shutdown shell scripts. These are the polite and proper ways to start and stop Tomcat; however, if you choose to stop Tomcat with an impolite "Ctrl+C", the proper shutdown sequence is skipped. Additionally, an error that unexpectedly terminated Tomcat causes the same results, and the hit count would be lost. Higher quality persistence would require that the data be stored in a way that the assignment and commit are in a transaction framework.