Popular posts

Pages

Saturday, October 8, 2016

Create a Windows service out of Java Program using Apache prunsrv / procrun

When I had to run a stand-alone Java application in the background, I used to run it with an "&" and push it to background in Linux. Then I scheduled a cron to check the program every hour and start it if it went dead. This helped me in most scenarios on Linux platform.

However, when I had to write an 'always on' Java application on Windows platform.. I didn't like the idea of an always open cmd console with program output running on it. What if someone closed the cmd window by mistake? What if the server got rebooted for any reason? Yes, to run a program in background I could use javaw.exe instead of java.exe to push it into background as I used to do in Linux. But it didn't appeal me much. Then I stumbled upon this cool thing Apache Commons procrun/prunsrv application to wrap around the program and create a Service out of it. It would run in background, and a service could be set to automatic start... elegant and perfect solution for my problem.

Here is how it got working for me after troubleshoot for many days...now I’m writing it down here, so nobody has to spend so much time again. Refer and use as you like.
  1. Download the prunsrv exe for Windows - link
  2. I had to modify my Main class to suite the prunsrv format, as initially I didn’t plan to use it.
a)      prunsrv.exe takes lot of arguments which you can study here.
b)      I have used the StartMethod and StopMethod as "main" itself, and the StartParams as "start" and StopParams as "stop". These params get passed to main as arg[0]. Now my program looks like below. Notice that 'stopServer()' is static method, that is important.
      public static void main(String[] args) throws Exception {
            EventServer server = new EventServer();
            if ("start".equals(args[0])) {
                 
                  // your program or calls etc etc.

            }
            if("stop".equals(args[0]))
                  stopServer();

      }
     
      public static void stopServer() {
            log(EventServer.class.getSimpleName() + " ENDING SERVER PROGRAM.");
            System.exit(0);
      }

  1. Contents of installapp.bat file, which I run in cmd prompt to install the service. It looks scary, but remember it is a single line. If you study the parameters, all are easily understood. Some parameters have different behavior to accept data like JvmOptions, which you can study on the commons page. Note that prunsrv.exe resides in folder windows\amd64, because my processor is amd64 (you can check by running the command "echo %PROCESSOR_ARCHITECTURE%")
  2. prunsrv.exe //IS//EventGridGateway --DisplayName="EventGridGateway" --Description="Event Grid Gateway" --Install="C:\Users\abhishek\Downloads\commons-daemon-1.0.15-bin-windows\amd64\prunsrv.exe" --Jvm="C:\Program Files\Java\jdk1.8.0_92\jre\bin\server\jvm.dll" --StartMode=jvm --StopMode=jvm --Startup=auto --StartClass=com.eventgridgateway.server.EventServer --StopClass=com.eventgridgateway.server.EventServer --StartParams=start --StopParams=stop --StartMethod=main --StopMethod=main --Classpath="D:\MyStuff\workspace_eclipse\eventgridgateway\target\gatewayserverv2.jar;D:\MyStuff\workspace_eclipse\eventgridgateway\target\bin\hsqldb-2.3.4.jar;D:\MyStuff\workspace_eclipse\eventgridgateway\target\bin\guava-19.0.jar;D:\MyStuff\workspace_eclipse\eventgridgateway\target\bin\sqljdbc41.jar" --JvmOptions=-Dprops="D:\MyStuff\workspace_eclipse\eventgridgateway\target\config.properties" --LogLevel=DEBUG --LogPath="D:\logs" --LogPrefix=procrun.log --StdOutput="D:\logs\stdout.log" --StdError="D:\logs\stderr.log"

  3. Once you run installapp.bat, and if everything is fine, Windows will install your service successfully. Search services.msc with name EventGridGateway. If you need to recreate the service, say any change in above command, first you need to uninstall the service using below command in cmd (Run as Administrator)
  4. After the service is setup, you can run it. For me, it took many attempt before it actually started. The log in D:\logs capture details regarding service and program output (system.out.print)

I have tested this on my machine which is Windows 8, with JRE 1.8