Published on ONJava.com (http://www.onjava.com/)
 See this if you're having trouble printing code examples

Using Tomcat Configuring Tomcat and Apache With JK 1.2

by James Goodwill

In an earlier article, I promised to demystify Tomcat's server.xml file. Now, I'd like to advance the discussion with an in-depth look at the JK modules. This is the first of five articles addressing JK. Here's a preview of the whole series:

  1. Configuring Tomcat and Apache using JK v1.2
  2. Configuring Tomcat and IIS using JK v1.2
  3. Configuring Tomcat and Apache using JK v2
  4. Configuring Tomcat and IIS using JK v2
  5. Advanced Connector Configurations

What is JK v1.2?

In the simplest terms, the JK modules, or mod_jk, are conduits between a Web server and the Tomcat JSP/servlet container. They replace the previous Web server module, mod_jserv, which had many shortcomings. The new JK modules include support for a wider variety of Web servers, better SSL support, support of the AJP13 protocol, and support for the entire Tomcat series from 3.2.x to 5.x.

Preparing Your Environment

Before we can continue with our discussions, you must get all of the components required to configure Tomcat and Apache. The following lists these components and their current locations.

AJP 13

The AJP 13 protocol is a packet-based protocol that allows a Web server to communicate with the Tomcat JSP/servlet container over a TCP connection. For our purposes, all that we need to know is that AJP13 is a more efficient protocol and includes better support for SSL than its predecessors. Further information on AJP13 is available at http://jakarta.apache.org/tomcat/tomcat-4.1-doc/jk2/common/AJPv13.html.

Make sure that you download the appropriate binary for your operating system. You can download the source for each of these components, but we will not be covering the building of any of them. Once you have downloaded all of the components listed above, complete the following steps:

  1. Install Apache as described in its packaged documentation.

  2. Test the Apache installation, by starting Apache and opening your browser to http://localhost. You should now see an image similar to Figure 1.

    Figure 1. The Apache Installation Test Page

  3. Install Tomcat as described by its documentation.

  4. Set the environment variable JAVA_HOME equal to the root directory of your JDK installation.

  5. Set the environment variable CATALINA_HOME equal to the root directory of you Tomcat installation.

  6. Test the Tomcat installation by starting Tomcat and opening your browser to http://localhost:8080. You should now see an image similar to Figure 2.

    Figure 2. The Tomcat Default Homepage

  7. Now shut down both Apache and Tomcat, before moving on to the next sections.

Configuring Tomcat and Apache With the JK 1.2 Connector

It is now time to begin the actual integration between Apache and Tomcat. This process can be broken down into two sections: configuring Tomcat and configuring Apache.

Configuring Tomcat

To begin our Tomcat and Apache integration, we need to first tell Tomcat that it should start listening for AJP13 requests; both JK and JK2 use AJP13 to communicate with Tomcat. To do this, we need to add an additional <Connector> element to Tomcat's server.xml file. Add the following entry to server.xml, making sure that it is inside of the <Service> element and immediately follows any previously-defined <Connector> elements.

<Connector className="org.apache.ajp.tomcat4.Ajp13Connector"
port="8009" minProcessors="5" maxProcessors="75"
acceptCount="10" debug="0"/>

The only two attributes in this <Connector> worth noting are the port and className attributes. The port attribute tells Tomcat that it needs to open a new Connector that listens to port 8009 for incoming requests. The className attribute tells Tomcat that all of the requests coming in on this port should be serviced by the Tomcat Connector class org.apache.ajp.tomcat4.Ajp13Connector, which also uses the AJP 1.3 protocol. (If you have further questions about Tomcat Connectors, you can refer to "Demystifying Tomcat's server.xml File.") This completes the Tomcat configuration.

Configuring Apache

Now that Tomcat is configured to listen to port 8009 for incoming AJP13 request, let's tell Apache to actually talk to Tomcat using that port and protocol. This process, while not terribly complicated, is somewhat more complicated than Tomcat's equivalent configuration, so I have broken it down into several sections.

Create a Tomcat Worker

We begin the Apache configuration by creating a Tomcat worker definition that will tell Apache how and when to talk to Tomcat. This is done by creating a Tomcat worker file, containing the definition for at least one Tomcat worker. A Tomcat worker is a process that defines a communications link between Apache and a Tomcat container. (If you have any questions about Tomcat Workers, you can refer to the actual Jakarta documentation.) We will cover Tomcat workers in much more detail when we get to Part 5 of this series, "Advanced Connector Configurations."

The Tomcat worker file, in this example, should be named workers.properties and should be copied into the <CATALINA_HOME>/conf directory of the Tomcat instance that you will be integrating with Apache. (<CATALINA_HOME> represents the base directory of your Tomcat installation.)

Now add the following properties to this newly-created file and save your changes.


Related Reading

Apache: The Definitive Guide
By Ben Laurie, Peter Laurie

These entries define a Tomcat worker named testWorker that resides on the same host as the Apache server, localhost, and listens to port 8009 for a client using the AJP13 protocol. This is accomplished using a series of worker properties.

The first of these properties is the worker.list property. This property defines a list of Tomcat workers to which our instance of Apache will talk. This list can define any number of Tomcat workers as long as each name is separated with a comma.

(Note that all of the worker properties are prepended by the string worker. This string acts the top-level identifier of all worker properties.)

In our example we are defining a single worker named testWorker. Once we have a worker named, we can then modify the attributes of that worker explicitly using the following syntax:

worker.testWorker + name of property being modified

Because our current example is so simple, we are only going to modify three of the new workers properties: port, host, and type. All of these are easy enough to decipher, but for clarity's sake, they are still described in the following table.

Property Use
<workername>.port The port property defines the port number of this Tomcat worker. This value must match the port attribute of the previously defined Tomcat <Connector> element.
<workername>.host The host property defines the hostname of this Tomcat worker. Because we are configuring both Apache and Tomcat on the same host, this value is currently set to localhost.
<workername>.type The type property defines the protocol of this Tomcat worker, which in our case is ajp13.

Modify Apache's httpd.conf Configuration File

Now that we have defined a Tomcat worker, we need to tell Apache to talk to that worker. We do this by making several modifications to Apache's <APACHE_HOME>/conf/httpd.conf file. This process is broken down into several steps:

  1. Copy the previously downloaded mod_jk module to the <APACHE_HOME>/libexec directory.

  2. Tell Apache to load the mod_jk module. We do this by adding the LoadModule and AddModule directives to the bottom of the httpd.conf file, as follows:

    LoadModule jk_module libexec/mod_jk-1.3.26.dll
    AddModule mod_jk.c

    Note: If your OS is a flavor of Unix, then you will most likely be pointing at the file mod_jk-1.3-eapi.so. If you are on a Windows box, which is what I am currently using, then you will most likely be pointing to the file mod_jk-1.3.26.dll.

  3. We must now tell mod_jk the location of our workers.properties file. This is done by using the JkWorkersFile property. Make sure you use the appropriate path when defining the location of your properties file.

    JkWorkersFile C:/Tomcat4_1_12/conf/workers.properties
  4. Our next step is an optional but very useful (when you run into problems) step: naming a log file that will record mod_jk's actions. You do this by adding two additional properties to the httpd.conf file. The first of these properties, JkLogFile, identifies the location of the log file. The second, JkLogLevel, defines the logging level, which can be one of three logging levels: debug, error, or info, which decrease in level of verbosity, respectively.

    Note: If you do not define a log level, then no log file will be generated.

    JkLogFile C:/Tomcat4_1_12/logs/mod_jk.log 
    JkLogLevel debug
  5. The next step is to tell Apache that we want all static content requested from the /examples directory to be served from the <CATALINA_HOME>/webapps/examples directory. This is accomplished using the Alias directive, as follows:

    Alias /examples C:/Tomcat4_1_12/webapps/examples
  6. We now need to tell Apache that we want all requests with the patterns /examples/servlet/* and /examples/*.jsp to be rerouted and serviced by the worker named testWorker. This is accomplished using the JkMount directive, as follows.

    JkMount /examples/servlet/* testWorker 
    JkMount /examples/*.jsp testWorker
  7. The final step in our Apache/Tomcat integration is a step that restricts all requests to the /example application's WEB-INF directory. This is done by telling Apache that it should deny all requests to the /examples/WEB-INF directory. The following <Location> element enforces this constraint:

    <location "/examples/web-inf/">
    AllowOverride None 
    deny from all 

When all of these changes are made, you should have an addition similar to the following, with appropriate path changes, at the bottom of Apache's httpd.conf file.

LoadModule jk_module libexec/mod_jk-1.3.26.dll
AddModule mod_jk.c 
JkWorkersFile C:/Tomcat4_1_12/conf/workers.properties
JkLogFile C:/Tomcat4_1_12/logs/mod_jk.log 
JkLogLevel debug 
Alias /examples C:/Tomcat4_1_12/webapps/examples 
JkMount /examples/servlet/* testWorker 
JkMount /examples/*.jsp testWorker 
<Location "/examples/WEB-INF/">
AllowOverride None 
deny from all 

What Have We Done?

As I mentioned in the previous section, the mod_jk modules act like conduits between a Web server (Apache, for our purposes) and Tomcat. In the last two sections, we basically installed and configured this conduit. Now Apache performs in the following manner:

On Apache Startup:

  1. Apache loads the mod_jk module.
  2. It then tells the mod_jk module that all of its workers are defined in the worker.properties file, which in our case defines a single worker, testWorker.
  3. Apache then associates all requests for the patterns /examples/servlet/* and /example/*.jsp with the worker testWorker.

When a request, including either of the patterns /examples/servlet/* or /example/*.jsp, is received:

  1. Apache will turn the request over to the mod_jk module.
  2. mod_jk will then pass the request to the Tomcat Connector org.apache.ajp.tomcat4.Ajp13Connector, which is listening on port 8009.
  3. This Connector then takes over and services the request as if it were running inside the Tomcat container.
  4. When the request has been serviced, the org.apache.ajp.tomcat4.Ajp13Connector will return the results back to the mod_jk module and control will be shifted back to Apache.

Testing Your New Configuration

At this point, you can now test your changes. To do this you must first start Tomcat and then start the Apache server. When both servers are up and running, open your browser to either http://localhost/examples/servlets/index.html or http://localhost/examples/jsp/index.html and browse around, testing your new integration.

That about does it for a basic Apache/Tomcat configuration. Do note that all requests to the /examples application are no longer using localhost:8080, but are instead using localhost. This is because Tomcat is listening to port 8080, while Apache is servicing requests using the default port of 80, which is being served by Apache.

Up Next: Next time, I'll take another look at server.xml while we configure Tomcat to receive requests from Microsoft's Internet Information Server (IIS).

James Goodwill is the co-Founder of Virtuas Solutions, LLC, a Colorado-based software consultancy.

Read more Using Tomcat columns.

Return to ONJava.com.

Copyright © 2009 O'Reilly Media, Inc.