Howto setup a Daemon implementation as windows ser

2019-02-11 10:03发布

问题:

I didn't find any really good example (actually I did not find a single example) on how to register a class that implements the org.apache.commons.daemon.Daemon interface as Windows service.

Do I have to register this implementation using procrun? But than there doesn't seem to be a point in implementing the interface as procrun can register any program as windows service.

Furthermore there seems to be a docu-bug on the procrun page (http://commons.apache.org/proper/commons-daemon/procrun.html):

The description of the --StartMethod parameter states:

Note: in jvm mode, the start method should not return until the stop method has been called.

But further down the page in the "Using Procrun in jvm mode" section:

Note that the method handling service start should create and start a separate thread to carry out the processing, and then return. The start and stop methods are called from different threads.

Am I reading this wrong or is this a little conflicting?? And what would be the correct behavior of a static start(String[] args) method?

Best regards

回答1:

For the records:

Do I have to register this implementation using procrun? But than there doesn't seem to be a point in implementing the interface as procrun can register any program as windows service.

Yes the service needs to be registered in Windows using prunsrv. For example with the following call:

prunsrv.exe //IS//MyTestService ^
    --DisplayName="My Test Service" --Description="Doesn't really do anything" ^
    --Install=@@PATH_TO_PRUNSRV@@\prunsrv.exe ^
    --Startup=manual ^
    --Jvm=auto ^
    --Classpath="@@PUT_FULL_CLASSPATH_HERE@@" ^
    --StartMode=jvm ^
    --StartClass==com.stackoverflow.questions.31556478.ServiceLauncher ^
    --StartParams="@@PUT_ANY_START_ARGUMENTS_HERE@@" ^
    --StartMethod=start ^
    --StopMode=jvm ^
    --StopClass=com.stackoverflow.questions.31556478.ServiceLauncher ^
    --StopMethod=stop

After this the service can be started by

prunsrv //ES//MyTestSevice


And what would be the correct behavior of a static start(String[] args) method?

Testing both variants, only the implementation worked, that stayed in the start-method an did not spawn additional threads. That is a launcher implementation that can be registered with the above prunsrv call would look something like this (without any warranty):

package com.stackoverflow.questions.31556478;

import java.util.Arrays;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ServiceLauncher
{
  private static final Logger LOGGER = LoggerFactory.getLogger(ServiceLauncher.class);

  private static SomeServer mServer;

  public static void start(final String[] args)
  {
    LOGGER.debug("Start called: {}", Arrays.toString(args));

    try
    {
      mServer = new SomeServer(args);
      mServer.start();
    }
    catch (final Exception e)
    {
      LOGGER.error("Terminating due to Exception: ", e);
    }
  }

  public static void stop(final String[] args) throws Exception
  {
    LOGGER.debug("Stop called: {}", Arrays.toString(args));

    synchronized (ServiceLauncher.class)
    {
      if (mServer != null)
      {
        mServer.stop();
      }
    }
  }
}