In this blog post, I show you how to install a Java application with WinSW as a Windows service. WinSW is an executable binary, which can be used to wrap and manage any custom process as a Windows service.
Demo ¶
First, we need a demo application. I use a simple Quarkus application for this purpose. You can install any Java application as a service. Usually, you install applications that run forever like an HTTP server in this case.
To bootstrap a Quarkus application run this command
mvn io.quarkus:quarkus-maven-plugin:2.5.1.Final:create -DprojectGroupId=com.testlab -DprojectArtifactId=testservice -DclassName="com.testlab.testservice.GreetingResource" -Dpath="/hello"
cd testservice
We use the application as is with just a small change. I want to create a fat jar. A jar with all dependent libraries included.
You can package your application in any way you want. In this case, I prefer the fat jar installation because I only have to copy one file.
Open src\main\resources\application.properties
and insert the following property
quarkus.package.type=uber-jar
Now you can package the application with .\mvnw.cmd package
. You find the jar
in the target folder: testservice-1.0.0-SNAPSHOT-runner.jar
Preparation ¶
You can proceed in different ways. I usually create a new folder where I copy all the files into it that are needed to
run the application as a service. Copy the jar from the target
folder into this directory.
Java ¶
Next, I download the Java Runtime and also copy it into this folder. This is optional. Your service can access a globally installed Java. But I like to have everything contained in one folder and don't have to worry about somebody updating or removing the globally installed Java.
I usually download Java from Adoptium. On the release page, you find the ZIP file with the JDK for Windows.
Download the ZIP file and unzip it into the install folder. I unzip it into the java
subfolder, so the java.exe
is accessible with this path java\bin\java.exe
WinSW ¶
Open the release page of the WinSW project and download the executable suitable for your platform.
https://github.com/winsw/winsw/releases
For this demo installation, I download WinSW.NET461.exe
. WinSW runs on Windows with .NET Framework 2.0, 4.0 or 4.6.1. If you need to install
the service on a Windows without .NET framework, download the core variant WinSW-x64.exe
for 64-bit or WinSW-x86.exe` for 32-bit systems.
Copy the executable also into the folder where your jar resided. Rename the WinSW executable to any name you like.
For this example, I rename it to testservice.exe
. Create an XML with the same base name: testservice.xml
.
Make sure that the exe and XML file are located in the same folder.
Open the XML file and paste the following code into it.
<service>
<id>testservice</id>
<name>Test Service</name>
<description>This is a test service.</description>
<executable>"%BASE%\java\bin\java"</executable>
<arguments>-jar "%BASE%\testservice-1.0.0-SNAPSHOT-runner.jar"</arguments>
<logmode>rotate</logmode>
<stopparentprocessfirst>true</stopparentprocessfirst>
</service>
Check the executables path and arguments. %BASE%
is an environment variable that points to the directory where the WinSW executable is located.
If you want to start the application with a Java that is on the %PATH%
, just use <executable>java</executable>
.
Relevant here is <stopparentprocessfirst>
. This tells WinSW to shutdown the parent process first. In our case this is useful
because the main process opens a console (java
), which can respond to Ctrl+C and will gracefully shutdown the child process (the Java application).
Check out this wiki page to learn more about all the supported options:
https://github.com/winsw/winsw/blob/master/doc/xmlConfigFile.md
Directory structure ¶
The directory structure of my install folder.
testservice.exe
testservice.xml
testservice-1.0.0-SNAPSHOT-runner.jar
java
bin
java.exe
...
conf
legal
lib
...
Installation ¶
With everything in place you install the Windows service with this command
testservice.exe install
The WinSW command supports the following options:
install
: Install the serviceuninstall
: Uninstall the servicestart
: Start the installed servicestop
: Stop the servicerestart
: Restart the servicestatus
: Show the current service status (NonExistent, Started, Stopped)
The service by default is installed with start mode Automatic
. That means Windows starts
the service when it boots up. You can change that with the <startmode>
configuration in the XML file.
<startmode>Manual</startmode>
To test the installation, open http://localhost:8080
in a browser. You should see the default start page of Quarkus.
To test if the graceful shutdown works, stop the service
testservice stop
Open the file testservice.out.log
.
2020-05-06 05:30:52,501 INFO [io.quarkus] (main) Profile prod activated.
2020-05-06 05:30:52,501 INFO [io.quarkus] (main) Installed features: [cdi, resteasy]
2020-05-06 05:30:54,801 INFO [io.quarkus] (main) testservice stopped in 0.032s
We see that the application shutdown gracefully because of the testservice stopped
log entry.
Note that WinSW creates by default three logs files:
<service>.out.log
: Console output from the application (System.out.println
)<service>.err.log
: Error output from the application (System.err.println
)<service>.wrapper.log
: Log output from WinSW itself
That concludes this tutorial about installing any Java applications as Windows Service.
Optionally you could try and create a native image of your application with
GraalVM.
The service installation does not change a lot. You don't need the JRE
anymore and have to change <executable>
accordingly.