Deploying Spring Boot apps as Windows Services

Okezie Arukwe
4 min readAug 3, 2018

--

Spring Boot is cool. It makes application development using java and the spring framework a breeze. It even packages your java app into an executable uber jar with it’s own embedded application server (tomcat) ready to go, giving you a truly self contained micro-service. And when it’s time to deploy your application, all you have to do is open up a command terminal (on windows) and execute

java -jar helloworld.jar

and just like that, your helloworld.jar app is live!

However this has always been my biggest concern with deploying spring boot apps on windows machines. It seems you must have a command window open at all times. What if someone accidentally closes the window while your app is running? That doesn’t sound good. There has to be a better way, We already have an executable uber jar. Why can’t we take it a step further and make it a windows service? At least that way we won’t have to bother about accidental shutdowns, and even if that happens, we have a way of automatically restarting the app.

Enter NSSM

After a bit of googling how to convert java applications to windows services, I finally settled for NSSM (The non-sucking service manager). NSSM is good. Easy to use and straight to the point. You run the command

nssm install <servicename>

and it opens up a nice little GUI wizard to guide you through the service creation process. In my case I had to create a .bat file that executes my spring boot app with java -jar and then install the .batas a service using NSSM.

The Problem

So far my Spring Boot app is running great as a windows service until it’s time to stop the service. For some reason, The service experiences difficulty stopping completely when I click on stop service, and I always have to manually terminate the java windows processes running it.

The Solution: WINSW With Spring Boot Stopper

Leveraging Spring Boot’s admin features, we can expose the SpringApplicationAdminMXBean on the platform MBeanServer to provide us a way of gracefully shutting down our application via JMS. And that’s where Spring Boot Stopper comes in. Spring boot stopper simply calls our application’s JMS shutdown URL to trigger the application shutdown.

Winsw does just what nssm does and more. It enables us wrap any windows executable as a windows service. More importantly, it provides option for specifying command to run when the service is stopped. For a full guide on how to use winsw to wrap an executable check out the project’s github page.

Now what we want to achieve are twofold:

  1. Start our spring boot application with JMS admin features enabled and listening on a particular port. Note this exposes your service to the risk of being stopped by anybody with the right JMS URL and port.
  2. Tell winsw to execute Spring Boot Stopper when we stop the service and pass our application’s JMS port as argument.

Sample winsw configuration to achieve this scenario:

<?xml version=”1.0" encoding=”UTF-8"?>
<service>
<id>hello-springboot-service</id>
<name>Hello World</name>
<description>Hello World Spring Boot Service</description>
<workingdirectory>%BASE%\</workingdirectory>
<logpath>%BASE%\logs</logpath>
<logmode>rotate</logmode>
<executable>java</executable>
<startargument>-Dspring.application.admin.enabled=true</startargument>
<startargument>-Dcom.sun.management.jmxremote.port=54321</startargument>
<startargument>-Dcom.sun.management.jmxremote.authenticate=false</startargument>
<startargument>-Dcom.sun.management.jmxremote.ssl=false</startargument>
<startargument>-jar</startargument>
<startargument>helloworld.jar</startargument>
<stopexecutable>java</stopexecutable>
<stopargument>-jar</stopargument>
<stopargument>SpringBootStopper.jar</stopargument>
<stopargument>54321</stopargument>
</service>

From the configuration XML above you will notice the following among others:

  1. We used the <executable> tag to specify which windows executable to execute when the service starts.
  2. We used <workingdirectory> to define %BASE% (which translates to the folder containing this config) as the working directory for the executable.
  3. We passed a number of <startargument> to the executable. These are used as command line arguments when the service starts. The parameters we passed here are to specify the java .jar file to execute (helloworld.jar, enable JMS, set the JMS port (we are using 54321 as our JMS port), and disable JMS authentication and SSL.
  4. Lastly we used <stopargument>to define what actions to take when the service is stopped. In this case we want winsw to run java -jar SpringBootStopper.jar 54321.

That done, to finally get our helloworld service installed and running:

  1. We create a folder in the location we want our application to reside.
  2. Then we drop the following files in the folder: SpringBootStopper.jar, helloworld.jar, the .xml file containing the configurations from above, and the winsw.exe file.
  3. Next we rename the xml file to helloworld.xml and rename the winsw.exe file to helloworld.exe.
  4. The winsw executable, the configuration file and the application jar file must have the same name for winsw to function properly.
  5. Next we open a command terminal and navigate to the folder containing the files, then execute helloworld.exe install . This creates the windows service with the name specified in the configuration file. A logs folder will also be created in the service root folder.
  6. Lastly we go to the windows service manager to look for our service (Hello World) and start it. The log files generated by application will be in the logs folder.

And that’s it! Our spring boot application has been successfully configured and installed as a windows service.

To stop the application all we have to do is go to the windows service manager and stop the Hello World service.

No more worries about an always open command terminal and accidentally closing the terminal.

Additionally we can also set the windows service as automatic so that it always start whenever windows is restarted. This way we are fairly sure our application will always be running as long as windows is running. Unless some major application runtime error is encountered :D.

Congratulations! You’ve made it to the end of this post!

If you like this post or find it interesting please don’t hesitate to give it a clap or two or three, you know you can just keep clapping, I’ll appreciate. Also feel free to share it!

You can also check out my other posts on Deploying Spring Boot Apps on Azure and Securing Your Azure App With SSL for free.

--

--