 |
 |
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.
|
 |
 |
 |
 |
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.
|
 |
 |
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.
 |
 |
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.
|
 |
 |
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.
|
 |
 |
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.
|
 |
 |
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.
|
|
 |
 |
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.
|
 |
 |
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
|  |
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.
|
 |
 |
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
|
|
 |
 |
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.)
|
 |
 |
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
|
|
 |
 |
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 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
|  |
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.
|
|
 |
 |
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, 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
|  |
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
|
|
|
 |
 |
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
|
|
|
 |
 |
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.
|
|
|