[NetMesh Developer's Site Logo]
COMPANY
CONTACT

Installing the Apache / Tomcat Connector

There's very little usable information on the web on how to use the Apache HTTP server as the frontend to Tomcat. The information we found seems to be out of date, incomplete, and in some cases, outright wrong.

Here are our notes on what finally worked after hours of trying, posted here in the hope that hours pulling our hair out were not spent in vain but instead can help others:

The goal of the exercise

We host firstsso.netmesh.org, an example website that illustrates how to use LID, the user-controlled digital identity technology that we came up with. At this site, we want to showcase our various LID implementations in different programming languages, such as PHP, Perl and Java. While it is easy to run PHP and Perl implementations on the same Apache web server, Java is a different animal that needs to get run under a servlet container such as Tomcat. Tomcat, in turn, needs its own port because it is a different server process.

We wanted to avoid having to go to a different port for the Java implementation, and thus thought that if we got the Apache web server to forward to Tomcat, we'd get the best of both worlds: Apache at port 80 for the Java implementation just like the PHP and the Perl implementation, while running Tomcat in the background. Our goal was not load balancing etc. (although the notes below may help you figure that one out, too)

We are using Apache 2.0.54 and Tomcat 5.5.12.

Apache-side installation

  1. You need mod_jk. You can download binaries or sources from here. We built ours from sources and had no trouble.
  2. In your Apache config file's (e.g. http.conf) main section, you need to load the module and set a few parameters. For example, in Apache 2.x:
    LoadModule jk_module modules/mod_jk.so
    JkWorkersFile      /etc/http/conf/workers.properties
    JkLogFile          /var/log/httpd/mod_jk.log
    JkLogLevel         info
    JkLogStampFormat   "[%a %b %d %H:%M:%S %Y] "
    JkOptions          +ForwardKeySize +ForwardURICompat -ForwardDirectories
    JkRequestLogFormat "%w %V %T"
    
    Within the virtual host section for host firstsso.netmesh.org, we specify which URL patterns shall be forwarded to Tomcat.
    <VirtualHost *:80>
        ServerName firstsso.netmesh.org
        JkMount /infogrid-java* worker1
    </VirtualHost>
    
    Note that this is a wildcard expression, not a regular expression like other path expressions in Apache, i.e. use * instead of (.*).
  3. Create a workers.properties file. This must have the same name as the name of the JkWorkersFile you set in the http.conf file. In the simplest case, this file contains:
    # Define 1 real worker using ajp13
    workers.tomcat_home=/usr/tomcat
    workers.java_home=/usr/java/j2sdk1.4.2_09
    ps=/
    worker.list=worker1
    # Set properties for worker1 (ajp13)
    worker.worker1.type=ajp13
    worker.worker1.host=localhost
    worker.worker1.port=8009
    worker.worker1.lbfactor=50
    worker.worker1.cachesize=10
    worker.worker1.cache_timeout=600
    worker.worker1.socket_keepalive=1
    worker.worker1.reclycle_timeout=300 
    I have to admit I'm not entirely sure about all of these parameters, but they seem to work...

Now to the Tomcat side.

Tomcat-side installation

We assume you have Tomcat up and running already.

  1. In the server config file, i.e. $CATALINA_HOME/conf/server.xml, you must define a new connector, in addition to the connector that you already have for accessing Tomcat directly. This new connector will talk the ajp13 protocol and listen to requests from Apache's mod_jk module. Assuming your server.xml file looked like this:
    <Server port="8005" shutdown="SHUTDOWN">
      ...
      <Service name="run">
        ...
        <Connector port="8080" maxHttpHeaderSize="8192" debug="1"
                   maxThreads="150" minSpareThreads="25"
                   maxSpareThreads="75" enableLookups="false"
                   redirectPort="8443" acceptCount="100"
                   connectionTimeout="20000" disableUploadTimeout="true" />
    
        <Engine name="Catalina" defaultHost="firstsso.netmesh.org">
          ...
        <Engine>
      <Service>
    <Server> 
    Modify it to look like this:
    <Server port="8005" shutdown="SHUTDOWN">
      ...
      <Service name="run">
        ...
        <Connector port="8080" maxHttpHeaderSize="8192" debug="1"
                   maxThreads="150" minSpareThreads="25"
                   maxSpareThreads="75" enableLookups="false"
                   redirectPort="8443" acceptCount="100"
                   connectionTimeout="20000" disableUploadTimeout="true" />
         
        <Connector className="org.apache.coyote.tomcat4.CoyoteConnector"
                   port="8009" minProcessors="5" maxProcessors="75"
                   enableLookups="true" redirectPort="8443"
                   acceptCount="10" debug="1" connectionTimeout="20000"
                   protocol="AJP/1.3" useURIValidationHack="false" />
    
        <Engine name="Catalina" defaultHost="firstsso.netmesh.org">
          ...
        <Engine>
      <Service>
    <Server> 
    The port number for the new connector must match the port number you specified in your JkWorkersFile above. Again, I'm not entirely sure about all these parameters, but they seem to work for us.
  2. Make sure you protect your ajp13 port, such as by configuring your firewall to only allow local connections to this port.

Restart both servers, and it should work

If not, the following things might help:

  • Make sure that Tomcat indeed listens to the ajp13 port that you configured. Try whether you can connect with something like telnet localhost 8009
  • In the httpd.conf Apache config file, set the the logging level (JkLogLevel) to debug, and watch the log file.
  • Run Tomcat in foreground mode, such as by executing $CATALINA_HOME/bin/catalina.sh run.

Have fun, and good luck! Again, this is in no way authoritative, but it documents only what worked for us.