The other day one of our customers asked me for help getting Presto/Tomcat up and running as a Windows service. What I thought should be a fairly simple task turned into tedious hours of Googling, tweaking, and re-trying various things to no avail until I finally realized the problem. If you’re banging your head against your screen trying to get Tomcat to run as a Windows Service then read on.
Presto is a web application that runs on a variety of JEE 5 compliant containers, including the bundled Apache Tomcat. Apache Tomcat is the popular open-source servlet container developed by the Apache Software Foundation, and is a pure-Java implementation of the Java Servlet and JavaServer Pages (JSP) specifications.
Tomcat and Presto 3.x
Presto contains an Apache Tomcat within the ‘appserver’ directory of the installation zip archive.
· Presto 3.0 comes with Apache Tomcat 5.5.20 base version, under <presto-home>/appserver/apache-tomcat-5.5.20
· Presto 3.1 comes with Apache Tomcat 6.0.29 with Windows 32-bit support under <presto-home>/appserver/apache-tomcat-6.0.29
Why Platform Specific Tomcat bundles
On it’s website, Apache makes available separate downloads for Windows 32-bit, Windows 64-bit, and Windows 64-bit Itanium. In addition, there is also an Installer download that will create the Windows service for you. But why these different distributions you ask? Isn’t Tomcat a pure-Java implementation? Shouldn’t it run on any platform with a proper JVM?
The answer is YES.
Well, sort of…
You COULD take any of the zip distributions above, and download/extract it to any platform with a JVM, set your JAVA_HOME appropriately and run Tomcat using its startup and shutdown scripts. That would be the equivalent of just downloading the base Tomcat distribution. So, what does the platform specific distribution get you? There are two features of Tomcat where the platform comes into play: the Apache Portable Runtime (APR), and the Tomcat service wrappers.
Apache Portable Runtime (APR)
In a nutshell, the APR is the core Apache HTTPD server engine (written in C) compiled into a library. Tomcat can be configured to use the APR via JNI to serve static page requests. When this is the case, Tomcat is essentially using Apache HTTPD native code to service non-servlet/JSP requests which results in far faster performance than if the servlet engine is serving plain old static content.
The use of APR is highly suggested for production environments, but it is not required. Tomcat prints out a small warning upon startup if you’re not using APR:
Dec 21, 2010 11:24:55 AM org.apache.catalina.core.AprLifecycleListener init
INFO: The APR based Apache Tomcat Native library which allows optimal performance
in production environments was not found on the java.library.path:
After that little note, Tomcat is on its way.
The windows specific distributions contain the APR as a DLL in <tomcat-home>/bin/tcnative-1.dll.
Tomcat Service Wrappers
In order for Tomcat to run as a windows service, Apache created a service wrapper. This service wrapper is what gets installed as a service. When started, it will start the JVM for Tomcat appropriately. For Tomcat 5.x, the service wrapper is <tomcat-home>/bin/tomcat5.exe. For Tomcat 6.x, the service wrapper is <tomcat-home>/bin/tomcat6.exe. Full details about these small helper programs are available here:
Because both the Tomcat Service wrappers and the APR are native, they are compiled and linked to a specific JVM platform. So, the Windows 32-bit distribution contains an APR library and service wrappers compiled against the 32-bit JVM. In the 64-bit version, the tomcat6.exe and tcnative-1.dll are compiled against the 64 bit JVM.
Note: the base Tomcat distribution does not contain either the APR or the Service wrappers – that is why there is no need for a 32-bit vs. 64-bit base Tomcat Distribution.
Getting Tomcat to run as a Windows Service
The link above contains instructions on using a small script called “service.bat” provided by Apache. This starts tomcat6.exe (or tomcat5.exe for Tomcat 5.x) and sets up the input arguments appropriately for service installation. Once this is done, you will see the Apache Tomcat service listed in your windows services, and should be able to start and stop the server. Or, maybe not!?
Pitfall – Mismatched JVM and Tomcat distribution
Now that we’ve discussed the various Tomcat distributions, what they contain, and why, lets talk about the main problem and why it’s actually hard to find: using the wrong Tomcat distribution and JVM.
Here’s the scenario: I arrive at the customer’s site and login to the machine on which they want Presto/Tomcat to run. It is a 64-bit Windows 2008 Server machine. They have already installed Java. Great! I follow the installation instructions for Presto. The installer properly starts Tomcat and bootstraps the presto application into it. At the completion of the install, the server is shut down. At this point I can start and stop the Apache Tomcat at will using either the startup/shutdown scripts in <presto-home>/appserver/apache-tomcat-6.0.29/bin or the convenience startup/shutdown scripts in <presto-home>. Now I want Apache Tomcat running as a service. So I use the “service.bat” script to install my windows service:
Installing the service 'Tomcat6' ...
Using CATALINA_HOME: "C:\JackBe\Presto3.1-GA\appserver\apache-tomcat-6.0.29"
Using CATALINA_BASE: "C:\JackBe\Presto3.1-GA\appserver\apache-tomcat-6.0.29"
Using JAVA_HOME: "C:\Java"
Using JVM: "auto"
The service 'Tomcat6' has been installed.
Great. I then go to my Services in Control Panel and I see the “Apache Tomcat 6” service listed. Time for the moment of truth… Click the “Start” link to start up the service – no dice. I get a dialog with a non-descriptive error. "Windows could not start the Apache Tomcat 6 on Local Computer. For more information, review the System Event Log. If this is a non-Microsoft service, contact the service vendor, and refer to service-specific error code 0."
In the Windows Event viewer, the System log shows the error message: The Apache Tomcat 6 service terminated with service-specific error The operation completed successfully..
Not much to go on, unfortunately. From here I went down the path of verifying the paths to my JVM, looking at permissions, even trying to start tomcat6.exe from the command line with the “//RS//” parameter. It still didn’t work. I finally deleted the service I had created. (Note: to delete your Tomcat Service, execute the command: “tomcat6 //DS//Tomcat6”)
The problem turned out to be that I was using the 32-bit Apache Tomcat distribution on a 64-bit machine. The 32-bit tomcat6.exe binary was simply terminating with a 0 status code without giving any further hints as to why it was dying. Once I downloaded the appropriate Tomcat distribution for my platform/JVM version, it worked fine. It turned out to be a simple solution, but hard to find given the lack of proper error messages.
Pulling it all together – installing Presto using the correct Tomcat distribution
Now we know that we need to double check our Windows systems and what Tomcat distributions to use, here’s a list of steps to take when installing Presto/Tomcat as a service on a Windows host:
1. Find out from the System Administrator if this is a Windows 64 bit system. You should see it clearly in the Control Panel -> System and Security -> System page, or by right clicking “My Computer” and selecting “Properties”
2. Find out what JVM is installed. Open a command prompt (Start -> Run -> cmd.exe). In the command prompt, change to the JAVA_HOME/bin directory, and execute the “java –version” command. If you are on a 64-bit system, then verify that the JVM installed is also a 64-bit:
java version "1.6.0_22"
Java(TM) SE Runtime Environment (build 1.6.0_22-b04)
Java HotSpot(TM) 64-Bit Server VM (build 17.1-b03, mixed mode)
4. If you are on a 32-bit Windows machine with a 32-bit JVM, then you can continue to use the bundled Tomcat 6.0.29 version in the <presto-home>/appserver directory. However, if you are on a 64-bit Windows machine then:
a. Using Windows Explorer, navigate to <presto-home>/appserver
b. Re-name the existing apache-tomcat-6.0.29 to “apache-tomcat-6.0.29-ORIG” (or delete it entirely)
d. Extract the zip into <presto-home>/appserver. If you downloaded the same Tomcat version, then you should get a subfolder: apache-tomcat-6.0.29.
5. Now, follow the Presto installation instructions.
When you run the “setup.bat”, double check that the path to the application server is correct.
6. Once Presto installation has completed. Shut down the Tomcat instance if you chose to leave it running after install completed.
7. In your command prompt window, change directories to <presto-home>/appserver/apache-tomcat-6.0.29/bin
8. Install tomcat as a service using the command: service.bat install
9. Optionally startup the tomcat6w.exe, which allows you to further customize your Tomcat service’s logging and memory.
10. Using your Control Panel > Administrative Tools > Services screen, choose your Apache Tomcat service and select “Start”.
I hope this helps those out there who are facing the mysterious “terminated with service-specific error” scenario when attempting to install Presto/Tomcat as a windows service. Remember, the key is that the JVM, Host, and Tomcat distributions must all be the same target architecture, or you are asking for trouble.