Jan 6, 2014

Running a JSF search application as Windows service using Apache Commons Daemon

For my current project I had to prepare a show case to run a JSF based search application locally on a Windows touch device. This article is about running this application together with Apache Solr deployed in a Jetty container as a Windows service using Apache Commons Daemon.

Apache Commons Daemon to the rescue

I knew the Tanuki service wrapper from one of my previous projects, but I also remembered that you need a commercial license to run a 64-bit virtual machine. Since I needed to run large Solr indizes with 20GB+ I was pretty sure I was going to need a 64-bit JVM for heap sizes beyond ~1.4GB.

A quick Google search returned Tanuki and YAJSW on the first result page. The latter one really looked sophisticated with a lot of features, but way more than I would need. In the feature comparison chart the Apache Commons Deamon (ACD) caught my attention. Since I really like using Apache Commons libraries I downloaded the Windows binaries from the website and started using them. The ACD bundle mainly consists of two executables:
  • Prunsrv.exe: the main service application used to run any Java application as a windows service. This executable comes in different versions for all supported architectures (x32, amd64, ia64).
  • Prunmgr.exe: an optional GUI applicaton used to monitor and configure your Java application services.

Installing and Configuring the service

The installation of Jetty 9 together with the required web applications and ACD is really straight forward:
  1. Download the latest stable distribution of Jetty from the project site and unzip the archive to a location of your choice. 
  2. Download and unzip the Apache Commons Daemon distribution to the root directory (JETTY_HOME) of your Jetty installation.
  3. Copy the application WAR as well as the Solr WAR files to the webapps/ directory of the Jetty installation.
Done. Next, we need to configure ACD to install and run Jetty as a Windows service. The best way to do this is using a simple batch file, like the following example:

set JETTY_HOME={{INSERT JETTY INSTALL DIRECTORY}}
set JVM_HOME=%JAVA_HOME%\jre\bin\client\jvm.dll

prunsrv.exe //IS//JettyService ^
        --DisplayName="Jetty 9 Service" --Startup=manual ^
        --Install="%JETTY_HOME%\prunsrv.exe" ^
        --Jvm="%JVM_HOME%" --StartMode=jvm --StopMode=jvm ^
        --JvmMx=512 ^
        ++JvmOptions=-Djetty.port=8080 ^
        ++JvmOptions=-Djetty.home="%JETTY_HOME%" ^
        ++JvmOptions=-DSTOP.PORT=8079 ^
        ++JvmOptions=-DSTOP.KEY=diebartdie ^
        ++JvmOptions=-Dsolr.solr.home="%JETTY_HOME%\data" ^
        --Classpath="%JETTY_HOME%\start.jar" ^
        --LogPath="%JETTY_HOME%\logs" ^
        --StdOutput=auto --StdError=auto ^
        --StartClass=org.eclipse.jetty.start.Main ^
        --StopClass=org.eclipse.jetty.start.Main ^
        ++StopParams=--stop

You will have to adjust the first two lines. In the first line you need to insert the actual Jetty installation directory. The second line sets the path to the JVM DLL to use. ACD can auto detect a installed JVM, but this way you have more control of the actual JVM used.

The rest of the options should be self explanatory. //IS stands for install service, followed by a unique name to identify your service. The service needs to be started manually. The Jetty server will be started in-process using a JVM. Additional system properties are supplied by the ++JvmOptions parameters, like specific Jetty parameters or the Solr home directory for you index data. Careful here: make sure you only specify one system property at a time, otherwise the service won't start later on. A full list of all supported command line parameters can be found here.

Starting and Stopping the service

Once the service is installed, it can be started and stopped in several ways. Of course you can control it using the default Windows service control panel. But there is also the option to start and stop the service using ACD. Remember the service name you specified earlier? You need this name for all the following commands to identify the installed service.

This will execute and run the service:
prunsrv.exe //ES//JettyService 
This will stop the service:
prunsrv.exe //SS//JettyService 

Monitoring the service

The ACD bundle also comes with a handy little management and monitoring application. To start the application you need to execute the following command:
prunmgr.exe //MS//JettyService 
Once started a small Windows tray icon appears, showing the status (running, stopped) of the installed service. Right clicking the icon brings up a menu with options to Start, Stop and Configure the service. The configuration dialog provides easy access to all available service wrapper options.

(1) General service settings

On the first tab (1) you can configure the basic service information as well as control the service. In case you need to change the JVM or some of the system properties you need to switch to the Java tab (2). All of the tabs are pretty self explanatory.

(2) Java specific service settings