12. Connecting Apache and Tomcat using mod_jk2

Since (for some odd reason) some network managers allow outgoing web connections only to TCP port 80, there might be people around that cannot access your Tomcat (and MMBase) server through port 8080. You can install a JK 2 mapping or a reverse proxy in Apache, so Tomcat and MMBase can be accessed through the Apache web server at port 80. Apart from the port issue, this has the advantage that you can use Apache to manage you SSL connections and use your existing Apache logs and statistics facilities for Tomcat and MMBase as well.

Here we describe the installation and configuration of the JK 2 Connector connecting Apache and Tomcat. In this way, Tomcat paths can be mapped into Apache.

>From the JK 2 Connector website (http://jakarta.apache.org/tomcat/tomcat-4.1-doc/config/jk2.html):

" The JK 2 Connector element represents a Connector component that communicates with a web connector via the AJP protocol. This is used for cases where you wish to invisibly integrate Tomcat 4 into an existing (or new) Apache installation, and you want Apache to handle the static content contained in the web application, and/or utilize Apache's SSL processing. In many application environments, this will result in better overall performance than running your applications under Tomcat stand-alone using the HTTP/1.1 Connector. However, the only way to know for sure whether it will provide better performance for your application is to try it both ways. "

If you will only be needing a simple configuration-- typically a single Tomcat server sitting on the same system as your Apache server-- Apache reverse proxies might be an easier solution for you. Although these are simpler in terms of the interconnection features, reverse proxies provide more flexibility in fiddling with your paths and other options. The configuration of Apache reverse proxies is described in the next section.

However, if you plan to build or grow to a farm of several Tomcat servers behind an Apache front-end or build a high-performance system, deploying the JK 2 Connector is the way to go.

Download the sources of the JK 2 Connector from the Apache Jakarta website:

  http://jakarta.apache.org/site/sourceindex.cgi
  

Extract and compile the JK 2 Connector:

  
  tar -zxvf jakarta-tomcat-connectors-jk2-src-xxx.tar.gz
  cd jakarta-tomcat-connectors-jk2-src/jk/native2/
  ./configure \
    --with-apxs2=/usr/local/apache/bin/apxs
  make
  
  

Make sure your $JAVA_HOME environment variable is set and the Java binaries are in your $PATH or add this option to your ./configure command:

  --with-java-home=/usr/local/j2sdk
  

Copy the module files mod_jk2.so and jkjni.so to the modules/ directory of Apache:

  
  cp -i ../build/jk2/apache2/*.so /usr/local/apache/modules/
  chmod 755 /usr/local/apache/modules/mod_jk2.so
  chown root:root /usr/local/apache/modules/mod_jk2.so
  chmod 755 /usr/local/apache/modules/jkjni.so
  chown root:root /usr/local/apache/modules/jkjni.so
  libtool --finish /usr/local/apache/modules
  
  

Copy the sample configuration file workers2.properties to the configuration directory of Apache:

  

  cp -i ../../jk/conf/workers2.properties /usr/local/apache/conf/
  chown root:root /usr/local/apache/conf/workers2.properties
  chmod 644 /usr/local/apache/conf/workers2.properties
  
  

and adjust it to your own needs.

Here is a simple configuration that should get you up and running:

  
  [logger]
  # outcomment this in production use
  level=DEBUG
  
  [config:]
  file=${serverRoot}/conf/workers2.properties
  debug=0
  debugEnv=0
  
  [uriMap:]
  info=Maps the requests. Options: debug
  debug=1
  
  [shm:]
  info=Scoreboard. Required for reconfiguration and status with multiprocess servers
  file=${serverRoot}/logs/jk2.shm
  size=1000000
  debug=0
  disabled=0
  
  [workerEnv:]
  info=Global server options
  timing=1
  debug=0
  
  [status:]
  info=Status worker, displays runtime informations
  
  [uri:<hostname>/jkstatus/*]
  info=Display status information and checks the config file for changes.
  group=status:
  
  [channel.socket:localhost:8009]
  info=Ajp13 forwarding over socket
  
  # Define the worker
  [ajp13:localhost:8009]
  channel=channel.socket:localhost:8009
  
  [uri:<hostname>/mmbase-webapp/*]
  info=MMBase
  
  

Most of this configuration is pretty standard. The last uri declaration (replace <hostname> with your hostname) is what this is all about; it maps all client requests starting with /mmbase-webapp/ from Apache to your Tomcat server.

Note

When we made a virtual host mapping, somehow the general mappings no longer worked for this virtual host (other virtual hosts on the same IP address had no problem at all). We had to explicitly add the general mappings for this virtual host to make these work again. A bug? Or a consequence of the way Apache implements name based virtual hosts?

So now, the same application you accessed through Tomcat as (replace <hostname> with your hostname):

  
  http://<hostname>:8080/mmbase-webapp/
  
  

will be available through Apache as:

  
  http://<hostname>/mmbase-webapp/
  
  

Important

Only name based virtual hosts are supported this way. Make sure you add the virtual host name (pointing to this very same (web) server) to the /etc/hosts file (replace <hostname> with your hostname):

  
  192.168.3.17 <hostname>
  
  

or things will not work (running DNS is not sufficient here!).

If your Apache installation is serving only a single website, you can leave out the hostname:

  
  [uri:/mmbase-webapp/*]
  info=MMBase
  
  

which will serve the mapped /mmbase-webapp/ directory on every address and site of your Apache installation.

Note

Using JK Connector version 2, all configuration settings will be in the workers2.properties file. Even though Tomcat comes with its own JK 2 configuration file /usr/local/tomcat/conf/jk2.properties, there's no need to edit this as long as you stick with the standard port 8009.

If you do have to edit this file (for example when changing the port), make sure that you do it when your Tomcat server is not running; the file is auto-edited by Tomcat itself.

After adding the mod_jk2 module to your Apache configuration (in the file /etc/httpd/conf/httpd.conf or in a new file jk2.conf in the Apache configuration directory /etc/httpd/conf.d):

  
  # Load mod_jk2 module
  LoadModule jk2_module modules/mod_jk2.so
  
  


  
  chown root:root /etc/httpd/conf.d/jk2.conf
  chmod 644 /etc/httpd/conf.d/jk2.conf
  
  

you can now restart Apache and give your new entrance a try: (replace <hostname> with your hostname):

  
  http://<hostname>/mmbase-webapp/
  
  

To check the status of the JK 2 Connector (replace <hostname> with your hostname):

  
  http://<hostname>/jkstatus/
  
  

Tip

You can reread the configuration in /usr/local/apache/conf/workers2.properties by (re)loading the JK Status page. This allows you to add new mappings without restarting Apache or having it reload its configuration. However, existing mappings can not be removed this way and require Apache to reconfigure.

Although it's also possible to place the JK 2 configurations (in a slightly different form) in your Apache configuration file, this is a good reason to stick with the workers2.properties setup.

Important

To protect access to the JK Status page, add an authentication declaration to the Apache configuration. For example:

  
  <Location /jkstatus/>
  AuthType Basic
  AuthName "JK 2 Connector Status"
  AuthUserFile /etc/httpd/conf/users
  AuthGroupFile /etc/httpd/conf/groups
  Require group admin
  </Location>
  
  

This will prompt for a login from a user from the admin group.

In case of any problems, check the JK 2 Connector log messages that will be written to your Apache error_log.

Tip

In case the JK 2 Connector has difficulties connecting to Tomcat, check whether Tomcat is indeed available on port 8009:

  
  netstat -tln
  
  

Access requests mapping to Tomcat will be logged in the access_log's and error_log's of Apache.

For more information on the workers2.properties configuration, check the documentation at:

  http://jakarta.apache.org/tomcat/tomcat-4.1-doc/jk2/jk2/configwebcom.html
  

There you will read about setting up more (remote) Tomcat workers, grouping these together in load-balancing pools, setting up RPC channels, using Unix sockets, using the Java Native Interface (JNI) to interconnect with Tomcat directly (in-process), setting up alternative loggers, and optimizing your time-outs.

Tip

Apache is far more efficient than Tomcat in serving ordinary content files. You could have both the Apache and Tomcat document directories point to the same directory on your filesystem and only forward requests for JSP pages and Java Servlets. For example (in workers2.conf):

  
  #[uri:/examples/servlet/*]
  #info=Prefix mapping

  #[uri:/examples/*.jsp]
  #info=Extension mapping
  
  

However, now you need to protect Tomcat's WEB-INF/ directories (and other directories and files you don't want visitors to have access to) from being served by Apache. For example (in Apache's httpd.conf):

  
  <Location "/examples/WEB-INF/">
  AllowOverride None
  deny from all
  <Location>
  
  

Also, realize that a setup like this bypasses any security constraints you may have configured in the file /usr/local/tomcat/webapps/examples/WEB-INF/web.xml.

You can find more general information about the JK 2 Connector at:

  http://jakarta.apache.org/tomcat/tomcat-4.1-doc/jk2/