Wednesday, March 30, 2011

Tomcat Native Libraries

Again, I have been wrangled into solving the secrets of the universe. To make matters worse, I'd already solved this problem once. Now I get to solve it again.

The problem: When Tomcat starts, it writes to the logs...
The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path
What! I'm not getting optimal performance! Unsatisfactory. Hey, Doug! We want optimal performance... go get us some of that there Tomcat Native. And can you get us this optimal performance by lunch tomorrow?

Yeah.

First things first: Check out Apache's Native library for Tomcat documentation. Next, forget about that, its worthless. Okay, now Google it, and read the dozens of posts about compiling Tomcat Native on Debian and Ubuntu. Next, forget about that, its worthless. Remember this is production... and that means you grow up and run Red Hat.

Assuming you have Tomcat up and running, change to the Tomcat root directory, and look in bin. You should see a tomcat-native.tar.gz file. This contains one third of the source code you will need. Sounds like we need to find the rest:
rpm -qa apr-devel openssl-devel
apr-devel-1.3.9-3.fc13.x86_64
openssl-devel-1.0.0d-1.fc13.x86_64
Obviously, your versions may differ. Install if missing. Extract the tomcat-native and decent into the build dir:
tar -xzf tomcat-native.tar.gz
cd tomcat-native-*-src/jni/native
Per Unix lore, we ought to be able to run configure, make, and make install. In this case it fails with the error message "Please use the --with-apr option." After significant aggravation, I found the correct syntax for this option, as well as the SSL syntax:
./configure --with-apr=/usr/bin/apr-1-config \
 --with-ssl=/usr/lib64/openssl
Now I get:
error: can't locate a valid JDK location
I got this one:
ls -l $(which java)
<snip> /usr/bin/java -> /etc/alternatives/java
ls -l /etc/alternatives/java
<snip> /etc/alternatives/java -> /usr/lib/jvm/jre-1.6.0-openjdk.x86_64/bin/java
ls /usr/lib/jvm/
java
java-1.5.0-gcj-1.5.0.0
java-1.6.0
java-1.6.0-openjdk-1.6.0.0.x86_64
java-1.6.0-openjdk.x86_64
java-openjdk
<snip>
Since its missing the JDK, its got to be one of the openjdk items. Turns out, two are links, so we can use the shortest. Dig around to figure out the syntax to pass into the compile:
./configure --with-apr=/usr/bin/apr-1-config \
 --with-ssl=/usr/lib64/openssl \
 --with-java-home=/usr/lib/jvm/java-openjdk
Victory! Run make. Now make install. Wait! Not so fast. When you do this, its going to install something, somewhere... Right? Consider this: As long as this is a single purpose VM, go ahead and pull the trigger, but if you are running more than one Tomcat instance, which is probably the case with a physical server, running make install could cause problems. Instead, lets localize this library to the Tomcat that gave us the original TAR file. Back up a few steps and add a prefix option:
make clean
./configure --with-apr=/usr/bin/apr-1-config \
 --with-ssl=/usr/lib64/openssl \
 --with-java-home=/usr/lib/jvm/java-openjdk \
 --prefix=/opt/apache-tomcat-7.0.11
make; make install
Chamge dirs over to Tomcat's root. You'll notice an include dir, with nothing in it-- is safe to delete. Look in you lib dir and you will see several libtcnative files. These are the fruits of your labors. (Well, my labors, actually.) To invoke these files:
export LD_LIBRARY_PATH=/opt/apache-tomcat-7.0.11/lib
bin/startup.sh
The logs now show:
Loaded APR based Apache Tomcat Native library 1.1.20.
Hurray!

And the optimal performance? Don't worry... its there: Trust me. Benchmark? Performance metrics? Don't worry about that stuff. Just believe. Feel the love. Be one with the universe.

Yeah.