Usually, Java applications are run in a terminal on Unix systems. This requires a user account to be logged on to the system at all times and a terminal to be open.

There are several drawbacks to this ranging from security, to system performance, to simply having the risk of a user pressing the wrong key on the terminal and killing the Java application.

The Java Service Wrapper addresses these issues by making it possible to install your Java application as a daemon. It offers automatic detection of the service management tools (also known as init systems) available on your OS, or lets you configure a specific system to use when launching your application as a daemon.

Are you using Windows? Please check our QNA for Windows.

What is a daemon?

UNIX daemon are similar to Windows Services. They allow you to run your application in the background and are automatically launched on system startup.

The problem is that Java on its own cannot be run as a daemon. The user doing something as simple as logging off the machine will cause Java to shutdown.

The Java Service Wrapper not only makes it possible, but makes it easy to run any Java application as a daemon. It also adds advanced failover, error recovery, and analysis features to make sure that your application has the maximum possible uptime.

Simple HelloWorldServer Java Class

For this example, we will be making use of a simple HelloWorldServer application that will run in the background. Please take a look at the full overview of the application to learn how to create and build the HelloWorldServer application for this example.

Wrapping the HelloWorldServer class

The first step in turning our HelloWorldServer class into a daemon is configuring the Java Service Wrapper to run our application. For the majority of applications this can be done without writing any Java code.

Directory structure

The Wrapper is very flexible and can be set up to work with any directory structure. For this example, we suggest a directory structure which is clean and can be reused even for fairly complicated applications. Please recreate the following directory structure under an arbitrary directory of your choice. We will call this root directory $(EXAMPLE_HOME). This is an extension of the directory structure described in the HelloWorldServer overview.

Directory structure:
$(EXAMPLE_HOME)/
$(EXAMPLE_HOME)/bin/
$(EXAMPLE_HOME)/conf/
$(EXAMPLE_HOME)/lang/
$(EXAMPLE_HOME)/lib/
$(EXAMPLE_HOME)/lib/classes/
$(EXAMPLE_HOME)/logs/

Get the Java Service Wrapper

Please download the latest version of the Java Service Wrapper for your OS from the Download page, and extract it into a directory of your choice. We will call the extracted directory $(WRAPPER_HOME).

Copy Wrapper files

The Java Service Wrapper on UNIX consists of four primary components: the Wrapper binary, a jar file, a native library which is used by the jar file, and a shell script which is used to launch the Wrapper and perform actions such as controlling it as a daemon. Please copy these files as follows:

Copy files:
cp $(WRAPPER_HOME)/bin/wrapper $(EXAMPLE_HOME)/bin/wrapper
cp $(WRAPPER_HOME)/lib/wrapper.jar $(EXAMPLE_HOME)/lib/wrapper.jar
cp $(WRAPPER_HOME)/lib/libwrapper.so $(EXAMPLE_HOME)/lib/libwrapper.so
cp $(WRAPPER_HOME)/src/bin/App.sh.in $(EXAMPLE_HOME)/bin/helloworldserver

After that you need to make the script file executable:

chmod +x helloworldserver

License key:

The Standard and Professional Editions of the Java Service Wrapper require a license key to be able to run. The Wrapper is shipped with a simple license key that will let you run the Wrapper for 15 minutes. Please copy that over for now. You can obtain a long term trial license by clicking on the Free Trial button at the top of the page.

Copy the license file:
cp $(WRAPPER_HOME)/src/conf/wrapper-license-time.conf $(EXAMPLE_HOME)/conf/wrapper-license.conf

Wrapper configuration file:

Finally, copy over the default Wrapper configuration file. We will edit it in the next section.

Copy the configuration file:
cp $(WRAPPER_HOME)/src/conf/wrapper.conf.in $(EXAMPLE_HOME)/conf/wrapper.conf

Wrapper Configuration file

Open the $(EXAMPLE_HOME)/conf/wrapper.conf file in the text editor of your choice.

Please locate and modify the following properties.

Configuration file
wrapper.java.command=java
wrapper.java.command.loglevel=INFO

wrapper.java.mainclass=org.tanukisoftware.wrapper.WrapperSimpleApp
wrapper.app.parameter.1=HelloWorldServer

wrapper.java.classpath.1=../lib/wrapper.jar
wrapper.java.classpath.2=../lib/classes

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

wrapper.logfile=../logs/wrapper.log
  • The wrapper.java.command property is used to specify the location of the Java command that will be used. The value that we have specified will be searched in the system path. It is also possible to specify an absolute path.

  • The wrapper.java.command.loglevel property is optional, but it is useful to help debug the Java command line which the Wrapper generates. We recommend that you include this as you get started, but it can be commented out once you have your application working.

  • The wrapper.java.mainclass property is used to specify the main class that is passed to Java when it is launched. This is a point of confusion for new users, but in most cases, this will be one of the Wrapper's helper classes rather than the main class of your application. The Wrapper supports several integration methods, but for this example, we are using the most simple method called Integration Method #1 (WrapperSimpleApp).
    This method makes use of the org.tanukisoftware.wrapper.WrapperSimpleApp helper class to manage the JVM lifecycle and backend communication with the Wrapper. For now, don't worry about this point.

  • The actual main class of our application HelloWorldServer is passed in as the first parameter using the wrapper.app.parameter.1 property. It is possible to pass in additional parameters to HelloWorldServer by adding additional properties with increasing indexes wrapper.app.parameter.2=P1, for example.

    We don't show them here, but it is also possible to add additional Java parameters using the wrapper.java.additional.<n> properties.

  • The next step is to specify the classpath. This is done using the wrapper.java.classpath.<n> properties. We need to have two classpath entries for our application. The first is to include the required wrapper.jar file which includes the Wrapper's helper classes. The second includes the lib/classes directory where our HelloWorldServer class is located.

  • The Wrapper makes use of a native library, libwrapper.so, to implement some of its functionality. Native libraries are not used by many Java applications so you may not have encountered them before. The wrapper.java.library.path.<n> properties are used to specify where these libraries are located. For now, don't worry about this point.

  • The wrapper.logfile property is used to tell the Wrapper where to write its log file.

We have now told the Wrapper how to run our Java application.

One important thing to note about all of the property values is that they are always specified with path values that are relative to the location of the Wrapper binary.

Shell script

Open the $(EXAMPLE_HOME)/bin/helloworldserver shell script file in the text editor of your choice.

Somewhere near the beginning of the file you will see two variables: APP_NAME and APP_LONG_NAME. Please replace the values with the name of your application.

Shell script
# Application
APP_NAME="helloworldserver"
APP_LONG_NAME="Hello World Server"

There are few other variables useful to configure the Wrapper as a daemon, but we will see them a little later in this tutorial.

Running HelloWorldServer in a terminal

The Wrapper has now been set up. Let's start testing our configuration by running the Wrapper in the terminal.

Please open a new terminal and go into our $(EXAMPLE_HOME) directory with the cd command. The Wrapper and our wrapped application can now be started as follows:

bin/helloworldserver console

Note that the location of the configuration file is relative to the location of the Wrapper binary. This is a little counter-intuitive, but it greatly increases the reliability of the Wrapper when launched using different methods.

You should see something similar to the below output after the Wrapper starts:

wrapper  | --> Wrapper Started as Console
wrapper  | Java Service Wrapper Professional Edition 64-bit {version}
wrapper  |   Copyright (C) 1999-2010 Tanuki Software, Ltd. All Rights Reserved.
wrapper  |     https://wrapper.tanukisoftware.com
wrapper  |
wrapper  | --------------------------------------------------------------------
wrapper  | Thank you for your interest in the Java Service Wrapper.
wrapper  |
wrapper  | You are running with a full featured trial License Key which will
wrapper  | allow you to run or restart the Java Service Wrapper as many times
wrapper  | as you like.  Each invocation of the Wrapper will shutdown
wrapper  | automatically after 15 minutes.
wrapper  |
wrapper  | This limited trial License Key is useful for quick configuration
wrapper  | tests on various machines without the need to request a trial
wrapper  | license.  If more time is required, you can also immediately obtain
wrapper  | a one-month Free trial license:
wrapper  |   https://wrapper.tanukisoftware.com/trial
wrapper  |
wrapper  | The Java Service Wrapper requires a License Key to activate the
wrapper  | software.  License Keys can be purchased on the Java Service Wrapper
wrapper  | web site:
wrapper  |   https://wrapper.tanukisoftware.com/purchase
wrapper  |
wrapper  | This trial License Key in intended for testing and development and
wrapper  | should not be used as part of a production environment.
wrapper  | --------------------------------------------------------------------
wrapper  | 
wrapper  | 
wrapper  | Launching a JVM...
wrapper  | Java Command Line:
wrapper  |   Command[0] : /usr/lib/jvm/java-7-openjdk-amd64/jre/bin/java
wrapper  |   Command[1] : -Djava.library.path=../lib
wrapper  |   Command[2] : -classpath
wrapper  |   Command[3] : ../lib/wrapper.jar:../lib/classes
wrapper  |   Command[4] : -Dwrapper.key=sSRU9TooPnyds7IrRI2rFtKRHEgc8E4A
wrapper  |   Command[5] : -Dwrapper.port=32000
wrapper  |   Command[6] : -Dwrapper.jvm.port.min=31000
wrapper  |   Command[7] : -Dwrapper.jvm.port.max=31999
wrapper  |   Command[8] : -Dwrapper.pid=8557
wrapper  |   Command[9] : -Dwrapper.version=3.5.32-pro
wrapper  |   Command[10] : -Dwrapper.native_library=wrapper
wrapper  |   Command[11] : -Dwrapper.arch=x86
wrapper  |   Command[12] : -Dwrapper.cpu.timeout=10
wrapper  |   Command[13] : -Dwrapper.jvmid=1
wrapper  |   Command[14] : org.tanukisoftware.wrapper.WrapperSimpleApp
wrapper  |   Command[15] : HelloWorldServer
jvm 1    | WrapperManager: Initializing...
jvm 1    | Accepting connections on port: 9000

The banner at the top of the log is because we are using a temporary trial license. It points you to where you can get a long term trial license or purchase a license later.

The lines following "Java Command Line:" show all arguments of the command that the Wrapper uses to launch the JVM. It is very useful to resolve problems. Once it is working, please comment out the wrapper.java.command.loglevel property. The rest of this example will assume you have done so.

If you have purchased a license, this is what you would see:

wrapper  | --> Wrapper Started as Console
wrapper  | Java Service Wrapper Professional Edition 64-bit {version}
wrapper  |   Copyright (C) 1999-2010 Tanuki Software, Ltd. All Rights Reserved.
wrapper  |     https://wrapper.tanukisoftware.com
wrapper  |   Licensed to {licensee}
wrapper  |
wrapper  | Launching a JVM...
jvm 1    | WrapperManager: Initializing...
jvm 1    | Accepting connections on port: 9000

You can stop your application at any time by pressing CTRL-C. The Wrapper always keeps a record of why an application was stopped so you will see something like the following in your log.

wrapper  | CTRL-C trapped.  Shutting down.
wrapper  | <-- Wrapper Stopped

Running HelloWorldServer as a daemon

Once the Wrapper configuration has been verified as correct, we are ready to install the Wrapper as a daemon.

Installing the daemon

This can be done using the install command of the shell script as follows.

sudo bin/helloworldserver install

NOTE

Please note that you will need to be root to do so.

You should see something similar to the below output, confirming that the daemon has been installed.

Detected Ubuntu or Debian:
Installing the Hello World Server Application daemon using systemd...
creating default service file...
Created symlink from /etc/systemd/system/multi-user.target.wants/testwrapper.service to /etc/systemd/system/testwrapper.service.

NOTE

The messages may differ depending on the OS and the service management tool used to install the daemon. Same goes with other commands showed below in this page.

Starting the daemon

You can now start your daemon up by using again the shell script file as root.

sudo bin/helloworldserver start

You should see something similar to the below output, confirming that the daemon has been started.

Waiting for Hello World Server Application...
running: PID:17548

This tells that the script is actually requesting the init system to start the daemon and waits until the process is detected running, then prints its PID. After that the terminal will let you input other commands but the Wrapper will still be running in the background.

You may confirm that the Wrapper is running by opening the log file or by using the status command:

bin/helloworldserver status
Hello World Server Application (installed with systemd) is running: PID:17548, Wrapper:STARTED, Java:STARTED

This tells that the Wrapper started and launched the Java application successfully.

Installing and starting the daemon at once

Since version 3.5.28, the script also has the installstart command to perform both an installation and a start at once.

sudo bin/helloworldserver installstart

If the daemon succeeds to install and start, you should see the following output:

Detected Ubuntu or Debian:
Installing the Test Wrapper Sample Application daemon using systemd...
creating default service file...
Created symlink from /etc/systemd/system/multi-user.target.wants/testwrapper.service to /etc/systemd/system/testwrapper.service.
Waiting for Test Wrapper Sample Application...
running: PID:20720

Stopping the daemon

When you are ready to stop the daemon, you can use the stop command of the shell script file as root.

sudo bin/helloworldserver stop

You may confirm that the Wrapper is running by opening the log file or by using the status command:

bin/helloworldserver status
Hello World Server (installed with systemd) is not running.

Restarting the daemon

The daemon can be restarted using the restart or condrestart commands. restart will stop the daemon if it is running and then start it. If the daemon is not running, the command will simply start it. condrestart will restart the daemon only if it is in running state.

sudo bin/helloworldserver restart
sudo bin/helloworldserver condrestart

Pausing and resuming the daemon

Since version 3.5.31, the Wrapper can be paused and resumed using the shell script. But you first need to set it as pausable. This can be done by uncommenting the line "#PAUSABLE=true" (remove the '#' character) located at the top of the script. Note that the daemon needs to be restarted for this property to take effect.

PAUSABLE=true

Just below in the script, you will see the line "#PAUSABLE_MODE=signals" which makes it possible to configure the mode used to pause and resume the daemon. Currently two modes are available:

- 'signals' which uses SIGUSR1 and SIGUSR2 to communicate the pause and resume actions to the Wrapper

- 'file' which uses the command file.

The default value is 'signals' as it is faster to execute and safer since there is no need to care about the permissions of the command file.

PAUSABLE_MODE=signals

Now you may start the Wrapper and run the pause command. The output should look like this:

bin/helloworldserver pause
Pausing Hello World Server.

You may confirm that the Wrapper is indeed paused using the status command:

bin/helloworldserver status
Hello World Server (installed with systemd) is running: PID:7050, Wrapper:PAUSED, Java:DOWN_CLEAN

Then you can resume the application using the resume command:

bin/helloworldserver resume
Resuming Hello World Server.

And confirm that the Wrapper is running again using the status command:

bin/helloworldserver status
Hello World Server (installed with systemd) is running: PID:7050, Wrapper:PAUSED, Java:DOWN_CLEAN

Uninstalling the daemon

The Wrapper is currently configured to start up again when your system is rebooted. As this is a test, you most likely want to remove the daemon as follows:

sudo bin/helloworldserver remove

You should see something similar to the below output, confirming that the daemon has been uninstalled.

sudo bin/testwrapper remove
Detected Ubuntu or Debian:
Stopping Test Wrapper Sample Application...
Test Wrapper Sample Application was not running.
Removing Test Wrapper Sample Application daemon from systemd...
Removed symlink /etc/systemd/system/multi-user.target.wants/testwrapper.service.

Note that the script will first make sure that the Wrapper is not running before uninstalling it.

After uninstalling, the status command should show the following:

bin/helloworldserver status
Hello World Server (not installed) is not running.

Choosing the service management tool

Depending on the platform, there are different systems with which a daemon can be installed and run. For example on Linux systemd, upstart, and initd are commonly used. On AIX, a daemon can be installed with either SRC or initd.

The table below gives an overview of the different service management tools used by the Wrapper to install a daemon depending on the platform. Those listed on the top are more advanced and generally preferred.

Linux
AIX
MacOSX
FreeBSD
Other UNIX platforms
SystemdSrcLaunchdrc.dInit.d
UpstartInit.d
Init.d

Depending on the distribution (Linux), the OS version and the OS configuration, some of the service management tools listed above may not be installed. The Wrapper shell script, however, has the ability to detect which service management tool(s) is (are) present on the machine. Whenever several tools are possible for a given OS (i.e on Linux and AIX), the Wrapper will automatically choose the recommended one in a priority order. For example, on Linux, systemd is preferred to upstart, which itself is preferred to initd. This default behavior has been introduced in version 3.5.31 and is configured by the following line located near the top of the script:

SERVICE_MANAGEMENT_TOOL=auto

You may want to explicitly specify another service management tool than the one automatically chosen by the Wrapper. In this case, you would set the above property with the name of another system.

SERVICE_MANAGEMENT_TOOL=initd

NOTE

Note that the daemon needs to be reinstalled for this property to take effect.

You should see the following output after reinstalling the service:

sudo bin/helloworldserver install
Detected Ubuntu or Debian:
Installing the Hello World Server daemon using init.d..
 Adding system startup for /etc/init.d/helloworldserver ...
   /etc/rc0.d/K20helloworldserver -> ../init.d/helloworldserver
   /etc/rc1.d/K20helloworldserver -> ../init.d/helloworldserver
   /etc/rc6.d/K20helloworldserver -> ../init.d/helloworldserver
   /etc/rc2.d/S20helloworldserver -> ../init.d/helloworldserver
   /etc/rc3.d/S20helloworldserver -> ../init.d/helloworldserver
   /etc/rc4.d/S20helloworldserver -> ../init.d/helloworldserver
   /etc/rc5.d/S20helloworldserver -> ../init.d/helloworldserver

Following that, the daemon will use initd the next time it starts.

WARNING

If the specified service management tool is not present on the system or if the installation failed for some reason, the shell script will return an error code of 1.

When your tests are finished, don't forget to uninstall the daemon to prevent it from starting on the next system boot.

Reference: Launching your application with the Wrapper