■ はじめに
JavaをWindowsサービス化する方法を調べてみたら、 以下「JavaをWindowsサービス化するには」のような方法があった で、今回、「【1】 Apache Commons Daemon を使う」を扱う
補足:.NETでWindowsサービス化するには
* 以下の関連記事を参照。Windowsサービス ~ Hello World編 ~
https://blogs.yahoo.co.jp/dk521123/37948659.html
■ JavaをWindowsサービス化するには
【1】 Apache Commons Daemon を使う << 今回は、これを扱う 【2】 Java Service Wrapper を使う 【3】 winsw を使う etc...
【2】 Java Service Wrapper を使う
http://www.tanukisoftware.com/ja/wrapper.php【3】 winsw を使う
* 作者は Jenkins の川口さん * Java だけでなく使える模様 => 本当は、こっちを試したい。時間をある時にそのうち。。。https://kiririmode.hatenablog.jp/entry/20170407/1491490800
■ Apache Commons Daemon を使ったサービス作成方法
[1] 以下のサイトから、必要なモジュールをダウンロードするcommons-daemon
http://commons.apache.org/proper/commons-daemon/download_daemon.cgi
http://ftp.jaist.ac.jp/pub/apache//commons/daemon/binaries/windows/
commons-logging
https://commons.apache.org/proper/commons-logging/download_logging.cgi
~~~~~~ + commons-daemon-1.1.0-bin.zip + commons-daemon-1.1.0-bin-windows.zip + commons-logging-1.2-bin.zip ~~~~~~ [2] Windowsサービス用の処理をコーディングし、JARファイルを出力する => 今回は、JARファイルはEclipseの機能で、プロジェクト名を右クリックし、 [Export]-[Java]-[JAR file]でJARファイルを作成した [3] Windowsサービス用のインスール/アンインストール用のバッチファイルを作成する [4] 64ビットOSの場合「commons-daemon-1.1.0-bin-windows/amd64/prunsrv.exe」を 「【サービス名】.exe」にリネームする => 32ビットOSの場合は、prunsvr.exeを【サービス名】.exeにprunmgr.exeを 【サービス名】w.exeにそれぞれリネーム [5] ファイルを配置する(以下の「■ サンプル」の「ファルダ構成」を参照) [6] Windowsサービス用のインスール用のバッチファイルを起動する [7] Windowsサービスを開始する
■ サンプル
* Windowsの場合、開始・終了用のstaticメソッドが必要
Windowsサービス用Javaソース
HelloWorldServiceLauncher.javapackage com.sample.service; import java.util.Arrays; import java.util.Scanner; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class HelloWorldServiceLauncher { private static Log LOG = LogFactory.getLog(HelloWorldServiceLauncher.class); private static IService service = null; private static HelloWorldServiceLauncher instance = new HelloWorldServiceLauncher(); private ExecutorService executor = null; private static Scanner scanner; public static void main(String[] args) { if (args != null) { LOG.debug("Param : " + Arrays.toString(args)); } HelloWorldServiceLauncher.start(null); scanner = new Scanner(System.in); LOG.debug("Enter 'stop' to halt: "); while (!scanner.nextLine().toLowerCase().equals("stop")) { ; } HelloWorldServiceLauncher.stop(null); } public static void start(String[] args) { if (args != null) { LOG.debug("Param : " + Arrays.toString(args)); } instance.initialize(); } public static void stop(String[] args) { if (args != null) { LOG.debug("Param : " + Arrays.toString(args)); } instance.terminate(); } public void initialize() { if (HelloWorldServiceLauncher.service == null) { HelloWorldServiceLauncher.service = new HelloWorldService(); } this.executor = Executors.newSingleThreadExecutor(); this.executor.execute(HelloWorldServiceLauncher.service); } public void terminate() { if (HelloWorldServiceLauncher.service != null) { HelloWorldServiceLauncher.service.stop(); } if (this.executor != null) { this.executor.shutdown(); } } }IService.java
package com.sample.service; public interface IService extends Runnable { public void stop(); public Boolean isStopped(); }HelloWorldService.java
package com.sample.service; import java.io.FileWriter; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class HelloWorldService implements IService { private static Log LOG = LogFactory.getLog(HelloWorldService.class); private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); private Boolean isStopped = Boolean.FALSE; @Override public void run() { while (!this.isStopped()) { LOG.debug("[ENTER]" + dateFormat.format(new Date())); try { // ★ここに処理を書く(今回はダミー処理を書いておく)★ try (FileWriter fileWriter = new FileWriter("C:\\temp\\hello-world.txt", true);) { fileWriter.write(dateFormat.format(new Date()) + " : Hello World!\n"); } catch (IOException ex) { LOG.error("IO Error", ex); } Thread.sleep(5_000L); } catch (InterruptedException ex) { LOG.error("Error", ex); this.isStopped = Boolean.TRUE; } LOG.debug("[EXIT]" + dateFormat.format(new Date())); } } @Override public void stop() { this.isStopped = Boolean.TRUE; } @Override public Boolean isStopped() { return this.isStopped; } }
Windowsサービス用のインスール/アンインストール用のバッチファイル
install.batset EXEC_DIR=%~dp0 echo %EXEC_DIR% set CLASSPATH_DIR=%EXEC_DIR%lib echo %CLASSPATH_DIR% set CLASSPATH=%EXEC_DIR%HelloWorldServiceLauncher.jar;%CLASSPATH_DIR%commons-daemon-1.1.0.jar;%CLASSPATH_DIR%commons-logging-1.2.jar;%CLASSPATH_DIR%\*; echo %CLASSPATH% set JVM_PATH="C:\Program Files\Java\jdk1.8.0\jre\bin\server\jvm.dll" set INSTALL_PATH=%EXEC_DIR%HelloWorldServiceLauncher.exe echo %INSTALL_PATH% HelloWorldServiceLauncher //IS//HelloWorldService --DisplayName="Hello World Service" --Description="Demo for Hello World Service" ^ --Install %INSTALL_PATH% --Startup auto --Jvm %JVM_PATH% --StartMode jvm --StopMode=jvm ^ --Classpath=%CLASSPATH% --StartClass com.sample.service.HelloWorldServiceLauncher --StartMethod start --StartParams Hello#World#Start ^ --StopClass com.sample.service.HelloWorldServiceLauncher --StopMethod stop --StopParams Hello#World#Stop ^ --LogPath=%EXEC_DIR%logs --LogLevel=DEBUG ^ --StdOutput=auto --StdError=auto ^ pauseuninstall.bat
HelloWorldServiceLauncher //DS//HelloWorldService pause
ファルダ構成
C:\temp\ + hello-world-service + HelloWorldServiceLauncher.exe (prunsrv.exe をリネーム) + HelloWorldServiceLauncher.jar + install.bat + uninstall.bat + lib + commons-daemon-1.1.0.jar + commons-logging-1.2.jar
参考文献
http://tanakanbb.blogspot.com/2012/03/commons-daemon-1.htmlhttp://tanakanbb.blogspot.com/2012/04/commons-daemon-2.html
http://tanakanbb.blogspot.com/2012/04/commons-daemon-3.html
http://kisk0419.hatenablog.com/entry/2013/03/05/175816