The Method 1 is to use the
WrapperSimpleApp helper class
to launch the application.
This is by far the simplest way to integrate with the Wrapper,
and where possible, it is highly recommended.
There are some things to be aware of when using this method however. When
the Wrapper shuts down the JVM, there is no direct call to an
application requesting that it shutdown cleanly. Rather, the Wrapper
will exit the JVM by calling System.exit()
from within the JVM. If the application has registered its own
Shutdown Hook,
it will be invoked, giving the application a chance to shutdown
cleanly. If on the other hand, a Shutdown Hook is not registered, then
the application will suddenly exit like pressing CTRL-C in the console (command window).
Both cases, with and without a Shutdown Hook,
provide the exact same behavior as if the application was running without the Wrapper.
When integrating with this Method 1 (WrapperSimpleApp helper class),
the WrapperSimpleApp
class replaces an application's main class. This gives the
WrapperSimpleApp class a chance to
immediately initialize the WrapperManager
and register the JVM with the Wrapper. The
WrapperSimpleApp 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 actual main class is called.
The WrapperSimpleApp helper class
is told how to launch the application by passing the application's main class name,
followed by any additional application parameters
to the main method of the WrapperSimpleApp.
Detailed Instructions
This section will walk you through a detailed explanation of
how to configure JBoss
to run within the Wrapper.
Most other applications can be integrated by following the same steps.
Install JBoss
This tutorial will start with a clean install of
JBoss.
We used "JBoss version 6.0.0.Final" so the exact steps may be slightly different
depending on the exact version installed.
JBoss was installed in the
/usr/lib directory,
resulting in a JBoss Home directory of
/usr/lib/jboss-6.0.0.Final.
Installing Wrapper Files
There are four directories which are required to be configured in order to be able to use the Wrapper.
NOTE
Please make sure that you are using the appropriate Wrapper, and
libwrapper.so files which
were built for the platform being run. It sounds obvious,
but the Wrapper Linux version will not work on Solaris for example.
bin directory
The Wrapper is shipped with a shell script (sh)
which can be used to reliably start and stop any Java application
controlled by the Java Service Wrapper.
First, please copy the following files into the JBoss
bin directory:
Rename the script file to reflect the name of the application.
{JBOSS_HOME}/bin/jboss
Now open the script into an editor.
We need to set the long and short names
to reflect that the script is being used to launch JBoss.
You will see two variables immediately after the header of the script.
APP_NAME and APP_LONG_NAME.
Suggested values for these variables are shown below.
The script should not require any additional modification.
However it does assume that
the wrapper.conf file
will be located within a conf directory
(one level up, ../conf/wrapper.conf).
If you wish to place the wrapper.conf file somewhere else,
the WRAPPER_CONF variable in the script
will require appropriate modification.
NOTE
Important! Before proceeding,
please make sure that all files copied into the
bin
directory have their executable bit set.
lib directory
Copy the native library into the JBoss bin/native/lib directory
in case you plan to run 32-bit version of JBoss and the Wrapper or
bin/native/lib64 directory for 64-bit:
{WRAPPER_HOME}/lib/libwrapper.so
NOTE
With version 6, JBoss is utilizing the HornetQ Project, hence to that,
the 2 bin/native/lib* directories are existing.
(Earlier versions of JBoss are not having those 2 directories.)
In this case, please copy the native library to JBoss's lib directory.
Finally you also need to copy the wrapper.jar file to JBoss's lib directory:
{WRAPPER_HOME}/lib/wrapper.jar
The libwrapper.so file is a
native library file
required by the portion of the Wrapper which runs within the JVM.
The wrapper.jar file contains all of the Wrapper classes.
NOTE
Note that the native library follows slightly different naming
conventions on some platforms. Possible names include;
libwrapper.a,
libwrapper.sl,
libwrapper.so,
and libwrapper.jnilib.
In any case, the file should be copied over without changing
the extension.
conf directory
The Wrapper requires a configuration file
"wrapper.conf" for each application.
The standard location for this file is in a conf directory in the application's home directory.
JBoss does not have such a directory by default, so we will need to create one.
Please copy the following template file wrapper.conf.in
into the conf directory of JBoss.
{WRAPPER_HOME}/src/conf/wrapper.conf.in
Rename the file as follows.
Be sure to remove the .in
extension so that the file is named
wrapper.conf.
You should now have:
{JBOSS_HOME}/conf/wrapper.conf
If you wish to relocate the configuration file wrapper.conf, you are free
to do so. You will need to modify the scripts copied
into the bin directory above,
to reflect the new location.
logs directory
The default configuration file wrapper.conf
will place a wrapper.log file
in a logs directory under the application's home directory.
JBoss does not have such a directory by default, so we will need to create one.
You should now have the following directory:
{JBOSS_HOME}/logs
If you wish to place the wrapper.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.
lang directory
Starting with Wrapper version 3.5.0, the Wrapper can be localized.
The language resource files can be found in the
lang directory. JBoss does not have such a directory by default,
so we will need to create one and copy those files to there:
If you wish to place the language resource files "*.mo" to another location,
you will need to edit the wrapper.conf file
and modify the wrapper.lang.folder 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 script to build up the actual command line.
These scripts tend to get quite unwieldy
but in fact, the featured ability to avoid having to work with them is
one of the benefits of working with the Wrapper.
JBoss is launched by default using a script called
run.sh.
It is launched by first changing the current directory to the
bin directory and then run from there.
If you open run.sh into an editor,
you will notice the following lines towards the end of the file:
# Execute the JVM in the foreground
eval \"$JAVA\" $JAVA_OPTS \
-Djava.endorsed.dirs=\"$JBOSS_ENDORSED_DIRS\" \
-classpath \"$JBOSS_CLASSPATH\" \
org.jboss.Main "$@"
JBOSS_STATUS=$?
The majority of the script has the task of collecting system specific information
and storing that information into environment variables.
The lines above then expands all of the collected information
into the final Java command which launches the application.
From looking at the source of the script,
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 script run.sh
by changing it as follows:
# Execute the JVM in the foreground
echo eval \"$JAVA\" $JAVA_OPTS \
-Djava.endorsed.dirs=\"$JBOSS_ENDORSED_DIRS\" \
-classpath \"$JBOSS_CLASSPATH\" \
org.jboss.Main "$@"
If you now rerun the script, you will see something like the
following in the console (Your output will all be on one line):
In order to be able to use the above Java command line with the Wrapper,
we need to break up the command line's components into a configuration file.
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.
Environment Variable:
In order to ease the configuration, it is recommended to store the HOME directory of Jboss and Java
into a environment variable in the configuration file.
This will make the conf file much more readable and eventually easier to maintain in case a directory path gets changed.
If set in the configuration file, the Wrapper will set the environment variables everytime it launches:
First is to extract the Java executable and assign the location path to the
wrapper.java.command
property:
wrapper.java.command=%JAVA_HOME%/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 JBoss 6.0.0.Final command line has already 8 additional Java Argument.
The initial and maximal memory size of the JVM specified by -Xms128m (initial) and -Xmx512m (maximal),
can be defined using the
wrapper.java.initmemory and
wrapper.java.maxmemory properties.
# Initial Java Heap Size (in MB)
wrapper.java.initmemory=128
# Maximum Java Heap Size (in MB)
wrapper.java.maxmemory=512
NOTE
JBoss with version 6 is utilizing internally a MBeanServer Factory based on
org.jboss.system.server.jmx.MBeanServerBuilderImpl,
however this one is incompatible to the default JVM MBeanServerBuilder
(javax.management.MBeanServerBuilder).
So when the Wrapper starts, it would create the MBeanServer using the JVM's default MBeanServer;
when JBoss starts, it also tries to register its MBeans to the MBeanServer,
however because of the incompatibility with the default JVM's MBeanServer,
JBoss will fail to register any MBean.
If you will not need the MBeans provided by the Wrapper,
the shortest resolution on this incompatibility would be to deactivate the Wrapper-sided MBeans
and thus the creation of the MBeanServer.
To disable please set this following property:
JBoss versions prior to 6 do not need this as they are not instrumenting an own MBeanServer Factory, so disabling is not necessary.
If you are running JBoss version 6.* but want to make use of the Wrapper's MBeans.
Please follow the discriptions on the JMX guide.
Notice that the full property was copied directly from the command line without any modifications.
See the property documentation about how to handle properties containing 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:
The final component of the command used to launch JBoss is the
main class, org.jboss.Main.
The main class executed by Java when launched is specified by
using the
wrapper.java.mainclass
property. As mentioned above however.
Because the JBoss main class does not know how to communicate with the Wrapper,
we will set the main class to be the full class name of
WrapperSimpleApp.
The JBoss main class is then specified as the first application parameter below.
Application parameters are set using the
wrapper.app-parameter.<n>
properties. Application parameters appear in the Java command
line directly after the main class. While JBoss does not have
any such parameters, it is still necessary to set one of these
properties. This is because we are using the
WrapperSimpleApp helper class
and as described above, its first parameter is the main class
name of the application being run. in this case,
org.jboss.Main:
wrapper.app.parameter.1=org.jboss.Main
Library Path
In order to use the Wrapper, there is one more property which must be set.
The Wrapper makes use of a native library to control interactions with the system.
This library filelibwrapper.so needs to be specified
on the library path supplied to the JVM.
JBoss 6 also has the native library from HornetQ in the
bin/native/lib* directories for 32/64-bit architectures.
As the libwrapper.so file should have been copied there as well,
there is only one definition necessary.
If you are using another native library file sometime you have to define here subsequently.
The library path is set using the
wrapper.java-library-path.<n>
properties.
For earlier versions of JBoss please use the %JBOSS_HOME%/lib directory.
Putting It All Together
Putting it all together, we get the following:
set.JBOSS_HOME=/home/christian/tanuki/jboss.6.final/jboss-6.0.0.Final
set.JAVA_HOME=/usr/lib/jvm/java-6-openjdk
wrapper.java.command=%JAVA_HOME%/bin/java
# Java Main class.
wrapper.java.mainclass=org.tanukisoftware.wrapper.WrapperSimpleApp
# Java Classpath (include wrapper.jar)
wrapper.java.classpath.1=%JBOSS_HOME%/bin/run.jar
wrapper.java.classpath.2=%JAVA_HOME%/lib/tools.jar
wrapper.java.classpath.3=%JBOSS_HOME%/lib/wrapper.jar
# Java Library Path (location of Wrapper.DLL or libwrapper.so)
#For 32-bit architectures
wrapper.java.library.path.1=%JBOSS_HOME%/bin/native/lib
#For 64-bit architectures
#wrapper.java.library.path.1=%JBOSS_HOME%/bin/native/lib64
# Java Bits. On applicable platforms, tells the JVM to run in 32 or 64-bit mode.
wrapper.java.additional.auto_bits=TRUE
# Java Additional Parameters
# JVM settings
wrapper.java.additional.1=-server
wrapper.java.additional.2=-XX:MaxPermSize=256m
wrapper.java.additional.3=-Dprogram.name=run.sh
wrapper.java.additional.4=-Djava.endorsed.dirs=../lib/endorsed
wrapper.java.additional.5=-Dorg.jboss.resolver.warning=true
wrapper.java.additional.6=-Dsun.rmi.dgc.client.gcInterval=3600000
wrapper.java.additional.7=-Dsun.rmi.dgc.server.gcInterval=3600000
wrapper.java.additional.8=-Djava.net.preferIPv4Stack=true
wrapper.java.additional.9=-Dorg.tanukisoftware.wrapper.WrapperManager.mbean=false
# Initial Java Heap Size (in MB)
wrapper.java.initmemory=128
# Maximum Java Heap Size (in MB)
wrapper.java.maxmemory=512
# Application parameters. Add parameters as needed starting from 1
wrapper.app.parameter.1=org.jboss.Main
Trying It Out
JBoss can now be run by simply executing the script
bin/jboss console.
Because of the way the Wrapper sets its current directory,
it is not necessary to run this script from within the
bin directory.
As you will see if you omit a command,
the scripts shipped with the Wrapper are fairly standard Daemon scripts.
They accept
console,
start,
stop,
restart, and
dump commands.
The start,
stop, and
restart commands
are common to most Daemon scripts and are used to control the Wrapper and its application as a Daemon process.
The status command
can be used to find out whether or not the Wrapper is currently running.
The console command
will launch the Wrapper in the current shell,
making it possible to kill the application with CTRL-C.
The final command, dump,
will send a "kill -3" signal to the Wrapper
causing the its JVM to do a full thread dump.
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.
Advanced
Tuning The Startup
By default the
WrapperSimpleApp
class will wait 2 seconds for the user application's main method to complete.
After that,
it assumes that the application has started and reports back to the Wrapper process.
This is done because many user applications are written with main methods
that do not return for the life of the application.
In such cases, there is no reliable way for the
WrapperSimpleApp class to tell
when and if the application has completed its startup.
If, however, it is known that the application's main method will return
once the application is started,
it would be ideal for the Wrapper to wait until it has done so before continuing.
waitForStartMain System Property:
For main methods that return in this way, the
WrapperSimpleApp
looks for the
org.tanukisoftware.wrapper.WrapperSimpleApp.waitForStartMain
system property.
If it is set to TRUE,
the WrapperSimpleApp
will wait indefinitely for the main method to complete.
Waiting indefinitely is an advantageous option
if it known for sure that the main method will return in a timely manner.
But on the other hand, while it is waiting eternally,
the Wrapper will never give up on the startup process, no matter how long it takes.
So, if there is any chance that this startup could hang, then
the org.tanukisoftware.wrapper.WrapperSimpleApp.maxStartMainWait
system property to set the maximum wait time may be a better option.
For instance, to wait for up to 5 minutes (300 seconds) for the startup main method to complete,
set the property to 300 as follows:
The main methods of many applications are designed not to return.
In these cases, you must either stick with the default 2 second startup timeout
or specify a slightly longer timeout, using the
maxStartMainWait property,
to simulate the amount of time your application takes to start up.
WARNING
If "TRUE" in the waitForStartMain is specified for an application
whose start method never returns, the Wrapper will appear at first to be functioning correctly.
However the Wrapper is actually in a wait status eternally and will never enter a "running" state,
this means that the Windows Service Manager and several of the Wrapper's error recovery mechanisms
will not function correctly.