How to Configure Tomcat AJP Connector with Apache httpd: Solving 404 Errors and VirtualHost Integration


2 views

When integrating Apache Tomcat with Apache httpd using mod_jk, many developers encounter the frustrating "404 Not Found" error despite following official documentation. The core issue often lies in configuration nuances between virtual hosts and URI mapping.

First, verify these essential elements in your setup:

# In httpd.conf or apache2.conf
LoadModule jk_module modules/mod_jk.so
JkWorkersFile /etc/apache2/workers.properties
JkLogFile /var/log/apache2/mod_jk.log
JkLogLevel debug
JkMount /webapp/* worker1

The workers.properties file should contain:

worker.list=worker1
worker.worker1.type=ajp13
worker.worker1.host=localhost
worker.worker1.port=8009

A common oversight is forgetting that JkMount directives don't automatically apply to VirtualHosts. The solution is to either:

# Option 1: Copy global mounts to VirtualHosts
JkMountCopy On

# Option 2: Explicitly declare within each VirtualHost

    JkMount /webapp/* worker1
    # Other VirtualHost directives

Ensure your web application's context path matches the JkMount path. For example, if your WAR is deployed as myapp.war, the proper configuration would be:

# Apache config
JkMount /myapp/* worker1

# Tomcat's server.xml

When encountering "missing uri map" errors in mod_jk.log, check:

  • Apache error.log for configuration errors
  • Tomcat's catalina.out for AJP connection attempts
  • Network connectivity between httpd and Tomcat (telnet localhost 8009)

Here's a verified configuration for Debian systems:

# /etc/apache2/mods-available/jk.conf

    JkWorkersFile /etc/apache2/workers.properties
    JkLogFile /var/log/apache2/mod_jk.log
    JkLogLevel info
    JkMountCopy On
    JkMount /tomcat7* worker1


# /etc/tomcat7/server.xml (relevant portion)

Remember to enable the configurations with:

a2enmod jk
systemctl restart apache2
systemctl restart tomcat7


When integrating Tomcat with Apache HTTP Server through AJP (Apache JServ Protocol), the configuration involves multiple components working in harmony. Let's break down the essential elements:

# Essential mod_jk configuration in httpd.conf
LoadModule jk_module modules/mod_jk.so
JkWorkersFile /etc/apache2/workers.properties
JkShmFile /var/log/apache2/mod_jk.shm
JkLogFile /var/log/apache2/mod_jk.log
JkLogLevel debug
JkLogStampFormat "[%a %b %d %H:%M:%S %Y] "
JkMount /webapp/* ajp13_worker

The workers.properties file serves as the bridge between Apache and Tomcat. A properly configured file should resemble:

# Define worker list
worker.list=ajp13_worker

# Set properties for AJP13 worker
worker.ajp13_worker.type=ajp13
worker.ajp13_worker.host=localhost
worker.ajp13_worker.port=8009
worker.ajp13_worker.connection_pool_size=50
worker.ajp13_worker.connect_timeout=5000
worker.ajp13_worker.prepost_timeout=10000

The most common pitfall occurs when VirtualHost configurations don't properly inherit JkMount directives. Here's a robust VirtualHost setup:


    ServerName example.com
    JkMountCopy On
    JkMount /webapp* ajp13_worker
    
    # Optional: Static content handling
    Alias /static /path/to/static/files
    
        Require all granted
    

When facing "missing uri map" errors, consider these diagnostic steps:

  1. Verify mod_jk is properly loaded in Apache:
    apachectl -M | grep jk
  2. Check Tomcat's AJP connector is enabled in server.xml:
  3. Test the AJP connection directly:
    telnet localhost 8009

For production environments, consider these optimizations:

# In workers.properties
worker.ajp13_worker.socket_keepalive=true
worker.ajp13_worker.retries=3
worker.ajp13_worker.reply_timeout=300000

# In httpd.conf
JkOptions +ForwardURICompatUnparsed
JkOptions +ForwardDirectories

Always secure your AJP connection, especially in production: