Generating a Win32 service executable

Note: The following tutorial assumes you have the Java Runtime Environment (1.2 and above) installed on your machine.

In this tutorial, we are going to learn how to generate a service executable i.e. an executable that could be installed as a service and started/stopped using the Services control panel applet. Noted that services are only available on Windows NT/2K/XP, and not on the Win9x/ME platforms.

The Java program that we are going to use is a simple console program that continually logs the date/time to a file called service.log at 5 seconds interval. The main() method takes a -start argument to start the logging activity, and a -stop argument to stop the logging.

File: Service.java
1:  package examples;
2:
3:  import java.io.*;
4:  import java.util.*;
5:
6:  public class Service
7:  {
8:      static boolean stop = false;
9:      public static void main(String[] args) throws Exception
10:     {
11:         // Start the service
12:         if (args[0].equals("-start"))
13:         {
14:             while(true)
15:             {
16:                 // Append current date/time to log file
17:                 log("Current date/time is " + new Date());
18:
19:                 // Sleep for 5 secs
20:                 Thread.currentThread().sleep(5000);
21:
22:                 // Check for termination
23:                 if (stop)
24:                 {
25:                     log("Service stopped.");
26:                     break;
27:                 }
28:             }
29:         }
30:         else
31:         // Stop the service
32:         if (args[0].equals("-stop"))
33:         {
34:             // Set the termination flag
35:             stop = true;
36:         }
37:     }
38:
39:     /**
40:      * Log given string to file "service.log".
41:      */
42:     static void log(String msg) throws IOException
43:     {
44:         PrintWriter pw = new PrintWriter(
45:             new FileWriter("service.log", true));
46:         pw.println(msg);
47:         pw.close();
48:     }
49: }

Let's generate an executable called service.exe, which will run our examples.Service program.

The Service.java file has been compiled and packaged in examples\examples.jar, along with the other examples. In this subdirectory, you will also find service.njp, along with other .njp files.

Run NativeJ and open the service.njp project. The project defines the following parameters:
Name Value Remarks
Executable
Application type
Console
The executable generated will run as a console program.
Allow application to be installed as service
Yes
The executable generated can be installed and launched as a Win32 service.
Executable filename (32-bit)
services.exe
The filename of the generated executable.
Executable icon
services.ico
The application icon.
Classpath
Classpath
examples.jar
This contains required class files i.e. examples.Service</>.
Application
Main application class
examples.Service
The name of the Java class we wish to run. This class should have a main() method.
Default application arguments
-start
The argument(s) to pass to the main() method when program is started normally.
Service
Service name
Test Service
The service name which will appear in Services when installed.
Install command
-install
The command line argument to install the service. By default, this is -install.
Uninstall command
-uninstall
The command line argument to uninstall the service. By default, this is -uninstall.
Start argument(s)
-start
The argument(s) to pass to the main() method when starting the program.
Stop argument(s)
-stop
The argument(s) to pass to the main() method when stopping the program.

Now, click on File... Generate... to generate the executable. If everything goes well, you will receive a notification that service.exe has been generated.

Now use service -install to install the service. You should see the following message:

C:\Program Files\NativeJ\examples>service -install
Service installed: Test Service

Check the services list using the Services control panel applet. You should see a new entry called Test Service.

Now start Test Service using Services. You should find a file called service.log written to the same directory where services.exe resides. The file contains the date/time logged approximately every 5 seconds.

Current date/time is Sat Jun 01 22:20:04 GMT+08:00 2002
Current date/time is Sat Jun 01 22:20:09 GMT+08:00 2002
Current date/time is Sat Jun 01 22:20:14 GMT+08:00 2002
Current date/time is Sat Jun 01 22:20:19 GMT+08:00 2002
Current date/time is Sat Jun 01 22:20:24 GMT+08:00 2002

Now, stop the service. The last line of service.log should contain the words "Service stopped.", logged by line 25 of Service.java.

If you encounter any errors while starting or stopping the service, launch Event Viewer and look under Application Log for messages attributed to Test Service.

Use service -uninstall to uninstall Test Service.

If you run examples.Service directly using java examples.Service -start, you won't be able to stop it using java examples.Service -stop. That's because they will be running under two different JVM instances, which means the stop flag set to true in line 35 of Service.java will not be reflected in the first JVM instance. The NativeJ-generated executable has no problems with this approach because it actually calls main() with the -stop argument through a separate thread within the same JVM instance, but you won't be able to do so when running using java or javaw.

If you wish to implement a start/stop mechanism that is generic and works under java/javaw (in fact, across all Java-enabled platforms), please refer to Implementing a Generic Start/Stop Mechanism.