I had to configure a Windows server with Apache, Tomcat, and MySQL in order to host a number of Clearspace instances. Each instance resides on its own subdomain. For instance, we have one Clearspace instance on cma.somedomain.com and another on cts.somedomain.com. I also had the requirement to make each Tomcat instance easily identifiable in the process list.
For this installation I grabbed
- Apache 2.2.9
- Tomcat 6.0.16
- mod_jk 1.2.26
- MySQL Java connector 5.1.6
The J2sdk 1.6.0_07 had already been loaded on the machine. Here is a reason to load the SDK instead of the JRE. The JAVA_HOME environment variable is required to start Tomcat, so add the entry and point it to the root of your Java install, i.e. C:\Program Files\Java\jdk1.6.0_06.
First, I installed MySQL 5.x on the server. No issues there. I used the Windows installer with MySQL running as a service.
On to Tomcat. Tomcat can host multiple instances of itself under one install. As one of my requirements was to make each instance appear as a separate and uniquely named process I chose to install separate complete instances of Tomcat. To identify the different Tomcat installation directories create a directory for each instance with the naming convention X:\tomcat-subdomain.

Tomcat Directory Structure
Copy the MySQL Java connector into tomcat\lib.

MySQL Java Connector
Next setup a CATALINA_HOME environment variable for each instance of Tomcat. Point the variable to the root of the directory just created. The naming convention I used is CATALINA_HOME_SUBDOMAIN.

Tomcat Environment Variables
Each Tomcat instance will need to use a unique set of ports to communicate. Modify X:\tomcat-installdir\conf\server.xml to set the ports. You’ll want each server to listen on its own port, so modify the server port accordingly. I incremented ports by 100 where possible for each instance, so my first instance runs on port 8005, my second instance runs on 8105, etc.

Tomcat Server Port
Tomcat contains its own web server, so modify the HTTP port.

Tomcat HTTP Port
And most importantly, the AJP port. The AJP port is the Apache port for forwarding requests. This port will ensure that Apache and Tomcat can talk to each other.

Tomcat AJP Port
Next, modify the bat files so they refer to the current Tomcat instance. To do this, after the opening comments in each file set CATALINA_HOME to the correct HOME environment variable like this
rem rem $Id: catalina.bat 615987 2008-01-28 18:48:10Z rjung $ rem ---------------------------------------------- set CATALINA_HOME=%CATALINA_HOME_CMA%
Do this for each instance in the following bat files in X:\tomcat-subdomain\bin\
- catalina.bat
- digest.bat
- shutdown.bat
- startup.bat
- tool-wrapper.bat
- version.bat
Now, make sure each instance of Tomcat appears as its own identifiable process in the process list. Rename the Tomcat EXEs to something identifiable in the process list. I followed my convention of tomcat-subdomain.

Tomcat EXEs
Then modify service.bat to reflect the changes. You’ll see ***MODIFY THIS LINE*** where you need to make modifications.
@echo off if "%OS%" == "Windows_NT" setlocal rem ******************** rem ***MODIFY THIS LINE*** rem ******************** set CATALINA_HOME=%CATALINA_HOME_CMA% rem ******************** rem Guess CATALINA_HOME if not defined set CURRENT_DIR=%cd% if not "%CATALINA_HOME%" == "" goto gotHome set CATALINA_HOME=%cd% rem ******************** rem ***MODIFY THIS LINE*** rem ******************** if exist "%CATALINA_HOME%\bin\tomcat-cma.exe" goto okHome rem ******************** rem CD to the upper dir cd .. set CATALINA_HOME=%cd% :gotHome rem ******************** rem ***MODIFY THIS LINE*** rem ******************** if exist "%CATALINA_HOME%\bin\tomcat-cma.exe" goto okHome rem ******************** echo The tomcat.exe was not found... echo The CATALINA_HOME environment variable is not defined correctly. echo This environment variable is needed to run this program goto end rem Make sure prerequisite environment variables are set if not "%JAVA_HOME%" == "" goto okHome echo The JAVA_HOME environment variable is not defined echo This environment variable is needed to run this program goto end :okHome if not "%CATALINA_BASE%" == "" goto gotBase set CATALINA_BASE=%CATALINA_HOME% :gotBase rem ******************** rem ***MODIFY THIS LINE*** rem ******************** set EXECUTABLE=%CATALINA_HOME%\bin\tomcat-cma.exe rem ******************** rem Set default Service name rem ******************** rem ***MODIFY THESE LINES*** rem ******************** set SERVICE_NAME=TomcatCMA set PR_DISPLAYNAME=Apache Tomcat CMA rem ******************** if "%1" == "" goto displayUsage if "%2" == "" goto setServiceName set SERVICE_NAME=%2 rem ******************** rem ***MODIFY THIS LINE*** rem ******************** set PR_DISPLAYNAME=Apache Tomcat CMA rem ******************** :setServiceName if %1 == install goto doInstall if %1 == remove goto doRemove if %1 == uninstall goto doRemove echo Unknown parameter "%1" :displayUsage echo. echo Usage: service.bat install/remove [service_name] goto end :doRemove rem Remove the service "%EXECUTABLE%" //DS//%SERVICE_NAME% echo The service '%SERVICE_NAME%' has been removed goto end :doInstall rem Install the service echo Installing the service '%SERVICE_NAME%' ... echo Using CATALINA_HOME: %CATALINA_HOME% echo Using CATALINA_BASE: %CATALINA_BASE% echo Using JAVA_HOME: %JAVA_HOME% rem Use the environment variables as an example rem Each command line option is prefixed with PR_ rem ******************** rem ***MODIFY THIS LINE*** rem ******************** set PR_DESCRIPTION=Apache Tomcat Server CMA - http://tomcat.apache.org/ rem ******************** set PR_INSTALL=%EXECUTABLE% set PR_LOGPATH=%CATALINA_BASE%\logs set PR_CLASSPATH=%CATALINA_HOME%\bin\bootstrap.jar rem Set the server jvm from JAVA_HOME set PR_JVM=%JAVA_HOME%\jre\bin\server\jvm.dll if exist "%PR_JVM%" goto foundJvm rem Set the client jvm from JAVA_HOME set PR_JVM=%JAVA_HOME%\jre\bin\client\jvm.dll if exist "%PR_JVM%" goto foundJvm set PR_JVM=auto :foundJvm echo Using JVM: %PR_JVM% "%EXECUTABLE%" //IS//%SERVICE_NAME% --StartClass org.apache.catalina.startup.Bootstrap --StopClass org.apache.catalina.startup.Bootstrap --StartParams start --StopParams stop if not errorlevel 1 goto installed echo Failed installing '%SERVICE_NAME%' service goto end :installed rem Clear the environment variables. They are not needed any more. rem ******************** rem ***MODIFY THIS LINE*** rem ******************** set PR_DISPLAYNAME=Apache Tomcat CMA rem ******************** set PR_DESCRIPTION= set PR_INSTALL= set PR_LOGPATH= set PR_CLASSPATH= set PR_JVM= rem Set extra parameters "%EXECUTABLE%" //US//%SERVICE_NAME% --JvmOptions "-Dcatalina.base=%CATALINA_BASE%;-Dcatalina.home=%CATALINA_HOME%;-Djava.endorsed.dirs=%CATALINA_HOME%\endorsed" --StartMode jvm --StopMode jvm rem More extra parameters set PR_LOGPATH=%CATALINA_BASE%\logs set PR_STDOUTPUT=auto set PR_STDERROR=auto "%EXECUTABLE%" //US//%SERVICE_NAME% ++JvmOptions "-Djava.io.tmpdir=%CATALINA_BASE%\temp;-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager;-Djava.util.logging.config.file=%CATALINA_BASE%\conf\logging.properties" --JvmMs 128 --JvmMx 256 echo The service '%SERVICE_NAME%' has been installed. :end cd %CURRENT_DIR%
Next, modify X:\tomcat-subdomain\conf\tomcat-users.xml to add the manager credentials.
<?xml version='1.0' encoding='utf-8'?> <tomcat-users> <role rolename="manager"/> <user username="tomcat" password="securePa$$word" roles="manager"/> </tomcat-users>
Now run service.bat to install this instance of Tomcat as a service.
x:\tomcat-subdomain\bin\service.bat
Open Windows services and modify the service to run automatically.

Tomcat Services
Start your Tomcat service. Each instance of Tomcat should serve files now. You can test this by navigating to Tomcat on the open port like http://somedomain:8180. Each Tomcat instance is easily identifiable in the server’s process list.

Tomcat Process List
Next, I installed Apache 2.2.9 using the windows installer. This was pretty straightforward. Now to configure Apache to communicate with Tomcat.
Rename mod_jk-1.2.26-httpd-2.2.4.so to mod_jk.so and copy it into the Apache modules directory.

Apache mod_jk
Modify httpd.conf to recognize mod_jk.

Apache httpd.conf
Add a line to load mod_jk in the modules section.
LoadModule jk_module modules/mod_jk.so
Now configure mod_jk to work with Tomcat. Mod_jk requires a workers.properties configuration file that defines how Apache should communicate with each Tomcat worker. Right after the mod_jk LoadModule line in httpd.conf, add a line to tell Apache where to find workers.properties. I also found logging mod_jk output helpful when debugging issues. I added lines to configure logging.
JkWorkersFile conf/workers.properties JkLogFile "C:/Apache/logs/mod_jk.log" JkLogLevel info
workers.properties looks something like this
worker.list = cts,cma,lucrumtesting # cts worker worker.cts.type=ajp13 worker.cts.host=localhost worker.cts.port=8209 # cma worker worker.cma.type=ajp13 worker.cma.host=localhost worker.cma.port=8409 # lucrumtesting worker worker.lucrumtesting.type=ajp13 worker.lucrumtesting.host=localhost worker.lucrumtesting.port=8309
The first line in workers.properties is the worker.list. The worker.list is a comma-separated list that defines which workers Apache should pay attention to. You may have additional worker configurations in the workers.properties file that do not appear in worker.list. These additional workers are ignored. Apache only uses the workers identified in the worker.list.
The remaining values tell Apache to use AJP to connect to the Tomcat instance along with the servername and the AJP port we defined in the Tomcat server.xml files earlier.
Finally, Apache needs to know about each Tomcat instance. We accomplished this by configuring a virtual host for each Tomcat instance.
ServerName cts.lucrumclearspace.com
JkMount /* cts
ServerName cma.lucrumclearspace.com
JkMount /* cma
ServerName lucrumtesting.lucrumclearspace.com
JkMount /* lucrumtesting
JkMount tells Apache how to map to each Tomcat worker instance as an Apache virtual host.
That’s it in terms of getting the configuration working. One final step included a redirect as I could not resolve, say, cma.somedomain. My browser continued to redirect to cma.somedomain/cma. We replaced the Tomcat default document with a redirect to cma.somedomain, and we were done.
I am not a Java app server expert by any means, so please feel free to comment if there are better ways to accomplish some of this. I’m guessing that my redirect is a kludge that someone could recommend alternatives to.
- Andy

Nice dude
Dude, you are a life-saver! Excellent article!