Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Contents

Table of Contents
styledisc

Abstract

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.

Introduction

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.

Assumptions

This article assumes the following:

...

In reality, these directories could be located anywhere.

Objective

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.

...

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.

Servlet Build Products

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.

...

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.

Removing the DOCTYPE from .plist Files

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.

Code Block
# [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 [^>Deployment-Tomcat Deployment^>]*>/s/.*//' \
    $PLISTFILE \
    > /tmp/remove-plist-temp

    cp /tmp/remove-plist-temp $PLISTFILE
done

Application Configuration with Tomcat

A WebObjects project with servlet support has a file called web.xml.template in it. By default, this is located in /Resources/Servlet Resources/WEB-INF in your project. The web.xml.template file is used as a template for creating web.xml which is also known as the servlet deployment descriptor. This deployment descriptor is used as the means of communicating settings to the application as well as the servlet container in which the application runs. This section covers some common changes to that file as well as a discussion around a means of general configuration of the application when it is running inside a servlet container.

Data Source for Model Database Configuration

Some WebObjects engineers use the setConnectionDictionary(...) method on a model to set the JDBC database connection parameters for the model. However, the servlet container has it's own data source mechanism for supplying database information which will override any connection dictionary information which is set into the model. If you don't want this to happen, and you want your setConnectionDictionary(...) to take effect, comment out the resource-ref item with the title jdbc/DefaultDataSource in the web.xml.template file.

...

Code Block
  <Resource
	auth="Container"
	description="MyApp Data Source"
HERE -> name="MyModel"
	type="javax.sql.DataSource"
	driverClassName="com.microsoft.jdbc.sqlserver.SQLServerDriver"
	url="jdbc:microsoft:sqlserver://serveraddress:1433;databaseName=TEST"
	username="user"
	password="pass"
	maxActive="4"
	maxWait="5000"
	maxIdle="10"
  />

Serving WebServerResources

To stop the web server resources (images, CSS files and other static data) from being served out of the java environment, you need to configure the context-param with the name WOAppMode to be Deployment in the web.xml.template file.

Application Specific Configuration

This area of configuration covers items such as the following ficticious examples;

...

It is probably easiest to apply these settings in some automated fashion to the web.xml file as part of a further automated build or deploy process.

Application Binary

Put your application servlet build product at $INSTDIR such that the following path exists.

No Format
$INSTDIR/webapps/FooApp/WEB-INF

Tomcat Server Configuration Files

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.

...

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 5

Code Block
xml
xml
<Server port="7071" shutdown="SHUTDOWN">
  <Service name="Catalina">
    <Connector port="8081" maxHttpHeaderSize="8192"
               maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
               enableLookups="false" acceptCount="100"
               connectionTimeout="20000" disableUploadTimeout="true" />

    <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">
        <Context cookies="false" docBase="FooApp"
          path="FooApp" reloadable="false">
          <Manager distributable="false" />
        </Context>
      </Host>
    </Engine>

  </Service>
</Server>

Tomcat 3

Code Block
xml
xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<Server>
  <ContextManager workDir="work">
    <LoaderInterceptor11 useApplicationLoader="true"/>

    <AutoDeploy source="modules" target="modules" redeploy="true"/>
    <AutoWebApp dir="modules" host="DEFAULT" trusted="true"/>
    <AutoWebApp dir="/home/fooapp/webapps" trusted="true" reloadable="false"/>

    <SimpleMapper1/>

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

    <WebXmlReader validate="false"/>
    <ErrorHandler showDebugInfo="true"/>

    <Jdk12Interceptor/>
    <LoadOnStartupInterceptor/>
    <Servlet22Interceptor/>

    <SessionId cookiesFirst="false" noCookies="true"/>
    <SimpleSessionStore maxActiveSessions="256"/>

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

...

You should have three files now present called server_i1.xml, server_i2.xml and server_i3.xml in the directory $INSTDIR.

Startup An Instance

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 5

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

Tomcat 3

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

Tomcat 3 Environment Variables

To pass java environment variables to your application, set the TOMCAT_OPTS shell environment variable before starting up the Tomcat 3 environment. An example of this would be as follows;

No Format
TOMCAT_OPTS=-Dabc=xyz
export TOMCAT_OPTS

Check Availability

You can now see if your instance is up using the following URL.

...

Check each of your instances.

Problems

Under Tomcat 5, check the log file at $TOMCATHOME/logs/catalina.out if you are unable to access your instance.

Shutdown An Instance

To shutdown an instance, issue a command as follows.

Tomcat 5

No Format
$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 3

No Format
TOMCATDIR/bin/shutdown -ajp13 -port 9091

Apache Adaptor Setup

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 Installing

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.

...

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 Apache

Now restart apache with the following command:

No Format
sudo apachectl restart

Test Application

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

...

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

Choosing the Right Instance

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 sticky sessions. It does not appear to be possible to nominate the instance from the servlet container in another way.