参考 Daemon - Commons Wiki
ただ、肝心な部分がよく分からなかったので、カスタマイズしてます。 まずは、Daemonインターフェースを実装したクラス。
EngineLauncher クラスが本体で、こいつがEngine(インターフェースを実装した)クラスを起動してメイン処理を実行します。
停止するときも、Engine(インターフェースを実装した)クラスを停止します。
EngineLauncher
Windowsのサービスとして動くときは、windowsServiceを使用します。procrun.exeは、public staticメソッドしか呼ぶことができません。
そして、実行時には引数を渡すことができますので
開始時には、"start"、停止時には"stop"を渡すことで、それぞれstartWindowsServiceとstopWindowsServiceメソッドを呼び出します。
mainメソッドはおまけです。使用しません。
Linuxで使用するjsvcでは、Daemonインターフェースを実装していると、
最初にinitが呼ばれ、続いてstartメソッドが呼ばれます。
停止するときは、"-stop"オプションをつけてjsvcを実行することでstopメソッドが呼び出されます。
- package jp.tanakanbb.blogspot.daemon.service.sample;
- import java.util.Scanner;
- import java.util.concurrent.ExecutorService;
- import java.util.concurrent.Executors;
- import jp.tanakanbb.blogspot.daemon.service.sample.impl.SampleEngineImpl;
- import org.apache.commons.daemon.Daemon;
- import org.apache.commons.daemon.DaemonContext;
- import org.apache.commons.logging.Log;
- import org.apache.commons.logging.LogFactory;
- public class EngineLauncher implements Daemon {
- /**
- * ログ
- */
- private static Log LOG = LogFactory.getLog(EngineLauncher.class);
- /**
- * エンジン
- */
- private static Engine engine = null;
- /**
- * エンジン起動
- */
- private static EngineLauncher engineLauncherInstance = new EngineLauncher();
- /**
- * Executor
- */
- private ExecutorService executor = null;
- /**
- * The Java entry point.
- *
- * @param args
- * Command line arguments, all ignored.
- */
- public static void main(String[] args) {
- // the main routine is only here so I can also run the app from the
- // command line
- engineLauncherInstance.initialize();
- engineLauncherInstance.startWindowsService();
- Scanner sc = new Scanner(System.in);
- // wait until receive stop command from keyboard
- System.out.printf("Enter 'stop' to halt: ");
- while (!sc.nextLine().toLowerCase().equals("stop")) {
- ;
- }
- engineLauncherInstance.stopWindowsService();
- }
- /**
- * Windowsサービスを起動します。
- * サービス登録するときのパラメータは次のようです。
- *
- * <pre>
- * --StartMode=jvm --StartClass=jp.tanakanbb.blogspot.daemon.service.sample.EngineLauncher --StartMethod=windowsService --StartParams=start --StopMode=jvm --StopClass=jp.tanakanbb.blogspot.daemon.service.sample.EngineLauncher --StopMethod=windowsService --StopParams=stop
- * </pre>
- *
- * Windowsサービス、つまりprocrunで起動する場合、実行するメソッドは"public static void"である必要があります。
- * voidでなくてもいいかもしれませんが、戻り値を解釈しないので、voidがいいと思います。
- *
- * @param args
- * Arguments from prunsrv command line
- **/
- public static void windowsService(String args[]) {
- String cmd = "start";
- if (args.length > 0) {
- cmd = args[0];
- }
- if ("start".equals(cmd)) {
- engineLauncherInstance.startWindowsService();
- } else {
- engineLauncherInstance.stopWindowsService();
- }
- }
- /**
- * Windowsサービスの場合のスタートメソッド。
- * Engine#execute()を起動します。
- */
- public void startWindowsService() {
- if (LOG.isDebugEnabled()) {
- LOG.debug("startWindowsService called");
- }
- initialize();
- // don't return until stopped
- executor.execute(engine);
- }
- /**
- * Windowsサービスを停止します。
- */
- public void stopWindowsService() {
- if (LOG.isDebugEnabled()) {
- LOG.debug("stopWindowsService called");
- }
- terminate();
- executor.shutdown();
- }
- /**
- * Implementing the Daemon interface is not required for Windows but is for
- * Linux
- * jsvcでの起動時に最初に呼ばれます。
- * {@link Daemon#init(DaemonContext)}
- */
- @Override
- public void init(DaemonContext arg0) throws Exception {
- LOG.debug("Daemon init");
- }
- /**
- * jsvcでの起動時に、{@link Daemon#init(DaemonContext)}の次に呼ばれます。
- */
- @Override
- public void start() {
- if (LOG.isDebugEnabled()) {
- LOG.debug("Daemon start");
- }
- initialize();
- }
- /**
- * jsvcでの-stopオプション時に呼ばれます。
- */
- @Override
- public void stop() {
- if (LOG.isDebugEnabled()) {
- LOG.debug("Daemon stop");
- }
- terminate();
- }
- /**
- * {@link Daemon#stop()}後に呼ばれます。
- */
- @Override
- public void destroy() {
- if (LOG.isDebugEnabled()) {
- LOG.debug("Daemon destroy");
- }
- }
- /**
- * Engineを初期化します。
- * WindowsでもLinuxでも、最初にこれを呼ぶ必要があります。 Do the work of starting the engine
- */
- private void initialize() {
- if (engine == null) {
- if (LOG.isInfoEnabled()) {
- LOG.info("Starting the Engine");
- }
- engine = new SampleEngineImpl();
- }
- executor = Executors.newSingleThreadExecutor();
- }
- /**
- * Windowsサービス、デーモンを停止します。 WindowsでもLinuxでも、停止時には、これを呼ぶ必要があります。 Cleanly stop
- * the engine.
- */
- public void terminate() {
- if (engine != null) {
- if (LOG.isInfoEnabled()) {
- LOG.info("Stopping the Engine");
- }
- engine.stop();
- if (LOG.isInfoEnabled()) {
- LOG.info("Engine stopped");
- }
- }
- }
- }
Engine
- package jp.tanakanbb.blogspot.daemon.service.sample;
- public interface Engine extends Runnable {
- public void stop();
- public Boolean isStopped();
- }
SampleEngineImpl
さて、第3回では、Windowsサービスへの登録方法とLinuxデーモン化方法を書きたいと思います。
- package jp.tanakanbb.blogspot.daemon.service.sample.impl;
- import jp.tanakanbb.blogspot.daemon.service.sample.Engine;
- import org.apache.commons.logging.Log;
- import org.apache.commons.logging.LogFactory;
- public class SampleEngineImpl implements Engine {
- /**
- * ログ
- */
- private static Log LOG = LogFactory.getLog(SampleEngineImpl.class);
- /**
- * 停止フラグ
- */
- private Boolean isStopped = Boolean.FALSE;
- /**
- * スレッドID
- */
- private String id = null;
- @Override
- public void stop() {
- this.isStopped = Boolean.TRUE;
- }
- @Override
- public Boolean isStopped() {
- return isStopped;
- }
- @Override
- public void run() {
- this.id = String.valueOf(Thread.currentThread().getId());
- while (!isStopped()) {
- if (LOG.isInfoEnabled()) {
- LOG.info("[" + id + "]" + "hoge");
- }
- try {
- Thread.sleep(10000);
- } catch (InterruptedException e) {
- isStopped = Boolean.TRUE;
- if (LOG.isErrorEnabled()) {
- LOG.error(e);
- }
- }
- }
- }
- }
0 件のコメント:
コメントを投稿