Starting Up Tomcat 6: Part 1

Exclusive offer: get 50% off this eBook here
Tomcat 6 Developer's Guide

Tomcat 6 Developer's Guide — Save 50%

Build better web applications by learning how a servlet container actually works.

$26.99    $13.50
by Damodar Chetty | December 2009 | Java Open Source

In this two-part article by Damodar Chetty, we look at how a Tomcat instance can be started using either the standard script-based mechanism or the alternative Run/Debug configuration. We look at the various class loader hierarchies that are set up during the initialization process. We also look at how the Apache Commons Digester library provides a convenient way of converting an XML file into a Java object graph. We end this article with an example of a web application that is deployed into our Tomcat instance.

Using scripts

The Tomcat startup scripts are found within your project under the bin folder. Each script is available either as a Windows batch file (.bat), or as a Unix shell script (.sh). The behavior of either variant is very similar, and so I'll focus on their general structure and responsibilities, rather than on any operating system differences. However, it is to be noted that the Unix scripts are often more readable than the Windows batch files.

In the following text, the specific extension has been omitted, and either .bat or .sh should be substituted as appropriate. Furthermore, while the Windows file separator '' has been used, it can be substituted with a '/' as appropriate.

The overall structure of the scripts is as shown—you will most often invoke the startup script.

 Tomcat 6 Developer's Guide

Note that the shutdown script has a similar call structure. However, given its simplicity, it lends itself to fairly easy investigation, and so I leave it as an exercise for the reader.

Both startup and shutdown are simple convenience wrappers for invoking the catalina script. For example, invoking startup.bat with no command line arguments calls catalina.bat with an argument of start. On the other hand, running shutdown.bat calls catalina.bat with a command line argument of stop. Any additional command line arguments that you pass to either of these scripts are passed right along to catalina.bat.

The startup script has the following three main goals:

  • If the CATALINA_HOME environment variable has not been set, it is set to the Tomcat installation's root folder. The Unix variant defers this action to the catalina script.
  • It looks for the catalina script within the CATALINA_HOMEbin folder. The Unix variant looks for it in the same folder as the startup script. If the catalina script cannot be located, we cannot proceed, and the script aborts.
  • It invokes the catalina script with the command line argument start followed by any other arguments supplied to the startup script.

The catalina script is the actual workhorse in this process. Its tasks can be broadly grouped into two categories. First, it must ensure that all the environment variables needed for it to function have been set up correctly, and second it must execute the main class file with the appropriate options.

Setting up the environment

In this step, the catalina script sets the CATALINA_HOME, CATALINA_BASE, and CATALINA_TMPDIR environment variables, sets variables to point to various Java executables, and updates the CLASSPATH variable to limit the repositories scanned by the System class loader.

  1. It ensures that the CATALINA_HOME environment variable is set appropriately. This is necessary because catalina can be called independently of the startup script.
  2. Next, it calls the setenv script to give you a chance to set any installation-specific environment variables that affect the processing of this script. This includes variables that set the path of your JDK or JRE installation, any Java runtime options that need to be used, and so on. If CATALINA_BASE is set, then the CATALINA_BASEbinsetenv script is called. Else, the version under CATALINA_HOME is used.
  3. If the CATALINA_HOMEbinsetclasspath does not exist, processing aborts. Else, the BASEDIR environment variable is set to CATALINA_HOME and the setclasspath script is invoked. This script performs the following activities:
    • It verifies that either a JDK or a JRE is available. If both the JAVA_HOME and JRE_HOME environment variables are not set, it aborts processing after warning the user.
    • If we are running Tomcat in debug mode, that is, if '–debug' has been specified as a command line argument, it verifies that a JDK (and not just a JRE) is available.
    • If the JAVA_ENDORSED_DIRS environment variable is not set, it is defaulted to BASEDIRendorsed. This variable is fed to the JVM as the value of the –Djava.endorsed.java.dirs system property.
    • The CLASSPATH is then truncated to point at just JAVA_HOMElibtools.jar. This is a key aspect of the startup process, as it ensures that any CLASSPATH set in your environment is now overridden.
      Note that tools.jar contains the classes needed to compile and run Java programs, and to support tools such as Javadoc and native2ascii. For instance, the class com.sun.tools.javac.main.Main that is found in tools.jar represents the javac compiler. A Java program could dynamically create a Java class file and then compile it using an instance of this compiler class.
    • Finally, variables are set to point to various Java executables, such as java, javaw (identical to java, but without an associated console window), jdb (the Java debugger), and javac (the Java compiler). These are referred to using the _RUNJAVA, _RUNJAVAW, _RUNJDB, and _RUNJAVAC environment variables respectively.
  4. The CLASSPATH is updated to also include CATALINA_HOMEbinbootstrap.jar, which contains the classes that are needed by Tomcat during the startup process. In particular, this includes the org.apache.catalina.startup.Bootstrap class. Note that including bootstrap.jar on the CLASSPATH also automatically includes commons-daemon.jar, tomcat-juli.jar, and tomcat-coyote.jar because the manifest file of bootstrap.jar lists these dependencies in its Class-Path attribute.
  5. If the JSSE_HOME environment variable is set, additional Java Secure Sockets Extension JARs are also appended to the CLASSPATH.

    Secure Sockets Layer (SSL) is a technology that allows clients and servers to communicate over a secured connection where all data transmissions are encrypted by the sender. SSL also allows clients and servers to determine whether the other party is indeed who they say they are, using certificates. The JSSE API allows Java programs to create and use SSL connections.

    Though this API began life as a standalone extension, the JSSE classes have been integrated into the JDK since Java 1.4.

  6. If the CATALINA_BASE variable is not set, it is defaulted to CATALINA_HOME. Similarly, if the Tomcat work directory location, CATALINA_TMPDIR is not specified, then it is set to CATALINA_BASEtemp. Finally, if the file CATALINA_BASEconflogging.properties exists, then additional logging related system properties are appended to the JAVA_OPTS environment variable.

All the CLASSPATH machinations described above have effectively limited the repository locations monitored by the System class loader. This is the class loader responsible for finding classes located on the CLASSPATH.

At this point, our execution environment has largely been validated and configured.

The script notifies the user of the current execution configuration by writing out the paths for CATALINA_BASE, CATALINA_HOME, and the CATALINA_TMPDIR to the console. If we are starting up Tomcat in debug mode, then the JAVA_HOME variable is also written, else the JRE_HOME is emitted instead.

These are the lines that we've grown accustomed to seeing when starting up Tomcat.

C:tomcatTOMCAT_6_0_20outputbuildbin>startup
Using CATALINA_BASE: C:tomcatTOMCAT_6_0_20outputbuild
Using CATALINA_HOME: C:tomcatTOMCAT_6_0_20outputbuild
Using CATALINA_TMPDIR: C:tomcatTOMCAT_6_0_20outputbuildtemp
Using JRE_HOME: C:javajdk1.6.0_14

With all this housekeeping done, the script is now ready to actually start the Tomcat instance.

Executing the requested command

This is where the actual action begins. This script can be invoked with the following commands:

  • debug [-security], which is used to start Catalina in a debugger
  • jpda start, which is used to start Catalina under a JPDA debugger
  • run [-security], which is used to start Catalina in the current window
  • start [-security], which starts Catalina in a separate window
  • stop, which is used to stop Catalina
  • version, which prints the version of Tomcat

The use of a security manager, as determined by the optional –security argument, is out of scope for this article.

The easiest way to understand this part of catalina.bat is to deconstruct the command line that is executed to start up the Tomcat instance.

This command takes this general form (all in one line):

_EXECJAVA
JAVA_OPTS
CATALINA_OPTS
JPDA_OPTS
DEBUG_OPTS
-Djava.endorsed.dirs="JAVA_ENDORSED_DIRS"
-classpath "CLASSPATH"
-Djava.security.manager
-Djava.security.policy=="SECURITY_POLICY_FILE"
-Dcatalina.base="CATALINA_BASE"
-Dcatalina.home="CATALINA_HOME"
-Djava.io.tmpdir="CATALINA_TMPDIR"
MAINCLASS
CMD_LINE_ARGS
ACTION

Where:

  • _EXECJAVA is the executable that should be used to execute our main class. This defaults to the Java application launcher, _RUNJAVA. However, if debug was supplied as a command-line argument to the script, this is set to _RUNJDB instead.
  • MAINCLASS is set to org.apache.catalina.startup.Bootstrap
  • ACTION defaults to start, but is set to stop if the Tomcat instance is being stopped.
  • CMD_LINE_ARGS are any arguments specified on the command line that follow the arguments that are consumed by catalina.
  • SECURITY_POLICY_FILE defaults to CATALINA_BASEconfcatalina.policy.
  • JAVA_OPTS and CATALINA_OPTS are used to carry arguments, such as maximum heap memory settings or system properties, which are intended for the Java launcher. The difference between the two is that CATALINA_OPTS is cleared out when catalina is invoked with the stop command. In addition, as indicated by its name, the latter is targeted primarily at options for running a Tomcat instance.
  • JPDA_OPTS sets the Java Platform Debugger Architecture (JPDA) options to support remote debugging of this Tomcat instance. The default options are set in the script. It chooses TCP/IP as the protocol used to connect to the debugger (transport=dt_socket), marks this JVM as a server application (server=y), sets the host and port number on which the server should listen for remote debugging requests (address=8000), and requires the application to run until the application encounters a breakpoint (suspend=n).
  • DEBUG_OPTS sets the -sourcepath flag when the Java Debugger is used to launch the Tomcat instance.
  • The other variables are set as seen in the previous section.
  • At this point, control passes to the main() method in Bootstrap.java. This is where the steps that are unique to script-based startup end. The rest of this article follows along with the logic coded into Bootstrap.java and Catalina.java.
Tomcat 6 Developer's Guide Build better web applications by learning how a servlet container actually works.
Published: December 2009
eBook Price: $26.99
Book Price: $44.99
See more
Select your format and quantity:

Setting up your project

Our Eclipse Run/Debug configuration directly invokes the main() method on the org.apache.catalina.startup.Bootstrap class. As is evident from its name, this class is responsible for starting up and initializing, or bootstrapping, Tomcat. This class exists as a single global singleton instance, there's a single static member named daemon, which is instantiated and initialized by the main() method. This instance holds references to three class loaders, and to an instance of the org.apache.catalina.startup.Catalina class, which serves as the primary means by which all the components that comprise Tomcat are assembled into a running whole.

The Catalina class extends org.apache.catalina.startup.Embedded, which you can use directly to embed a running Tomcat instance into any standard Java application that you might write. This class provides a programmatic means to setting up your own Tomcat instance.

The Bootstrap and Catalina classes that we discuss in this article simply provide a convenient means to do the same when running Tomcat in a traditional manner.

Modifying the Run/Debug configuration

In this section, we will modify the project that we setup to make it look more like a real world instance. First, ensure that you have built our project using Ant

Next, in the debug configuration that was set up to run Tomcat from within Eclipse, set the arguments for the JVM as shown (all in one line):

-Dcatalina.home="${project_loc}outputbuild"
-Dcatalina.base="${project_loc}outputbuild"

Tomcat 6 Developer's Guide

Next, limit your System class loader to only consider the following paths:

Tomcat 6 Developer's Guide

Finally, reattach your project source by setting the Source tab as shown:

Tomcat 6 Developer's Guide

Now, launch your Debug configuration.

What we have done here is to set up a configuration that runs Tomcat in a mode that is as close to a standard deployment as possible. However, you should note that any file that you modify and compile will not automatically make it to the output folder. As a result, rather than doing a standard Eclipse build, you will need to do an Ant build from within Eclipse. This will ensure that the outputbuild folders are updated with your changes, allowing them to be picked up by this Debug configuration.

Executing a Run configuration sometimes results in a cryptic message that claims the following:

Variable references empty selection: ${project_loc}

The workaround is fairly simple. Before you execute your configuration, ensure that the tomcat6 project has been selected in the Eclipse browser view.

Bootstrapping Tomcat

The bootstrapping process is actually rather simple. All we have to do is:

  • Set up the environment variables required by this Tomcat instance
  • Instantiate the general class loaders that will be used for our running Tomcat instance
  • Initialize this Tomcat instance
  • Parse the main configuration file for a Tomcat instance, server.xml, converting each configuration element into the appropriate Tomcat component
  • Start up our outermost Top Level Element—the Server instance
  • Set up a shutdown hook

In this section, we'll explore each aspect of this bootstrap process.

Bootstrapping environment variables

The first step is to set the CATALINA_HOME and CATALINA_BASE environment variables.

As we saw earlier, CATALINA_HOME identifies the location of the Tomcat binaries, whereas CATALINA_BASE sets the root location of a given running Tomcat instance. The reason for keeping these separate is to allow multiple Tomcat instances to be started (with independent configurations), while relying on a single set of binaries.

The catalina.bat startup script automatically obtains the values of the CATALINA_BASE and CATALINA_HOME environment variables, and then sets these as system properties for the JVM.

However, when starting the server using a debug configuration, these are empty, unless you have updated the JVM arguments as indicated in the previous section.

If these are uninitialized, Bootstrap determines the catalina.home system property from the user's current directory. It sets catalina.home to the user's current directory, unless the current directory contains a bootstrap.jar file, in which case, it is set to the parent folder of the user's current directory.

Next, if the catalina.base system property is not set, it is simply set to the catalina.home property.

Bootstrapping class loading

Remember that unlike a typical execution scenario, where the System class loader is responsible for loading all the classes found on the classpath, the startup process has neutered our System class loader so that it is able to only locate startup or utility classes.

Instead, the burden of finding Tomcat implementation classes, as well as common libraries that are used across all web applications, is handled by a separate hierarchy of three class loaders that are initialized by the bootstrap process.

Our Bootstrap instance holds references to the following three class loaders:

  • commonLoader, which loads classes that are common across Tomcat, as well as all the web applications.
  • catalinaLoader, or serverLoader, which loads classes that are used just by Tomcat.
  • sharedLoader, which loads classes that are common just across all the web applications within a Tomcat instance.

The sharedLoader is the ideal place to place common JAR files, rather than placing them in the WEB-INFlib of each web application in a Tomcat instance.

The repositories watched by each of these class loaders are defined in the catalina.properties file that is located in the CATALINA_BASE/conf folder. This file is read in by the org.apache.catalina.startup.CatalinaProperties class, which converts the entries into system properties.

This file has one property key per class loader. The common.loader key defaults to ${catalina_home}/lib,${catalina_home}/lib/*.jar, whereas the server.loader and shared.loader keys are both left empty. These properties point to repository locations that define the locations from where a class loader will load its classes.

Valid repository locations for a class loader may be:

  • A URL location with a known protocol, usually a directory in which .class files can be found, such as ${catalina_home}/lib
  • A single JAR file
  • A directory that contains JAR files, where the individual JAR files need to be added to the list of repository locations, such as ${catalina_home}/lib/*.jar

This information is converted by the static createClassLoader() method of org.apache.catalina.startup.ClassLoaderFactory into a class loader that monitors these repositories. This class loader is an instance of org.apache.catalina.Loader.StandardClassLoader.

This method verifies that the specified repositories exist and that they can be accessed. Wildcard-based repository locations are expanded into individual file names. These file paths are converted into URLs with a file: protocol (such as file:/C:/tomcat/TOMCAT_6_0_20/output/build/lib/).

The StandardClassLoader is a subclass of java.net.URLClassLoader, and there are no real functional differences between these two classes. The commonLoader is created with the System class loader as its parent. The serverLoader and sharedLoader class loaders are created with the commonLoader as their parent.

The serverLoader and sharedLoader class loaders are not instantiated if the server.loader and shared.loader properties are empty, respectively, in catalina.properties. In this case, both of these loaders are simply set to reference the commonLoader itself.

The general class loader model can thus be depicted as follows:

Tomcat 6 Developer's Guide

The grayed out class loaders indicate that the serverLoader and sharedLoader loaders are optional. If they are omitted, the Tomcat code as well as the individual web application class loaders directly delegate to the commonLoader.

The serverLoader (or the commonLoader, when there is no serverLoader instantiated) is set up as the context class loader for the current thread.

A context class loader is set as a ThreadLocal variable in the current thread, and provides a convenient mechanism for the Java EE container to propagate an appropriate class loader that can be used by class loaders higher in the hierarchy to load Tomcat related classes.

This is done to solve the class loader inversion problem that occurs often in the Java EE world. Here, classes from an API (such as the JDBC API) are often loaded by class loaders high up in the delegation hierarchy—such as the Bootstrap loader. Code within such an API class often needs to work with implementation classes (such as a JDBC driver) that are provided by some service provider, and whose names are exposed to the API class either through system properties or configuration files. The problem is that these implementation classes are often not visible to the higher class loader.

When code within the API class must load an implementation class, it simply delegates the task to the context class loader found in the current thread. This context class loader is set by the container to a class loader that can load the Tomcat server's code (either the serverLoader or the commonLoader). This context class loader is low enough in the hierarchy to be able to see the appropriate implementation classes.

In the next part we will cover bootstrapping the embedded container, Commons Digester, the server.xml Digester, parsing the server.xml file, initializing the server and adding a new web application to Tomcat in Eclipse.

>> Continue Reading: Starting Up Tomcat 6 - Part 2

[ 1 | 2 ]

If you have read this article you may be interested to view :

Tomcat 6 Developer's Guide Build better web applications by learning how a servlet container actually works.
Published: December 2009
eBook Price: $26.99
Book Price: $44.99
See more
Select your format and quantity:

About the Author :


Damodar Chetty

Damodar Chetty is a lifelong programmer with almost two decades in the computer software industry. He cut his teeth on assembler and BASIC programming, and has journeyed through FORTRAN, COBOL, Visual Basic, C++, and Java. Along the way he has stubbed his toes often enough to develop a keen sense of where dragons lie. He is currently an independent consultant at Software Engineering Solutions, Inc. doing what he loves most – building high quality software.

Damodar has a degree in Electronics & Telecommunications engineering from the University of Bombay, and higher degrees in Management Sciences from the University of Goa, and in Computer Engineering from the University of Minnesota.

He currently lives in Woodbury, Minnesota with his wife, Devi, and his children, Ashwin and Anita.

Books From Packt

Apache Geronimo 2.1: Quick Reference
Apache Geronimo 2.1: Quick Reference

JBoss AS 5 Development
JBoss AS 5 Development

GlassFish Administration
GlassFish Administration

MooTools 1.2 Beginner's Guide
MooTools 1.2 Beginner's Guide

JSF 1.2 Components
JSF 1.2 Components

jBPM Developer Guide
jBPM Developer Guide

Spring Persistence with Hibernate
Spring Persistence with Hibernate

Apache Roller 4.0 – Beginner's Guide
Apache Roller 4.0 Beginner's Guide

No votes yet

Post new comment

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
d
N
G
M
G
Z
Enter the code without spaces and pay attention to upper/lower case.
Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software