Tomcat

Connecting Apache to Java With mod_jk (on Windows)

Virtually all J2EE servlet containers come bundled with an HTTP server, and setting one of them up is usually very simple. Despite the conveniece, I've found many reasons not to use these bundled HTTP servers in even a development/testing environment. In production, the decision is simple: the Apache HTTPD server is faster, more stable, more secure, more configurable and more powerful than any bundled HTTP server. In development and testing, I've found the configurability of Apache to be an enormous asset, offsetting the additional challenge of using mod_jk to link Apache and the servlet container.

Downloading mod_jk

The mod_jk package is closely connected to the development of Jakarta Tomcat, and can be downloaded most easily by finding a tomcat mirror site. From the Tomcat site, make your way to a download mirror (via the download links), and then browse to jakarta/tomcat-connectors/jk/binaries/ once inside the mirror (paths may be slightly different due to mirror uniquenesses). From the binaries directory for your platform, download the newest version of mod_jk that matches your Apache version. Note that there are separate packages for the Apache 1.x and 2.x release cycles.

Placing the Module

After downloading the .so file, you'll need to place it in your Apache modules directory. Rename the file mod_jk.so and place it in %APACHE_ROOT%/modules.

Notifying Apache

Create a file d:/www-config/mod_jk-apache.conf, and place the following statements in it.



LoadModule jk_module "modules/mod_jk.so"

JkWorkersFile "d:/www-config/mod_jk-workers.properties"
JkLogFile "d:/www-logs/mod_jk.log"
JkLogLevel warn

#
# Standard mod_jk mappings
#
JkMount /*.jsp java1
JkMount /servlet/* java1
JkUnMount /servlet/*.gif java1

That file is imported using the Apache configuration recommended in another post, where Apache's httpd.conf includes all .conf files in d:/www-config. Note: the documentation for mod_jk directives is available.

The workers.properties file referenced above is a listing of "workers" (instances of a Java servlet container). Create the file d:/www-config/mod_jk-workers.properties.


worker.list=java1

worker.java1.port 8009
worker.java1.host localhost
worker.java1.type ajp13

The complete chain works like this: 1) The Apache JkMount and JkUnmount directives tell Apache which request patterns to forward on to the servlet container by its "worker" name. 2) The servlet container with the worker name in question receives the request as if it came directly from the client computer. 3) The servlet container's response is retrieved by Apache and returned to the end user. The trick is that only portions of the hosting tree are mapped to Java. Ideally, static HTML, Javascript, CSS and images are handled by Apache directly, without having to consult the servlet container.

Connecting IIS to Java Application Servers

The Apache Software Foundation's Tomcat servlet container was developed with an external module to connect it to other web servers using a protocol called AJP. The code is implemented in a project called JK. It is often referred to as mod_jk, because that's the name of the Apache HTTPD module. For some reason, the implementation for IIS is called ISAPI_Redirect.

The connection between IIS and Tomcat (or any of the numerous other servlet containers that have implemented AJP receivers to work with JK) is relatively simple. The JK DLL is installed into IIS as a filter + extension. It is configured to activate itself on certain URL patterns. For those patterns that match, the DLL sends an AJP packet to the servlet containers (called "workers") that have been configured. Assuming the servlet container has an AJP listener turned on, it then responds with the content of the response.

Note: Communication via AJP can be configured to happen on any port. By default, the port is 8009. AJP is not a secure protocol, so this port should be limited to communication between internal servers. Port 8009 should not be open on the external firewall.

Installation

First, download the JK 1.X Win32 binary from the an Apache mirror:
http://jakarta.apache.org/site/downloads/downloads_tomcat-connectors.cgi

If using IIS 5 or newer, download the isapi_redirect-1.x.exe. The EXE installer is the most convenient installation method.

The installer places all its files in C:\Program Files\Apache Software Foundation\Jakarta Isapi Redirector\. Example (usable) configuration files are placed in the conf subdirectory.

Registry configuration is also set up at HKEY_LOCAL_MACHINE\SOFTWARE\Apache Software Foundation\Jakarta Isapi Redirector\1.0. The registry keys point the ISAPI dll to the configuration files in C:\Program Files\Apache Software Foundation\Jakarta Isapi Redirector\conf.

You'll also find a new Virtual Directory, called jakarta in the IIS Web Site configuration window. This directory is needed to forward the requests on to the application server, although it will not be present in your site's URLs.

Setting up a Context

To set up a context (an application hosted in a subdirectory of the site), you need to edit the
uriworkermap.properties file in the installation folder. This file maps URLs to workers. A "worker" is an instance of Tomcat, Jetty or another application server that supports the AJP protocol. The term more accurately applies when mod_jk is used in a load balancing environment.

The uriworkermap.properties simply identifies URL patterns that should be forwarded to an application server. The URL will not be changed in the process, so IIS mapped URLs must be identical to the context/URL configuration of the application server.

For example, assume we have applications (contexts) called accounting, intranet, and development set up in Tomcat. When using Tomcat's own HTTP, the URL for the accounting application woudl be http://localhost:8080/accounting. To set up this application to be accessed through IIS, we'd modify uriworkermap.properties like so:


/accounting/*=ajp13w

In this case, ajp13w identifies the name of the Tomcat worker. The name ajp13w is the name of the default installation worker (which will likely be configured correctly if IIS and Tomcat and IIS are on the same server). The mapping indicates that all requests to the accounting subdirectory be sent to Tomcat.

Note: You'll need to restart IIS to get the new URL mappings to activate.

Division of Labor

You may want to divide responsibilities so that IIS handles static files, and only dynamic content is served by the underlying application server. This is typically done by unmapping certain file extensions in the uriworkermap.properties file. Unmap directives are identical to mapping ones, with an added ! as the first character.


!/accounting/*.jpg=ajp13w
!/accounting/*.gif=ajp13w
!/accounting/*.png=ajp13w
!/accounting/static/*=ajp13w

The above directives would cause mod_jk to not forward JPG, GIF and PNG requests for the accounting context. It also causes the entire static subdirectory to be ignored by mod_jk as well.

Now to make sure IIS knows where to find these files, we'll need to set up a Virtual Directory where these files can be found. In this case, we'll set up an IIS Virtual Directory called accounting (it must be the same as the context). We'll point that virtual directory to the same one that hosts the application server files.

HTTP Authentication

In many cases, you'll want the application server to continue to manage authentication. This setup is more portable (the same username database will be used on any web server), and it saves the effort of configuring usernames and passwords through Windows or IIS.

If your application uses HTTP Digest or Basic authentication, you'll need some special configuration, as IIS will normally try to hijack the application servers authentication attempts.

By default, the jakarta Virtual Directory has its own Directory Security settings turned on (Integrated Windows authentication is enabled, I believe). If you want authentication to be handled by the application server, you'll need to turn off all but Anonymous access in the Directory Security tab for the jakarta Virtual Directory. The same applies to context Virtual Directories if you're using them.