Hosted by:

WrapperStartStopApp Integration (Win32)

WrapperStartStopApp Integration (Win32)

Integration Methods

- Methods of Integrating with the Java Service Wrapper

Method 2 - WrapperStartStopApp Integration (Win32)

- Overview
- Detailed Instructions

| Overview

The second method is to use the `WrapperStartStopApp` helper class. This method provides a way to integrate with applications like Tomcat, which are started using one class and then stopped using another class. Typically, this kind of application will open a server socket on startup whose job is to wait for a connection which triggers a shutdown. The shutdown, or "stop", class when launched then triggers the shutdown by connecting to application. The Wrapper works with this kind of application by starting up the application, as in the first method, using the "start" class and then calling the main method of the "stop" class when it is time for the application to be shutdown.

When integrating with the `WrapperStartStopApp` helper class, the `WrapperStartStopApp` class replaces an application's main class. This gives the `WrapperStartStopApp` class a chance to immediately initialize the `WrapperManager` and register the JVM with the Wrapper. The `WrapperStartStopApp` class then manages all interaction with the Wrapper as well as the life-cycle of an application. When the Wrapper sends a start message to the JVM via the `WrapperManager`, the main method of the application's "start" class is called. Likewise, when the Wrapper sends a stop message, the main method of the application's "stop" class is called.

When the `WrapperStartStopApp` helper class is launched, it needs to be told about the class names of both the "start" and "stop" classes as well as any parameters which need to be provided to the main methods of each class. This results in a parameter list which is a little more complicated than with the `WrapperSimpleApp` helper class.

The first parameter passed to the `WrapperStartStopApp` class will be the full class name of the "start" class. This is followed by a count of the parameters to the "start" class's main method which will come next. After the "start" class's parameters, comes the "stop" class's full class name. This is followed a true/false flag which tells the `WrapperStartStopApp` class whether or not it should wait until all non-daemon threads have completed before actually exiting. This flag is then followed by the "stop" class's parameter count and parameters. Don't worry if this is confusing right now. A detailed example is provided below.

The following section will walk you through a detailed explanation of how to configure Tomcat to run within the Wrapper. Most other applications can be integrated by following the same steps.

| Detailed Instructions

| Install Tomcat
This tutorial will start with a clean install of Tomcat. We used version 4.1.18 so the exact steps may be slightly different depending on the exact version installed. Tomcat was installed in the root directory, `D:\`, resulting in a Tomcat Home directory of `D:\jakarta-tomcat-4.1.18`.

| Installing Wrapper Files

There are four files which are required to be able to use the Wrapper. We will also copy over three additional batch files which can be used to launch Tomcat as well as install and uninstall it as an NT Service.

| bin directory

First we will copy the following files into the Tomcat bin directory:

    {WRAPPER_HOME}\bin\Wrapper.exe
    {WRAPPER_HOME}\src\bin\App.bat.in
    {WRAPPER_HOME}\src\bin\InstallApp-NT.bat.in
    {WRAPPER_HOME}\src\bin\UninstallApp-NT.bat.in

Rename the three batch files as follows. Be sure to remove the `.in` extensions so that the files all end in `.bat`. Depending on how your file explorer is configured, you may not be able to see the extensions.

    {TOMCAT_HOME}\bin\Tomcat.bat
    {TOMCAT_HOME}\bin\InstallTomcat-NT.bat
    {TOMCAT_HOME}\bin\UninstallTomcat-NT.bat

The Wrapper.exe file is the actual Wrapper executable. The three batch files are used to run Tomcat in a console, and to install and remove it as an NT Service. These scripts should not require any modification. They do assume that the `wrapper.conf` file will be located within a `conf` directory one level up, `../conf/wrapper.conf`. If you wish to locate this file someplace else, then the three batch files will require that small modification.

| lib directory

Tomcat does not have a `lib` directory, which is the standard place for the Wrapper's library files to be located. So for Tomcat, we will place them into the `common/lib` directory. Copy the following two files into that directory:

    {WRAPPER_HOME}\lib\Wrapper.DLL
    {WRAPPER_HOME}\lib\wrapper.jar

The `Wrapper.DLL` file is a native library required by the portion of the Wrapper which runs within the JVM. The `wrapper.jar` file contains all of the Wrapper classes.

| conf directory

The Wrapper requires a configuration file. Please copy the template `wrapper.conf` file into the `conf` directory.

    {WRAPPER_HOME}\src\conf\wrapper.conf.in

Be sure to remove the `.in` extension so that the file is named `wrapper.conf`. Depending on how your file explorer is configured, you may not be able to see the extension. You should now have:

    {TOMCAT_HOME}\conf\wrapper.conf

If you wish to relocate the configuration file, you are free to do so. You will need to modify the batch scripts copied into the bin directory above, to reflect the new location.

| logs directory
The default `wrapper.conf` file will place a `wrapper.log` file in a `logs` directory under the application home directory. Tomcat already has such a directory, so we are all set. If you wish to place the log file in another location, you will need to edit the `wrapper.conf` file and modify the `wrapper.logfile` property to reflect the new location.

| Locate the Application's Java Command Line

Before the Wrapper can be configured to launch an Application, you will need to know the full Java command which is normally used.

Most applications make use of a batch file to build up the actual command line. These batch files tend to get quite unwieldy and in fact, the ability to avoid having to work with them is one of the benefits of working with the Wrapper.

Tomcat is launched by using a batch file called `startup.bat` and then shutdown using a batch file called `shutdown.bat`. It is launched by first changing the current directory to the `bin` directory and then run from there. If you open `startup.bat` into an editor, you will notice after some investigation, that Java is not actually launched from this script. Rather another batch file, `catalina.bat`, is called. Tomcat's scripts are very advanced and allow the user to do a lot of configuration from the command line. The command line that we will capture and use with the Wrapper will actually be a snapshot of one such configuration. This example will assume that no parameters are passed to either the startup or shutdown scripts when they are run.

If you open `catalina.bat` into an editor and scroll down to the very bottom of the file, you will see four lines which launch Java. With the defaults that we are using, the first of these will be used. The line we are interested in looks like the following: (The command is very long and has been truncated.)

    %_EXECJAVA% %JAVA_OPTS% %CATALINA_OPTS% %DEBUG_OPTS% -Djava.endorsed.dirs="%JAVA_ENDORSED_DIRS%" ...

The majority of the batch file has the task of collecting system specific information and storing that information into environment variables. The line above then expands all of the collected information into the final Java command which launches the application. From looking at the source of the batch file, we hope you appreciate the complexity and the desire to have to avoid completely writing such scripts yourself.

In order to configure the Wrapper, all that is really needed is the final expanded command line. Rather than reading through the entire script and attempting to understand it, we will use a simple trick to display the final command line in the console. Edit the batch file by inserting "ECHO " at the beginning of the above line. After doing so, you should have: (Once again the line has been truncated to fit on the screen.)

    ECHO %_EXECJAVA% %JAVA_OPTS% %CATALINA_OPTS% %DEBUG_OPTS% -Djava.endorsed.dirs="%JAVA_ENDORSED_DIRS%" ...

If you now rerun the script, you will see something like the following in the console (Your output will all be on one line):

    start "Tomcat" "D:\Sun\j2sdk1.4.0_03\bin\java"    -Djava.endorsed.dirs="..\bin;..\common\endorsed"
      -classpath "D:\Sun\j2sdk1.4.0_03\lib\tools.jar;..\bin\bootstrap.jar" -Dcatalina.base=".."
      -Dcatalina.home=".." -Djava.io.tmpdir="..\temp" org.apache.catalina.startup.Bootstrap  start

We now need to repeat the same process for the `shutdown.bat` script. You may be surprised to find that if you simply run it now, you will get the following output. This is because they both call `catalina.bat` only changing a parameter.

    "D:\Sun\j2sdk1.4.0_03\bin\java"    -Djava.endorsed.dirs="..\bin;..\common\endorsed"
      -classpath "D:\Sun\j2sdk1.4.0_03\lib\tools.jar;..\bin\bootstrap.jar" -Dcatalina.base=".."
      -Dcatalina.home=".." -Djava.io.tmpdir="..\temp" org.apache.catalina.startup.Bootstrap  stop

Other than the `start "Tomcat"` at the beginning of the startup line, the two commands are almost identical. The only difference is the parameter passed to the main class at the end. The `start "Tomcat"` portion of the command is only used to spawn Tomcat into its own console. This is not required with the Wrapper so the rest of this example will ignore that portion of the command.

The Wrapper will also handle the quoting of elements of the Java command line that it builds up. so it is not necessary for them to be carried over into the configuration file below.

| Modifying the wrapper.conf File

In order to be able to use this command with the Wrapper, we need to break up its components. Open the `wrapper.conf` file into an editor and make the changes below.

NOTE MEG |  | Where properties are mentioned below, links are provided to their descriptions. Please take the time to review the descriptions of any properties which are modified. In many cases, there are further details on their usage which are not mentioned here.

| Java Executable

First is to extract the java executable and assign it to the `wrapper.java.command` property:

    wrapper.java.command=D:\Sun\j2sdk1.4.0_03\bin\java

| Java Arguments

Most applications provide a number of parameters to the Java executable when it is launched. The Wrapper provides special properties for configuring things like memory, as well as class and library paths. These will be covered below, however any other settings are configured using the `wrapper.java.additional.<n>` series of properties.

The Tomcat command line has several such properties:

    wrapper.java.additional.1=-Djava.endorsed.dirs=..\bin;..\common\endorsed
    wrapper.java.additional.2=-Dcatalina.base=..
    wrapper.java.additional.3=-Dcatalina.home=..
    wrapper.java.additional.4=-Djava.io.tmpdir=..\temp

Note that all quotes have been removed as none of these paths will ever contain quotes. (See the property documentation for details on how to handle cases where a property must contain spaces.)

| Classpath

Next, comes the classpath, which is configured using the `wrapper.java.classpath.<n>` properties. The Wrapper requires that the classpath be broken up into its individual elements. Then, because we will also be making use of the Wrapper, it is necessary to include the `wrapper.jar` file as well:

    wrapper.java.classpath.1=..\common\lib\wrapper.jar
    wrapper.java.classpath.2=D:\Sun\j2sdk1.4.0_03\lib\tools.jar
    wrapper.java.classpath.3=..\bin\bootstrap.jar

| Main Class

The next component of the command used to launch Tomcat is the main class, `org.apache.catalina.startup.Bootstrap`. The main class executed by Java when launched is specified by using the `wrapper.java.mainclass` property. As mentioned above however. Because we are making use of the `WrapperStartStopApp` helper class to start and stop Tomcat, we will specify that class's full name as the main class. The Tomcat main classes are then specified as application parameters below.

    wrapper.java.mainclass=org.tanukisoftware.wrapper.WrapperStartStopApp

| Application Parameters

Application parameters are set using the `wrapper.app-parameter.<n>` properties. Application parameters appear in the Java command line directly after the main class.

When using the `WrapperStartStopApp` helper class, a lot of information needs to be provided about both the "start" and "stop" classes. This information includes each classes' full name, the list of parameters passed to their main methods, and a flag instructing the helper class whether or not it should wait for all non daemon threads to exit before causing the JVM to exit.

To make it clear how all of this information is encoded, we will start by presenting the property values for the Tomcat application several comments have been added above what is normally in the `wrapper.conf` file to make it clearer what the properties mean. We suggest adding these comments to your configuration file as well.

    # The first application parameter is the name of the class whose main
    # method is to be called when the application is launched.  The class
    # name is followed by the number of parameters to be passed to its main
    # method.  Then comes the actual parameters.
    wrapper.app.parameter.1=org.apache.catalina.startup.Bootstrap
    wrapper.app.parameter.2=1
    wrapper.app.parameter.3=start

    # The start parameters are followed by the name of the class whose main
    # method is to be called to stop the application.  The stop class name
    # is followed by a flag which controls whether or not the Wrapper should
    # wait for all non daemon threads to complete before exiting the JVM.
    # The flag is followed by the number of parameters to be passed to the
    # stop class's main method.  Finally comes the actual parameters.
    wrapper.app.parameter.4=org.apache.catalina.startup.Bootstrap
    wrapper.app.parameter.5=true
    wrapper.app.parameter.6=1
    wrapper.app.parameter.7=stop

The start and stop class names should be fairly clear. The first parameter count is required to locate the stop class in the parameter list. The second count is there for consistency.

The flag at parameter #5 above is used to control the behavior of the `WrapperStartStopApp` helper class when it is shutting down the JVM. When the Wrapper sends a JVM shutdown request, `WrapperStartStopApp` responds by calling the main method of the "stop" class with the configured parameters. The flag above controls what happens when that main method returns. If the flag is false then `System.exit(0)` will be called immediately. When true, `WrapperStartStopApp` will wait until all non daemon threads have completed before calling `System.exit(0)`. The later is the behavior which produces the cleanest shutdown for Tomcat. If true is specified, but one or more daemon threads do not complete, the Wrapper will forcibly kill the JVM after its `Shutdown Timeout` has expired. This defaults to 30 seconds.

Non-daemon threads are counted by iterating over all threads in the system and counting those whose isDaemon method returns false. Unfortunately, this count will never actually reach 0 on most JVMs because of the existence of system threads. In most Sun JVMs, there will be one non-daemon system thread. To make the shutdown work correctly, this system thread count needs to be correct. It can be set by defining a `org.tanukisoftware.wrapper.WrapperStartStopApp.systemThreadCount` system property. The default value is 1 thread.

NOTE MEG

If the main method of the stop class calls System.exit from within its main thread, that thread will in effect become deadlocked by that call. The Wrapper avoids a deadlock by detecting this and proceeding with the shutdown after 5 seconds. This may however result in the application failing to shutdown cleanly on its own and should be avoided where possible.

This case can be tested for by enabling the wrapper.debug=true property and then observing the log file during the shutdown process.

| Library Path

In order to use the Wrapper, there is one more property which much be set. The Wrapper makes use of a native library to control interactions with the system. This file `Wrapper.DLL` needs to be specified on the library path supplied to the JVM. Tomcat does not have any native libraries of its own, but if it did, the directories where they were located would also need to be specified. The library path is set using the `wrapper.java-library-path.<n>` properties.

    wrapper.java.library.path.1=..\common\lib

| Putting It All Together

Putting it all together, we get the following:

    wrapper.java.command=D:\Sun\j2sdk1.4.0_03\bin\java

    wrapper.java.additional.1=-Djava.endorsed.dirs=..\bin;..\common\endorsed
    wrapper.java.additional.2=-Dcatalina.base=..
    wrapper.java.additional.3=-Dcatalina.home=..
    wrapper.java.additional.4=-Djava.io.tmpdir=..\temp

    wrapper.java.classpath.1=..\common\lib\wrapper.jar
    wrapper.java.classpath.2=D:\Sun\j2sdk1.4.0_03\lib\tools.jar
    wrapper.java.classpath.3=..\bin\bootstrap.jar

    wrapper.java.library.path.1=..\common\lib

    wrapper.java.mainclass=org.tanukisoftware.wrapper.WrapperStartStopApp

    wrapper.app.parameter.1=org.apache.catalina.startup.Bootstrap
    wrapper.app.parameter.2=1
    wrapper.app.parameter.3=start
    wrapper.app.parameter.4=org.apache.catalina.startup.Bootstrap
    wrapper.app.parameter.5=true
    wrapper.app.parameter.6=1
    wrapper.app.parameter.7=stop

Notice what while this will function correctly on this particular machine, it is highly dependent on the directory structure and platform. By taking advantage of the fact that the Wrapper always sets the working directory to the location of the `Wrapper.exe` file and by making use of a single environment variable, we are able to modify the above properties so that they are completely platform and machine independent. One exception in the case of Tomcat, being the `java.endorsed.dirs` property, which contains a Windows path separator.

    wrapper.java.command=%JAVA_HOME%/bin/java

    wrapper.java.additional.1=-Djava.endorsed.dirs=../bin;../common/endorsed
    wrapper.java.additional.2=-Dcatalina.base=..
    wrapper.java.additional.3=-Dcatalina.home=..
    wrapper.java.additional.4=-Djava.io.tmpdir=../temp

    wrapper.java.classpath.1=../common/lib/wrapper.jar
    wrapper.java.classpath.2=%JAVA_HOME%/lib/tools.jar
    wrapper.java.classpath.3=../bin/bootstrap.jar

    wrapper.java.library.path.1=../common/lib

    wrapper.java.mainclass=org.tanukisoftware.wrapper.WrapperStartStopApp

    wrapper.app.parameter.1=org.apache.catalina.startup.Bootstrap
    wrapper.app.parameter.2=1
    wrapper.app.parameter.3=start
    wrapper.app.parameter.4=org.apache.catalina.startup.Bootstrap
    wrapper.app.parameter.5=true
    wrapper.app.parameter.6=1
    wrapper.app.parameter.7=stop

NOTE MEG

It has been reported that Tomcat 5.0.28 will not work correctly if the bin directory is included in the java.endorsed.dirs system property. This is caused by a change in Tomcat, rather than any issue with the Wrapper. Please modify the above configuration as follows:

    wrapper.java.additional.1=-Djava.endorsed.dirs=../common/endorsed

| Wrapper NT/2000/XP Service Properties

The final step is to set the Windows specific `NT/2000/XP Service Properties` properties. We will just set the properties which should be changed. But there are several others available. See the documentation for details on their usage.

    wrapper.ntservice.name=Tomcat
    wrapper.ntservice.displayname=Tomcat Application Server
    wrapper.ntservice.description=Tomcat Application Server

| Trying It Out

Tomcat can now be run by simply executing the `bin\Tomcat.bat` script. Because of the way the Wrapper sets its current directory, it is not necessary to run this script from within the `bin` directory. Please try running the application once as a console application to verify the configuration before attempting to run it as a service.

Congratulations. Your application should now be up and running.

If you did have any problems, please take a look at the Troubleshooting section for help with tracking down the problem.

by Leif Mortenson

Copyright ©1999-2004 by Tanuki Software. All Rights Reserved. | last modified: