Java Service Launcher (for Win NT) (JSL 0.99c)

download here or contact the author at  Michael@Roeschter.com

27.12.2002

What is the JSL?
Links
Current version
Changes and previous versions
Will you answer mail asking for support?
Can I contribute or improve JSL?
Requirements
How To start my java programm as a service
Examples
Troublehooting
License
Contact the author
 

What is the JSL?

The Java Service Launcher is a small executable to start JAVA-programs as a Service under Windows NT 4.0. Is is NOT a Java virtual machine.
It's just an utility like javap, javac or javah which will launch a a JAVA application with the help of an installed JVM. Use my mobile if you need help in case of emergencies (production problem, not being able to roll out and so - but please honour time zones - I'm in CET )

Links

Links to other sources for launching java applications as a service.
http://sw-technologies.com/java/ntsvc/
 

Current version

Current version is v0.99c (public release)
Release date: December 27th 2002
Author: Michael Röschter
Download URL http://141.40.138.11/jsl/index.html  or http://www.roeschter.com/index.html

Release policy: The product receives ongoing support, feature enhancements and bugfixes are included from time to time. Every 3-6 months I produce a minor release though I will most probably never do a 1.0 release. I will support new JDKs and platforms (server operating systems only, no XP, no Win98 ). If you report bugs or show stoppers for your project I will generally try to fix them as soon as possible (usually on the next weekend).

NT 4.0 and Win2000 are supported.
The special parameters (-classic -hotspot -client -server ) which allow for a VM selection on command line are supported.
Supported JAVA versions are SUN JRE 1.2, JRE 1.3, JRE 1.4 and IBM JDK 1.3 Works around LOGOFF shutdown bug in all JDKs pre 1.3.1..
All varieties of the virtual maschine should work (classic, JIT, hotspot, server). I will support future versions of the JDK as soon as they are released.
If you would like other JVMs supported please send me a working example of how to start it using C/C++ code.

Changes and previous versions

Release 0.99c Support for redirecting stderr, stdout, Java System.out and System.err is now working. Previously only C stdout and stderr got redirected properly. Please see example jsl.ini for more details. Fixed a minor bug, which created problems when there where spaces in the path to the executable.

Release 0.99b Support for environment variable substitution in config file. Normal Windows style subsitutions should work. E.g. %PATH% Moved helper classes into a package due to JDK 1.4 compiler having problems with default package. Support for pause and continue service manager events. You can simulate and test service stop, pause and continue behavior on the command line by starting with -debug option. Use CTRL-C for stop service, CTRL-BREAK will toggle between pause and continue service.

Release 0.99a Support for redirecting error and output stream to a file. All Java output to System.out and System.err will end there. The kind of error reported to the service manager is now configurable. Non zero error code from the JVM can be configured to be ignored, to be reported back or to result in fatal termination (from the viewpoint of the service manager). Some users requested the later behaviour as it allows for sophisticated WIN2000 service recovery strategies to be triggered by a simple System.exit(1). The location of the executable to be registered as the service can be defined in the .ini file. The location of the .ini files can be passed on the command line. This feature allows for more flexibility in install scripts if multiple services are to be installed.

Release 0.99 Support for stopping JAVA program through a direct call to static method through JNI (in the simplest case a System.exit() ). Tested with IBM JDK 1.3. Supports setting the environment PATH of the service.

Release 0.98 Internal version.

Release 0.97 Supports JDK 1.4. New -run option that does not pass the -Dservice properties. Console window is now switchable with the useconsolehandler option (see jsl.ini example).

Release 0.96 nasty bug that erronously reported unexpected process termination in Win2000 has been removed.

Release 0.95 supports service dependencies. new -configure option to reconfigure the service settings without deinstalling it. The JRE environment can now be configured in the jsl.ini file. A description on how a JRE is selected is given in the FAQ. User account and password to start the service are now configurable. Service start type is configurable.

Release 0.94 works around the infamous LOGOFF bug which stopped the Hotspot VM when a user logged off. I use a workaround which installs a ConsoleControlHandler after
the JVM has been initialized but before the main() method is called. Tested on Win NT 4.0 and Win 2000.
The special parameters (-classic -hotspot -server ) which allow for a VM selection on command line are now supported.
The demo classes and ServiceStopper classes are provided as a .jar archive for ease of use.
The ServiceStopper Thread is started as a deamon Thread for cleaner shutdown.

Release 0.93 will now run with JRE 1.3 release

Release 0.92 will now run with JRE 1.3 beta

Release 0.91 is now debugged against Win 2000. Microsoft subtly changed the StartServiceCtrlDispatcher API call. Null is no longer a valid parameter for a service name. NT 4.0 API states that the service name will be ignored if service is of type SERVICE_WIN32_OWN_PROCESS.

Release 0.9 contained a serious bug. To be precise it would not run (I apologize to all who tried).

Release 0.5 First public release

Will you answer mail asking for support?

Any feedback is welcome. I will happily give e-mail support and feedback as long as you acknowledge that I'm a hard working member of society. I can't guarantee a 2 hour response time and won't care for requests like "help, my project is due tomorrow and I will get fired if I can't get the service running under WIN 2000". You may phone me, too. My timezone is Central European (or so depending on project location). From Monday to Friday I'm working in projects and can not be easily contacted, but you might try on weekends.

Can I contribute to or improve the JSL?

In any way you like. I have no commercial interest in this. The only form of compensation I will give is an invitation to the Oktoberfest or some Biergarten if you happen to travel to munich.

Which software is needed to run the JSL?

NT 4.0 or Win2000. You need a JRE 1.2 or JRE 1.3 beta properly installed. That is, the JRE or JDK must be installed from the installation program, not just copied to the disk (which might suffice to run a java program from the command line). The JSL needs no setup and can simply be copied anywhere. Just note the limitations concerning a network as explained in the troubleshooting section.
 

How To start my java programm as a service

Quick start: Setup:
The jsl executable will look for an ini file with the same name in it's directory. Copy both to a location of your choice (posible where your java app is located).

Initialization file:
The initialization file is both necessary for setup and running the service. Don't remove it after you have installed the service.
It contains parameters for both service setup and java application.

General service settings
This section will be applied when calling -install or -configure

[service]
appname = Telnet Echo
servicename = TelnetEcho
displayname = Telnet Echo

;environment variable substitution is possible in any value
;e.g.
;jrepath=%JAVA_HOME%
;% is escaped by %%

;port used to communicate stop command to JVM
;Must be unique for each JSL instance installed
stopport = 8465

;service dependencies can be added
;as a comma separated string "dep1,dep2"
;dependencies=TinyHttp

;service start type
;auto demand disabled
;default is auto
starttype=auto

;load ordering group
loadordergroup=someorder

;account under which service runs
;default is system
;account=.\administrator

;password for above account
;system need not provide a password
;password=somewpd

;Allocate a console and register a console event handler to catch shutdown events.
;Default is true; options are FALSE TRUE false true YES NO yes no
;This option has two effects:
;1. If active it catches the logoff events and prevents the service from erroneously stopping in this case.
;2. If active it creates a console window if interaction with the desktop is allowd.
;Effect 1 can be achieved in Java 1.3.1 and higher by using the -Xrs option.
;Effect 2 may or may not be desired.
useconsolehandler=false

;Call <stopclass>.<stopmethod> through JNI so stop the JVM.
;This can be used an alternative to the ServiceStopper
;When all three parameters are defined the JSL will try to use JNI to stop the service.
;If not it will use a tcp/ip connection to the stopport.
;The simplest way to use this functionality is to use the Systen.exit() call as specified below.
;Nevertheless you can call any static method in your code.
;The method called is expected to terminate the JVM one way or the other. It can directly
;call System.exit() or make another Thread do it make the main method return.
;The method can return imediately if desired. If the JVM doesn't stop another attempt can be made to
;stop the service at a later time.

;stopclass=java/lang/System
;stopmethod=exit

;Take care to specify the right signature for your method. void System.exit( int code ) has
;the sifnature specified below. void myMethod() has the signature ()V. Please refer to the
;JNI documentation for details.
;stopsignature=(I)V

;Name and signature of service pause method. Will be called on a SERVICE_CTRL_PAUSE event.
;Please note that unless you have configured all pause and continue arguments
;you will not see the pause button enbaled in the service control manager GUI
;pauseclass=TelnetEcho
;pausemethod=pause
;pausesignature=()V

;Name and signature of service pause method. Will be called on a SERVICE_CTRL_CONTINUE event.
;Please note that unless you have configured all pause and continue arguments
;you will not see the pause button enbaled in the service control manager GUI
;contclass=TelnetEcho
;contmethod=cont
;contsignature=()V

;Value of the PATH environement variable being set by the service.
;PATH will remain unchanged if this is empty.
;path=c:\util

;Redirect stdout and stderr to the specified files
;Leave empty for no redirection
;stdout=e:\stdout.log
;stderr=e:\stderr.log

;Redirect JAVA level System.out and System.err to the specified files
;This simply sets new output streams for System.out and System.err after
;the JVM is initialized but before the main method is called.
;You might find that this option has no effect at all for some applications, as the
;JAVA application is of course free to redirect System.out and System.err
;to some other log mechanism.
;Default is no redirection
;Default is over to overwrite file
;systemout=c:\systemout.log
;systemoutappend=no
;systemerr=c:\systemerr.log
;systemerrappend=no

;Behaviour in case of JVM exiting with an error
;Define whether an execption in the main method should be considered an error
;Use this exit code in case of an exception.
;exceptionerrorcode=0

;Desired behaviour for a non zero exit code (including exceptions as specified above)
;Options:
;ignore   terminate without error (default)
;returncode   exit with error code reported by the JVM to to the service manager
;fatal   don't report regular service stop to service manager making it believe
;a fatal error had occured in the service (this is sometimes desirable if fatal error
;recovery mechanisms are in place)
;onexiterror=fatal

;Use this executable for registering the service.
;Default is the executable used for installation
;modulepath=e:\java\test\jsl_0_9_9a\release\jsl.exe
 

Parameters applying to the JVM
This section will be applied on every service start.

[java]
;Path to the java runtime used
;If this option is not used the default from the registry will be used
jrepath=E:\java\jdk13

;working directory
wrkdir=e:\java\test

;the number of paramters passed to the java application
;parameters must be named param00, param01 ...
;Please note that each command line parameter has to go on it's own parameter value here!
;The way the JVM is called in JSL, the JVMexpects a preparsed array of parameters.
; Everything seperated by whitespace on a java command line is broken down into a parameter here. You won't need to care about quotes
;around string containing spaces here. e.g.
;java.exe -cp "c:\program files\test\lib.jar" com.test.Java "test.>"
;becomes
;params = 4
;param00 = -cp
;param01 = c:\program files\test\lib.jar
;param02 = com.test.Java
;param03 = test.>

params = 3
param00 = -cp
param01 = e:\java\test\jsl_0_9_9b
param02 = com.roeschter.jsl.TelnetEcho
[service]
This section is only applied during service installation and removal.
appname =
servicename =
displayname =
stopport = <ip port on which the service manager will signal the java application to shut down. Must be unique if several jsl services run on the machine.>
 

Command line options
Calling jsl.exe without parameters gives an overview of the available options.

-install

Install the service in the NT service manager. Service is not started immediately, though it will start automatically when NT is rebooted.
Start the service from command line with NET START <APPNAME>.

-configure
Will reconfigure

-remove

Remove an installed service. This may fail if the service is still running.
Stop the service from command line with NET STOP <APPNAME>.

-debug

Run the application from command line for debugging purposes. Service need no be installed.

You can simulate and test service stop, pause and continue behavior on the command line by starting with -debug option. Use CTRL-C for stop service, CTRL-BREAK will toggle between pause and continue service.

-run

Run the application from command line purposes. No -Dservice parameters will be passed.

Stopping a service
To allow for orderly shutdown of the java application the service sends a signal to the java application by opening a connection on the port specified as "stopport" in the service ini file.
The most simple way to take advantage of this feature is to use the ServiceStopper class and Stopable interface as presented in the TelnetEcho example. The ServiceStopper will only accept connections from the localhost, so your service cannot be shutdown remotely.
You can avoid implementing the Stopable interface by using the class SimpleStopper.

This is the most simple service which simple does nothing until stopped.

public static main (String[] argv)
{
    ServiceStopper.stop( new SimpleStopper()  );
}

If the functionality supplied by ServiceStopper is insufficient for your needs, you might want to implement your own handler code for stopping the service. The port is passed to the java application via a -Dservice.stop.port=<PORT> parameter which is prepended to the parameters given in the INI file. You can read it back by a call to System.getProperty( "service.stop.port" )
 

Example

For an example of a simple java service see the files: Run jsl without parameters to check if the initialization file is where it is expected.

The out put shoud look like this

JSL Java Service Launcher by Michael Roeschter (Michael@Roeschter.com)
Version 0.99c December, 27th 2002
Command line options:
jsl -install [ini]    to install the service
jsl -configure [ini]  to reconfigure an installed service with new dependencies
jsl -remove [ini]     to remove the service
jsl -debug [ini]      to run as a console app for debugging
jsl -run [ini]        to run as a standalone console app

Initalization file: C:\Java\TEST\jsl_0_9_9c\Release\jsl.ini
jrepath=
dependencies=
dependency=
starttype=auto
account=(null)
password=(null)
loadordergroup=someorder
wrkdir=
appname=Telnet Echo
servicename=TelnetEcho
displayname=Telnet Echo
stdout=
stderr=
systemout=
systemerr=
systemoutappend=no
systemerrappend=no
exceptionerrorcode=0
onexiterror=ignore
stopclass=java/lang/System
stopmethod=exit
stopsignature=(I)V
pauseclass=
pausemethod=
pausesignature=
contclass=
contmethod=
contsignature=
stopport=0
startdelay=0
useconsolehandler=yes
path=
modulepath=
param00=-cp
param01=c:\java\test\jsl_0_9_9c\src
param02=com.roeschter.jsl.TelnetEcho
Java command line:
java -Dservice.stop.port=0 -Dservice.path=C:\Java\TEST\jsl_0_9_9c\Release\ -Dservice.name=TelnetEcho -cp c:\java\test\jsl_0_9_9c\src com.roeschter.jsl.TelnetEcho
StartServiceCtrlDispatcher being called.
This may take several seconds.  Please wait.
Now adjust the classpath setting in the initialization file.

Run jsl.exe -debug after you unpacked the distribution package.
Telnet echo will run a primitive telnet server which will simple echo back any character you try.
Test ist by running your favorite telnet terminal against your localhost.

Now install the service with jsl -install.
Go to the NT service manager and start it up.
Test again and try to shut it down in the service manager.
Uninstall with jsl -remove.

Now nothing should go wrong with your own service.

Troublehooting

Off course there is still a lot that may go wrong.

Which Java Runtime Environment is used when I start the jsl?
JSL attempts to find the JRE in the following location in the order given. For details look into java_md.c,

  1. It reads the jrepath parameter from the configuration file
  2. It loks for a java.dll in the bin directoy colocated with the jsl.exe
  3. It loks for a java.dll in the jre\bin directoy colocated with the jsl.exe
  4. It looks for JRE path in the registry
The service won't start and I can't see why.
Try to start it in debug mode first. Run it as a service only when you are sure that there are no serious bugs in it.

An error is reported when I stop the service under Win 2000 (service stopped unexpectedly)
It's the way win 2000 says that service terminated in a way it did not expect. That's not an a problem with the service, just Win 2000 being a bit overcritical. I'm working on this.

How can I see may standard output.
You might redirect the System.out stream to a file. But that's a hack anyway.
Instead you should use one of the numerous free packages on the web that can do a comfortable logging to a file.

The program did run fine in debug mode but can't find files when run as a service
Don't rely on the standard path when locating files from the service. Always use absolute paths. The service will path it's start path through a java system property.

How can I find out from which directory the service was started and how it is named
The JVM is started with a command line similar to this one.

java -Dservice.stop.port=8465 -Dservice.path=E:\Java\TEST\jsl_0_9\Debug\ -Dservice.name=TelnetEcho -cp e:\java\test\jsl_0_9 TelnetEcho
The -D options can be accessed through the System Properties. Look in class java.lang.System for details.

The program did run fine in debug mode but still does not find the files it needs though I load them from an absolute path.
Drives mounted from a network device are not accessible from a service!
Access them through fully qualified network names.

\\myserver\myfiles\myservice\hello.data

The program did run fine in debug mode but is denied access to the network shares I need
In standard settings the service will run as a system user. Sytem user can't access the network. You need to change the security settings manually in the NT service manager.
There may be other more exotic errors which could result from this.

The service runs fine but I can't stop it. Service manager tells me the stop request failed and I can't stop it using the task manager.
Services can not be stopped forcedly. They must stop themselves. That's what the stopable interface is for.
To get rid of your service you must either restart NT (after you set service starting mode to manual) or use a C debugger to attach to and kill the service.

License

There is no license required and no copyright retained for version 0.9xx of the JSL.

This software is supplied AS IS. Sources are supplied for informational purposes for the experienced developer.

Please note that this means:

Contact the author

Mail to: Michael@Roeschter.com
Phone: (+49) 8161/44426
Mobile: (+49) 160 97826723