Monday, October 30, 2006

Tomcat JSP and Servlet Reloading

Well, for my first official blog post, I'd like to talk about a problem I've recently ran into with JSP loading in Tomcat 5.5. Now, I've used Tomcat for years, but never took the time to learn it totally inside and out. I've become very good at using Tomcat over the years by tackling problems as they arise. So, I am very comfortable with it.

So, last week, when I uploaded a JSP to my Tomcat web application directory, and it didn't show the changes I've made to it, I was perplexed. This was the most cut and dry part of using Tomcat. Uploading JSPs and having them dynamically reload. Why was this happening? Why? Why? Why????? After researching the problem, I found that others had the same problem, but their questions were never answered, or the solutions were not available on the web. So hopefully, this post will help someone.

First, I will describe the environment. This is a server that was created for students, at the university that I teach at, to use for assignments. It is an Apache Tomcat version 5.5.17 application server, on a Sun Sparc OS 5.10. Since this is an intro to dynamic web development class, the students do not deploy WAR files. Rather, they deploy their servlets and JSPs to a pre-created web application directory, under the tomcat "webapps" directory. When I created this directory, I did not change any Tomcat configuration files. I just created the root directory "classfiles", and the WEB-INF, classes, and lib directories.

The first problem was loading servlets. That one was an easy one. The web.xml file needs to tell Tomcat what to look for and how to load servlets. So, I made a basic web.xml file under the directory "classfiles/WEB-INF" that included the following code in it:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<servlet>
<servlet-name>invoker</servlet-name>
<servlet-class>
org.apache.catalina.servlets.InvokerServlet
</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>0</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>invoker</servlet-name>
<url-pattern>/servlet/*</url-pattern>
</servlet-mapping>
</web-app>
This tells tomcat to look for anything that has the /servlet/ in the user for the "classfiles" application and load it as a Servlet. For example: http://localhost:8080/classfiles/servlet/HelloWorldServlet

Easy enough, however, the dynamic reloading of the servlets wasn't happening. After looking through the documentation on the Tomcat site, I found out that Tomcat has to be explicitly notified about web applications, and if they should be reloadable. By default, if I was to use WAR file deployment, Tomcat would handle this automatically. Since this is not the case, I need to explicitly tell Tomcat what to do. This can be done either by modifying the server.xml file, in the tomcat "conf" directory. Or, to give me more direct control over the web application, and reduce the risk of accidentally screwing up someone else's context, I decided to make my own context configuration. This is done by creating a new directory under your web application directory called "META-INF". Then creating a file in there called "context.xml". Therefore, the contents of my file at "classfiles/META-INF/context.xml" was as follows:
<?xml version='1.0' encoding='utf-8'?>
<Context displayName="Software Engineering Student Projects"
reloadable="true">
</Context>
I am telling Tomcat to monitor the WEB-INF/classes and WEB-INF/lib directories for any changes. And WHAM, the servlets, packages, and other classes are now reloadable. But what about JSPs??? Am I missing something? Aren't JSPs just simple servlets? Well, yeah, sort of. It turns out that you need to set the docBase for the JSPs to reload. So now my context.xml file looks like this:
<?xml version='1.0' encoding='utf-8'?>
<Context displayName="Software Engineering Student Projects"
docBase="/usr/local/tomcat/classfiles" reloadable="true">
</Context>
And now my JSPs are reloading with no problems.

So the context.xml file can be used to make your pages, servlets, classes, and packages reloadable, if you are not using the default deployment capabilities of Tomcat. Tomcat does all this stuff automatically when deploying applications as a Web ARchive, WAR file. Is that it??

"But that is not all I can do" said the cat. Through research into the context.xml, and server.xml, files, you will find a ton of more capabilities that these files provide. Such as data sources, cross context sessions, and application level variables. But that is a post for another time.

For more information, check out the Tomcat documentation on configuring the Context container.

1 comment:

Unknown said...

Very helpful, especially with the docbase - thx