I am a lazy guy. I like my systems to be capable of handling some problems that can be occuring by themself. At the project I am currently working we are using the application performance management (APM) solution from CA Introscope to monitor a highly distributed and big software system for a big automobile company. In order to capture the monitoring information, Introscope uses different agents. One type of agent is the so-called EPAgent that allows to integrate information revelevant for monitoring from arbitrary sources. The EPAgent is a small Java application that acts as scheduler for scripts or even Java programs. The scripts usually provides key-value pairs, that the EPAgent interprets as metric name and value. This information is then send to the central server.
But unfortunately this agent does not come with a way to integrate it as service in a windows based environment. I had a look at various tools to integrate a java application with windows services and got stuck a few times. Finally I managed to integrate the EPAgent using Apache Commons procrun (http://commons.apache.org/proper/commons-daemon/procrun.html). Procrun is a set of applications that allow Windows users to wrap (mostly) Java applications as a Windows service. With procrun the service can be started as soon as the systems starts up. Nice for lazy guys like me, so I do not have to check all the time to see if the agent is running or not.
Within procrun, the executable prunsrv.exe is responsible for creating a service for Java applications, so we have to look closer at this program. Note that procrun comes with prunsrv.exe for 32bit and 64bit environments, so choose the right one or you encounter strange errors messages. The list of options for prunsrv.exe is immense (have a look at http://commons.apache.org/proper/commons-daemon/procrun.html if you do not believe me).
Without further ado, here is the template for running an EPAgent as Windows service. Simply fill out the template and copy the text to a file called install.cmd and execute it to integrate the service and start it.
SET SERVICE_NAME=[[Name of the service]]
SET DISPLAY_NAME="[[Display Name of the service]]"
SET DESCRIPTION="[[Description of the service]]"
REM Set this if JAVA HOME is not found! and add --JavaHome=%JAVAHOME% to prunsrv call.
REM SET JAVAHOME="...\jre"
REM we first try to stop an existing service
sc stop %SERVICE_NAME%
REM then we delete this service. This allows us to call this installation script multiple times
sc delete %SERVICE_NAME%
[path-to-prunsrv]\prunsrv.exe %COMMAND% %SERVICE_NAME% --Startup=auto --DisplayName=%DISPLAY_NAME% --Description=%DESCRIPTION% --Classpath=%CLASSPATH% --StartPath=%STARTPATH% --StartMode=jvm --StopMode=jvm --StartClass=%STARTCLASS% ++JvmOptions=%JVM_OPTION% --StopClass=%STOP_CLASS% --StopMethod=%STOP_METHOD% ++StopParams=%STOP_PARAMS%
REM then we can start the service
sc start %SERVICE_NAME%
So a little bit more of explanation. The interesting part is the call to prunsrv.exe close to the end. As you see this uses the parameters defined at the beginning of the script.
- SERVICE_NAME: The internal name the service is associated with. This is used to start and stop the service.
- DISPLAY_NAME: The name that is displayed in the Windows service view.
- DESCRIPTION: A description that is shown with the Windows service view.
- CLASSPATH: Now it gets tricky. If you use a wrong classpath the service won’t run. Also please note that the classpath entries are relative to the STARTPATH. If you have additional plugins for your EPAgent you need to add them here.
- STARTPATH: The path to the root folder of the EPAgent installation.
- STARTCLASS: The name of the class to start
- JVM_OPTION: With the option epagent.properties you can provide the EPAgent with the configuration file that it should use when starting up.
- STOP_CLASS, STOP_METHOD, STOP_PARAMS: Now it is getting tricky. procrun allows to easily just define that the JVM should be stopped when the service stops (By default procrun then tries to stop the main method). This does not seems to work though for the EPAgent. Thus I added a neat little trick and instructed procrun to kill the JVM by executing java.lang.System.exit(0).
Note that I am not a Windows scripting expert. This script worked for me and different Windows environments. Improvements are always welcome 🙂