# WebObjects/Web Applications/Deployment/Tomcat Deployment

This article was written by Andrew Lindesay (http://www.lindesay.co.nz) around May 2005. It first appeared as LaTeX PDF and has been transcribed into this Wiki. You use the information contained in this document at your own risk. Please contact the author if you feel there may have been an error in the conversion to Wiki markup.

## AbstractEdit

From WebObjects 5.2, it has been possible to derive a build product from a WebObjects application project that can be deployed into a J2EE servlet container. This article shows how it is possible to deploy a WebObjects 5.2 application into a Tomcat environment and achieve a very similar topology to the ”native” WebObjects deploy.

## IntroductionEdit

This document was originally written assuming a Tomcat 5 deployment, but after some difficulties with web services and AXIS, I have modified this document to also cater for a Tomcat 3 deployment. This document covers both circumstances.

## AssumptionsEdit

• WebObjects 5.2 (likely to work fine with newer versions)
• Java 1.4
• Latest Tomcat release of version 5 (5.5.12 at the time of writing) or 3 (3.3.2 at the time of writing)
• Some sort of UNIX deployment.
• The reader has some conception of the concepts behind servlet technology.
• The reader is familiar with a standard WebObjects deployment topology which will be referred to as wotaskd deployment.

For the purposes of this document, it is assumed that Tomcat has been installed at a directory on the local disc called $TOMCATDIR. It is also assumed that you will have another directory with the files required to configure and run an instance called$INSTDIR. It is assumed also that you will have a directory called $JKDIR with the Tomcat apache adaptor in it. In this article, some configuration files require the paths to be shown and these are tabulated below. $TOMCATDIR /opt/tomcat $INSTDIR /opt/fooapp$JKDIR /opt/modjk

In reality, these directories could be located anywhere.

### ObjectiveEdit

The objective of this article is to show that a WebObjects application can be deployed into a servlet container and keep some of the desirable attributes of a WebObjects deployment topology. Some of these traits are itemised below.

• Clustering over a number of hardware nodes to prevent system downtime from a single hardware failure incident.
• Clustering over a number of virtual machine instances on each hardware node to avoid downtime from a single software failure incident.
• Ability to make efficient use of lower cost server hardware rather than encouraging use of large, expensive servers.
• Make maximum use of memory availabile in each virtual machine as cache to minimise database traffic and lower stress on the database server.
• Ability to make sessions "sticky" to a given virtual machine instance, whilst being multiplexed through a single web server front-end adaptor.
• Ability to load-balance requests to instances which are operational.

A standard WebObjects deployment topology is shown in the figure below alongside what is to be achieved with Tomcat. A typical J2EE deployment may have a different topology from this.

File:Wo-tomcat-deploy-topology.gif

## Servlet Build ProductsEdit

Creating a servlet build product from a WebObjects application project is covered in some depth by documentation that is supplied by Apple for WebObjects. This is not going to be repeated here, but here is a brief overview of the process.

• Include the JavaWOJSPServlet.framework framework into your project.
• In the build settings, set the SERVLET_SINGLE_DIR_DEPLOY value to YES to create the most trouble-free form of deployment servlet.
• Edit the SERVLET_DEPLOY_LICENSE to contain your valid deployment license key if you need one for the version of WebObjects you are using.
• Edit the SERVLET_WEBAPPS_DIR to point to $INSTDIR/webapps/ or some place where you want the build product to go. Now when you choose a Deployment build, you will also get the servlet assembled. The end result is a directory structure similar to that shown in the figure below. File:Wo-tomcat-ssd-filelayout-3.gif ## Removing the DOCTYPE from .plist FilesEdit Many property-list files (often called plist files) have a document type at the top. This can refer to files on a MacOS-X machine or to files on Apple servers. In either case this can cause problems with deployments which are not on MacOS-X servers. The following script can be run with the argument of the WEB-INF folder to remove these. The WebObjects application runs fine without this information in the plist files. This script can easily be incorporated one way or another as a step in the build process for your WebObjects project. # [apl 3.may.2006] # This will remove any DOCTYPE's from the top of plists so that # they do not attempt to validate the DTD which is either # extracted from /System or the internet over HTTP. if [ -z$1 ]; then
echo "syntax: stripdocype.sh <directory>"
exit 1
fi

for PLISTFILE in find $1 -name *.plist do sed \ '/<!DOCTYPE [^>]*>/s/.*//' \$PLISTFILE \
> /tmp/remove-plist-temp

$INSTDIR/webapps/FooApp/WEB-INF  ### Tomcat Server Configuration FilesEdit You need to create a tomcat configuration file for each of the instances that you would like to have. The pattern is followed here of having an instance number proceeded by the lower case letter "i". Put the first server configuration file at the following location. $INSTDIR/server_i1.xml


Here is an example of how this file might look. There is no coverage of the individual settings here as the reader is expected to review the tomcat documentation to discover the specific meanings of these settings.

#### Tomcat 5Edit

<Server port="7071" shutdown="SHUTDOWN">
<Service name="Catalina">
enableLookups="false" acceptCount="100"

<Connector port="9091" enableLookups="false" protocol="AJP/1.3" />

<Engine name="i1" defaultHost="appserver1.foo.co.nz" jvmRoute="i1">
<Host name="appserver1.foo.co.nz"
appBase="/home/fooapp/webapps"
unpackWARs="true" autoDeploy="false"
xmlValidation="false" xmlNamespaceAware="false">
<Manager distributable="false" />
</Context>
</Host>
</Engine>

</Service>
</Server>


#### Tomcat 3Edit

  <?xml version="1.0" encoding="ISO-8859-1"?>

<Server>
<ContextManager workDir="work">

<AutoDeploy source="modules" target="modules" redeploy="true" />
<AutoWebApp dir="modules" host="DEFAULT" trusted="true"/>

<SimpleMapper1 />

<SessionExpirer checkInterval="60" />
<SessionIdGenerator randomClass="java.security.SecureRandom" />

<ErrorHandler showDebugInfo="true" />

<Jdk12Interceptor />
<Servlet22Interceptor />

<SimpleSessionStore maxActiveSessions="256" />

<Http10Connector  port="8081" secure="false" />
<Ajp13Connector port="9091" tomcatAuthentication="false" shutdownEnable="true" />

</ContextManager>
</Server>


Assuming that there will be three instances in this example deploy, this entire file should be replicated and modified twice for the other two instances. For the other instances' server configuration files, change the "i1" (Tomcat 5 only) by modifying the numerical component and change the port numbers by making the last digit the instance number. For example, the ports 7071, 8081 and 9091 are used here. For "i2", use 7072, 8082 and 9092.

You should have three files now present called server_i1.xml, server_i2.xml and server_i3.xml in the directory $INSTDIR. ### Startup An InstanceEdit To startup an instance, issue a command as follows. You should issue this command for each of the server configuration files. The$JAVA_HOME shell environment variable should have been setup correctly before launching an instance.

#### Tomcat 5Edit

$TOMCATDIR/bin/startup.sh -config$INSTDIR/server_i1.xml


### Shutdown An InstanceEdit

To shutdown an instance, issue a command as follows.

#### Tomcat 5Edit

$TOMCATDIR/bin/shutdown.sh -config$INSTDIR/server_i1.xml


It is also possible to use the UNIX telnet command to connect to the port described in the server configuration file's Server tag and type the word supplied in the shutdown attribute to take out the Tomcat instance.

#### Tomcat 3Edit

TOMCATDIR/bin/shutdown -ajp13 -port 9091


A final deployment usually involves apache feeding inbound requests to instances and handling situations where an instance has gone down and balancing load over the instances that are currently running. This job is undertaken by mod_jk which is a module for apache written by the Tomcat group. This module communicates with the tomcat instances using a protocol called AJP. This protocol carries all the information required to check instances are operational as well as relaying requests to the instances. It is assumed that the configuration as well as binaries for the mod_jk apache module will be located at $JKDIR. ### Compiling and InstallingEdit Instructions for downloading and installing mod_jk can be obtained from the Tomcat website. The mod_jk.so binary should be located at the following path. $JKDIR/mod_jk.so


Add a line to your system's apache httpd configuration file like this:

Include /opt/modjk/apache.conf


Edit this file to look like this:

LoadModule jk_module /opt/modjk/mod_jk.so

JkLogFile /opt/modjk/mod_jk.log
JkLogLevel info

JkWorkerProperty worker.i1.type=ajp13
JkWorkerProperty worker.i1.port=9091
JkWorkerProperty worker.i1.host=appserver1.foo.co.nz
JkWorkerProperty worker.i1.lbfactor=1
JkWorkerProperty worker.i2.type=ajp13
JkWorkerProperty worker.i2.port=9092
JkWorkerProperty worker.i2.host=appserver1.foo.co.nz
JkWorkerProperty worker.i2.lbfactor=1
JkWorkerProperty worker.i3.type=ajp13
JkWorkerProperty worker.i3.port=9093
JkWorkerProperty worker.i3.host=appserver1.foo.co.nz
JkWorkerProperty worker.i3.lbfactor=1



Again, the details of the exact settings will not be covered in this article, but this should provide a simple guide to setting up this file to provide for a multi-instance deploy under Tomcat.

### Restart ApacheEdit

Now restart apache with the following command:

sudo apachectl restart


### Test ApplicationEdit

Now you can test your application using a URL such as this one.

http://www.foo.co.nz/FooApp/WebObjects/FooApp.woa


All three instances that you have setup should take some of the inbound requests.

### Choosing the Right InstanceEdit

mod_jk ensures that requests that have started a session will be directed to the correct instance where the session originated. This behaviour is known as {\it sticky sessions}. It does not appear to be possible to nominate the instance from the servlet container in another way.