WebObjects/Web Applications/Deployment/Tomcat Deployment Details

Place for detailed information on deploying WebObjects applications in Tomcat.

Assumptions

 * Tomcat installation location: /usr/local/tomcat
 * Apache configuration location: /etc/httpd
 * Applications location: /usr/local/myapps
 * Java installation location: /usr/java/jdk1.5.0_06

Common Libraries
Install all common libraries into /usr/local/tomcat/shared/lib, e.g.:

activation.jar commons-logging-1.1.jar httpunit-1.6.2.jar java-diff-1.0.5.jar mail.jar mysql-connector-java-5.0.6-bin.jar servlet-api.jar wsdl4j.jar

War file
Install:

/usr/local/myapps/deploy/myapp.war

Hosts
For each set of applications, here in sets of 10, create these files and directory structures. See the next section for the contents of ROOT.xml files.

Notice that each application has its own host directory, e.g. myapp01.mydomain.com, myapp02.mydomain.com, myapp03.mydomain.com, etc.

Place these under:

/usr/local/myapps

Group01

group01/catalina/conf/web.xml group01/catalina/conf/tomcat-users.xml group01/catalina/conf/context.xml group01/catalina/conf/Catalina/myapp01.mydomain.com/ROOT.xml group01/catalina/conf/Catalina/myapp02.mydomain.com/ROOT.xml group01/catalina/conf/Catalina/myapp03.mydomain.com/ROOT.xml group01/catalina/conf/Catalina/myapp04.mydomain.com/ROOT.xml group01/catalina/conf/Catalina/myapp05.mydomain.com/ROOT.xml group01/catalina/conf/Catalina/myapp06.mydomain.com/ROOT.xml group01/catalina/conf/Catalina/myapp07.mydomain.com/ROOT.xml group01/catalina/conf/Catalina/myapp08.mydomain.com/ROOT.xml group01/catalina/conf/Catalina/myapp09.mydomain.com/ROOT.xml group01/catalina/conf/Catalina/myapp10.mydomain.com/ROOT.xml group01/catalina/conf/server.xml group01/catalina/logs/

Group02

group02/catalina/conf/web.xml group02/catalina/conf/tomcat-users.xml group02/catalina/conf/context.xml group02/catalina/conf/Catalina/myapp11.mydomain.com/ROOT.xml group02/catalina/conf/Catalina/myapp12.mydomain.com/ROOT.xml group02/catalina/conf/Catalina/myapp13.mydomain.com/ROOT.xml group02/catalina/conf/Catalina/myapp14.mydomain.com/ROOT.xml group02/catalina/conf/Catalina/myapp15.mydomain.com/ROOT.xml group02/catalina/conf/Catalina/myapp16.mydomain.com/ROOT.xml group02/catalina/conf/Catalina/myapp17.mydomain.com/ROOT.xml group02/catalina/conf/Catalina/myapp18.mydomain.com/ROOT.xml group02/catalina/conf/Catalina/myapp19.mydomain.com/ROOT.xml group02/catalina/conf/Catalina/myapp20.mydomain.com/ROOT.xml group02/catalina/conf/server.xml group02/catalina/logs/

ROOT.xml
For each host/application, use this template, changing the "myapp01" string, wherever it occurs below, to match the host's name, e.g. myapp01, myapp02.

    

The wo/NSLog4jLoggerName parameter is used for log4j logging, see below. Have it match the application's name.

Setup your own variables here as well for application specific configuration.

server.xml
For each group above, install host definitions as such, matching the previous naming scheme, into that group's server.xml. Here are the entries for group02:

           <Host name="myapp18.mydomain.com" debug="0" unpackWARs="false" autoDeploy="true" /> <Host name="myapp19.mydomain.com" debug="0" unpackWARs="false" autoDeploy="true" /> <Host name="myapp20.mydomain.com" debug="0" unpackWARs="false" autoDeploy="true" /> </Engine> </Service> </Server>


 * the Connector port must be unique for each Service used on a single physical machine, and must match up with the corresponding modjk worker port used in the Apache worker.properties configuration file, covered below.

NOTE: per application deployment files and classes can be found in the applications work directory, but need not be altered at any time by the administrator.

Log4j debug mode
Add this to your start of Tomcat to get explicit debug information from log4j. Log4j can be very frustrating, so this is key in debugging the steps it is taking:

log4j.debug=true

See the below Tomcat startup command for details.

Getting started
Install the log4j properties file into Tomcat's common/clases directory:

/usr/local/tomcat/common/classes/log4j.properties

If this location does not seem effective, try:

/usr/local/myapps/group01/catalina/common/classes/log4j.properties

changing the path to the appropriate group for your application, e.g. from group01 to group02.

Commented lines can be uncommented, and the application's corresponding Tomcat server restarted, to output logging for a particular application. Here the example is for application named "myapp01"; this name is defined in the ROOT.xml file above by the wo/NSLog4jLoggerName parameter:

#log4j.logger.myapp01=DEBUG, A2  #log4j.appender.A2=org.apache.log4j.RollingFileAppender #log4j.appender.A2.File=${catalina.base}/logs/myapp01.log #log4j.appender.A2.MaxFileSize=100MB #log4j.appender.A2.MaxBackupIndex=2 #log4j.appender.A2.layout=org.apache.log4j.PatternLayout #log4j.appender.A2.layout.ConversionPattern=%-5p %c [%t] %r - %m%n #log4j.appender.A2.Threshold=DEBUG log4j.rootLogger=INFO, Tomcat log4j.appender.Tomcat=org.apache.log4j.FileAppender log4j.appender.Tomcat.File=${catalina.base}/logs/tomcat.log log4j.appender.Tomcat.layout=org.apache.log4j.PatternLayout log4j.appender.Tomcat.layout.ConversionPattern=%p %t %c - %m%n log4j.logger.myapp01=FATAL log4j.logger.myapp02=FATAL log4j.logger.myapp03=FATAL log4j.logger.myapp04=FATAL log4j.logger.myapp05=FATAL log4j.logger.myapp06=FATAL log4j.logger.myapp07=FATAL log4j.logger.myapp08=FATAL log4j.logger.myapp09=FATAL log4j.logger.myapp10=FATAL log4j.logger.myapp11=FATAL log4j.logger.myapp12=FATAL log4j.logger.myapp13=FATAL log4j.logger.myapp14=FATAL log4j.logger.myapp15=FATAL log4j.logger.myapp16=FATAL log4j.logger.myapp17=FATAL log4j.logger.myapp18=FATAL log4j.logger.myapp19=FATAL log4j.logger.myapp20=FATAL

Another method to view an application's logging information is, e.g, to comment the appropriate line and restart the server:


 * 1)   log4j.logger.myapp16=FATAL

This will output logging information for the myapp16 application to /usr/local/tomcat/logs/tomcat.log.

Server Startup
Start each server up separtely. Environmental variables may be exported beforehand, or passed like so on the command line, before the executable is called:

JAVA_OPTS="-Xms256m -Xmx256m" JAVA_HOME=/usr/java/jdk1.5.0_06 CATALINA_BASE=/usr/local/myapps/group01/catalina /usr/local/tomcat/bin/startup.sh JAVA_OPTS="-Xms256m -Xmx256m" JAVA_HOME=/usr/java/jdk1.5.0_06 CATALINA_BASE=/usr/local/myapps/group02/catalina /usr/local/tomcat/bin/startup.sh  JAVA_OPTS="-Xms256m -Xmx256m" JAVA_HOME=/usr/java/jdk1.5.0_06 CATALINA_BASE=/usr/local/myapps/group03/catalina /usr/local/tomcat/bin/startup.sh  JAVA_OPTS="-Xms256m -Xmx256m" JAVA_HOME=/usr/java/jdk1.5.0_06 CATALINA_BASE=/usr/local/myapps/group04/catalina /usr/local/tomcat/bin/startup.sh  JAVA_OPTS="-Xms256m -Xmx256m" JAVA_HOME=/usr/java/jdk1.5.0_06 CATALINA_BASE=/usr/local/myapps/group05/catalina /usr/local/tomcat/bin/startup.sh

Or start a Tomcat instance with log4j debugging on to determine what steps log4j is using in determining log settings and output:

JAVA_OPTS="-Dlog4j.debug=true -Xms256m -Xmx256m" JAVA_HOME=/usr/java/jdk1.5.0_06 CATALINA_BASE=/usr/local/myapps/group01/catalina /usr/local/tomcat/bin/startup.sh

Server Shutdown
On Linux, this command will shutdown all java processes on the server, be careful:

pkill java

or a particular process may be stipulated, e.g. 12203:

pkill -P 10203

And sometimes Tomcat gets hung, be careful though, this will kill every single last java process on your system, no questions asked:

pkill -9 java

This will also work, in this case for the group01 server:

CATALINA_BASE=/usr/local/myapps/group01/catalina /usr/local/tomcat/bin/shutdown.sh

Core modjk Settings
Add to httpd.conf

JkLogFile "/usr/local/tomcat/logs/mod_jk.log" JkLogLevel info JkOptions +ForwardURICompat JkWorkersFile /etc/httpd/workers.properties

And add /etc/httpd/worker.properties, containing:

worker.list=worker01,worker02,worker03,worker04,worker05 worker.worker01.type=ajp13 worker.worker01.host=localhost worker.worker01.port=8901 worker.worker02.type=ajp13 worker.worker02.host=localhost worker.worker02.port=8902 worker.worker03.type=ajp13 worker.worker03.host=localhost worker.worker03.port=8903 worker.worker04.type=ajp13 worker.worker04.host=localhost worker.worker04.port=8904 worker.worker05.type=ajp13 worker.worker05.host=localhost worker.worker05.port=8905

Virtual Hosts
Each virtual host contains such an entry, with specifics modified appropriately, e.g. change myapp02 to match your application's name:

<VirtualHost *:80> ServerName myapp02.mydomain.com DocumentRoot "/Library/WebServer/WebSites/myapp02" JkMount /WebObjects/* worker01 <Location "/MyApp/WEB-INF/*"> AllowOverride None deny from all </Location> <Location "/MyApp/META-INF/*"> AllowOverride None deny from all </Location> <IfModule mod_rewrite.c>                 Include "/etc/httpd/mods/mod_rewrite_tomcat.conf" RewriteRule    (.*)/cgi-bin/(.*)/___AppNamePlaceHolder___(\.woa(/.*)?)? $1/$2/MyApp$3      [L,PT] </IfModule> </VirtualHost>

Rewrite Rules
Assure that apache has been built and/or installed to use mod_rewrite.

Then install /etc/httpd/mod_rewrite.conf:

RewriteEngine On RewriteRule     ^/WebObjects/.*$                        - [L,PT] This is just an example, you will have to figure this out for yourself in detail. Or figure it out and update this wiki with universal rules.

Testing
Once the Tomcat servers are up and Apache running, hit a website:

http://myapp04.mydomain.com

Auto Deployment
Touching the WAR file will redeploy all the applications. Replacing the WAR file with an updated version of your application, will auto deploy the new version systematically, one application per Tomcat server at a time. This can be followed by tailing /usr/local/tomcat/logs/tomcat.log.

Touching or updating of the ROOT.xml application files will reload/redeploy the application, and if any changes have been made, they will be picked up by the new deployment.

Rewrite Debugging
To get rewrite rule logging, add the following to the top of your rewrite fils:

RewriteLog             /tmp/mod_rewrite.log RewriteLogLevel        9

Restart Apache and tail /tmp/mod_rewrite.log while hitting the website.

= Common Errors =

javax.servlet.UnavailableException: Error initializing servlet adaptor: access denied
Waiting on more information.

javax.naming.NameNotFoundException: Name jdbc is not bound in this Context
See above comment. At present, not stopping the app from running fine. Looks like an unused entry in the web.xml file.

javax.servlet.UnavailableException: Error initializing servlet adaptor: null
Unknown, but probably just a result of a previous complete failure of the app to start.

java.lang.reflect.InvocationTargetException
Get rid of duplicate copy of jar file in the class path, most likely in /usr/local/tomcat/common/lib:

Caused by: java.lang.ExceptionInInitializerError Caused by: java.lang.IllegalStateException There is already a unique instance for Bundle named 'JavaXML'.

like so:

mv /usr/local/tomcat/common/lib/JavaXML.jar /var/tmp

javax.servlet.UnavailableException
Unknown, misconfiguration.

- Servlet threw load exception javax.servlet.UnavailableException: Can't find application bundle. You can either define WOROOT, LOCALROOT and WOAINSTALLROOT as Java system properties (e.g. in your application server's launch script as command line arguments) or in the application Deployment Descriptor file (web.xml). at com.webobjects.jspservlet.WOServletAdaptor._applicationInit(WOServletAdaptor.java:335)

java.lang.IllegalStateException: Cannot fire array fault with a null handler
at com.webobjects.eoaccess.EODatabaseContext._fireArrayFault(EODatabaseContext.java:4399) at com.webobjects.eoaccess.EOAccessArrayFaultHandler.completeInitializationOfObject(EOAccessArrayFaultHandler.java:70) at com.webobjects.eocontrol._EOCheapCopyMutableArray.willRead(_EOCheapCopyMutableArray.java:38) at com.webobjects.eocontrol._EOCheapCopyMutableArray.count(_EOCheapCopyMutableArray.java:92) at com.webobjects.eocontrol.EOSortOrdering._sortUsingKeyOrderArray(EOSortOrdering.java:173) at com.webobjects.eocontrol.EOSortOrdering.sortArrayUsingKeyOrderArray(EOSortOrdering.java:254)