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:
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.
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.
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:
Install Apache as described in its packaged documentation.
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
Install Tomcat as described by its documentation.
Set the environment variable
JAVA_HOME equal to the root directory of your JDK installation.
Set the environment variable
CATALINA_HOME equal to the root directory of you Tomcat installation.
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
Now shut down both Apache and Tomcat, before moving on to the next sections.
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.
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 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
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.
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.
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.
worker.list=testWorker worker.testWorker.port=8009 worker.testWorker.host=localhost worker.testWorker.type=ajp13
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:
type. All of these are easy enough to decipher, but for clarity's sake, they are still described in the following table.
||The port property defines the port number of this Tomcat worker. This value must match the port attribute of the previously defined Tomcat
||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.|
||The type property defines the protocol of this Tomcat worker, which in our case is
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:
Copy the previously downloaded
mod_jk module to the <APACHE_HOME>/libexec directory.
Tell Apache to load the
mod_jk module. We do this by adding the
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.
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.
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:
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
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
We now need to tell Apache that we want all requests with the patterns
/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
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 </location>
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 </Location>
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:
mod_jkmodule that all of its workers are defined in the worker.properties file, which in our case defines a single worker,
/example/*.jspwith the worker
When a request, including either of the patterns
/example/*.jsp, is received:
mod_jkwill then pass the request to the Tomcat Connector
org.apache.ajp.tomcat4.Ajp13Connector, which is listening on port 8009.
org.apache.ajp.tomcat4.Ajp13Connectorwill return the results back to the
mod_jkmodule and control will be shifted back to Apache.
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.