Nov 19 2011

How to run your Java application as a windows service using Commons Daemon Procrun

Category: javaUlrich Palha @ 1:40 am

Overview

Apache Commons Daemon is made of 2 parts. One written in C that makes the interface to the operating system and the other in Java that provides the Daemon API. Both Win32 and UNIX like platforms are supported, but for this article I will only focus on the former and show you how to use Procrun to run your java application as a windows service.

Prerequisites

If  you want to run the sample application, you will need Java 6 and Maven installed. GIT is also recommended.

In a nutshell

1. Download the commons daemon windows binaries and extract the contents
2. Rename prunsrv.exe  to [YOUR_SERVICE_NAME].exe e.g. LoggerService.exe
3. Rename prunmgr.exe to [YOUR_SERVICE_NAME]w.exe e.g. LoggerServicew.exe
4. Create a java class start/stop your service and compile it
5. Run the commands to install your service and start your service

For more details run the sample application and/or see the How It Works section.

Running the Sample Application

1. Using GIT, get the code from JavaWindowsServiceUsingCommonsDaemon.git, or if you don’t have GIT, download the zip  and extract it locally.
2. Open up a command prompt to the directory where the GIT project/zip file was extracted to.
3. Run mvn package to build the project
4. Cd to the bin directory and run Install-Remove-Service.bat install to install the service

a. To verify that the service is installed, open up the services window from the Control panel.

5. Before starting the service from the Services Window, run LoggerService.exe to see the service run in console mode and confirm that everything was installed correctly.
6. You can now start/stop the service from the Services window to confirm that it is working

How does it work

Java Code

The bulk of the code is in the LoggerService class, which is a slightly modified version of the  ProcrunService class. This is the code that you need to write to wrap your application, namely the main, start, stop and run methods.
You can run the LoggerService class from the command line or as a service. The main method is executed when running it from the command line. It handles the case where start/stop are called from different consoles (and hence processes) and so uses a file to communicate between the processes. If, instead, you use Ctrl-C to stop in your version then you can omit this extra code.


Next, the start method, like stop, must conform to the signature public void methodName (String[] args). Your application service will run as long as the start method does not return. The start method in the sample ignores the arguments, starts a thread to run the application and blocks till the thread dies or is interrupted.

public static void start(String[] args) {
   startThread(null); //#1
   while (loggerThread.isAlive()) {
     try {
       loggerThread.join();
     } catch (InterruptedException ie) {
       // Ignored
   }
  }
}

Stop also ignores the arguments and interrupts the service thread to stop the service.

public static void stop(String[] args) {
  if (loggerThread != null) {
    logger.log("Interrupting the thread");
    loggerThread.interrupt();
  } else {
    logger.log("No thread to interrupt");
  }
}

Run is where your application (logger in the sample) is invoked. If interrupted, it will exit the while loop and end the service thread to stop the service.

public void run() {
  ...
  while (stopFile == null || stopFile.exists()) {
    ...
    try {
      logger.log("pausing " + sleepTime + " seconds");
      Thread.sleep(sleepTime * MS_PER_SEC);
    } catch (InterruptedException e) {
      logger.log("Exiting");
      break;
    }
  }
}

Installation Script

The batch file Install-Remove-Service.bat relies on LoggerService.exe which was renamed from prunsrv.exe and can be found in the commons daemon windows binarieszip file. The convention, as stated before, is to rename prunsrv.exe to [YOUR_SERVICE_NAME].exe.

Now let’s take a look at the Install-Remove-Service.bat and how to modify it for your own use.

1. The first line sets SERVICE_NAME defined, which as noted above, should exactly match the name you gave
to the prunsrv.exe

set SERVICE_NAME=LoggerService
set EXECUTABLE_NAME=%SERVICE_NAME%.exe
set EXECUTABLE=%APPLICATION_SERVICE_HOME%\bin\%EXECUTABLE_NAME%

2. Next, you need to provide the fully qualified classes that will be used to start and stop your service. These can be, and usually are the same class.

set CG_START_CLASS=com.ulrichpalha.service.LoggerService
set CG_STOP_CLASS=%CG_START_CLASS%

3. Optionally, you can provide the start and stop methods for the classes defined above. The methods must be of type public void methodName (String[] args). If none are provide, these default to the classes static void main(String[] args) method.

set CG_START_METHOD=start
set CG_STOP_METHOD=stop

4. Optional parameters to the start/stop methods above.

set CG_START_PARAMS=start
set CG_STOP_PARAMS=stop

5. Next provide the full path to the jar that contains your start/stop methods. This is used in 8 below.

set CG_PATH_TO_JAR_CONTAINING_SERVICE=%APPLICATION_SERVICE_HOME%\target\JavaWindowsServiceUsingCommonsDaemon-0.0.1-SNAPSHOT.jar

6. You can also choose to have your service start automatically upon reboot. The default is manual startup.

set CG_STARTUP_TYPE=auto

7. Set this if you want to use a different JVM that is configured in your registry, or if the JVM is not configured in your registry.

set CG_PATH_TO_JVM=%JAVA_HOME%\jre\bin\server\jvm.dll

8. Set the class path to include all jars needed to run your service

set PR_CLASSPATH=%APPLICATION_SERVICE_HOME%;%CG_PATH_TO_JAR_CONTAINING_SERVICE%

9. Next the service is installed with the //IS command. Note that if you use the –DependsOn option e.g. if your service depends on another service like ActiveMQ, then it must be included here as it will NOT work with the //US command

set EXECUTE_STRING= %EXECUTABLE% //IS//%SERVICE_NAME% --Startup %CG_STARTUP_TYPE% --StartClass %CG_START_CLASS% --StopClass %CG_STOP_CLASS%

10.The next series of //US commands update the service configuration

set EXECUTE_STRING= "%EXECUTABLE%" //US//%SERVICE_NAME% --StartMode jvm --StopMode jvm --Jvm %CG_PATH_TO_JVM%

The commons daemon windows binaries also include prunmgr.exe, which by convention is renamed to [YOUR_SERVICE_NAME]w.exe. After the service is installed, you can use it to start/stop your service and change most of the options that were set in the installation script. Below are some screenshots showing the General and Startup tabs.

Questions/Comments

Let me know if you have any questions or comments, especially if you used this to turn your java application into a windows service.

References/Further Reading

Commons Daemon Home Page
Procrun Home Page Provides a detailed description of all Prunmgr and Prunsrv command line options.

Tags: , ,