Gosh provides an alternate way to run command-line Groovy scripts, as well as a simplified way to write Windows Services (WinNT Services) using Groovy. Gosh treats scripts the same, whether they are run from the command-line or as a service (including bindings). You can debug a service by running it from the command-line, and you can also run standard command-line Groovy scripts. There is very little difference between a Groovy script that is intended to be run as a Windows Service and any other Groovy script.
Gosh uses JavaService to do the "heavy lifting" of running a Windows Service. Gosh provides the framework that integrates command-line and service calls with Groovy, and a utility to configure JavaService. The end result is something that is a lot easier to develop with, and ultimately a lot easier to maintain, than Windows Services based on pure Java using JavaService.
This project has been under development since the middle of 2007, but it still should be considered beta software. Some of the details documented here are likely to change over time. We will, of course, attempt to maintain backward-compatibility as much as possible going forward. As of this writing, the following items still need to be addressed (these will be documented in Jira eventually):
|
When installed, Gosh takes over as the default command-line runner for Groovy. This may break existing code. |
The following is required to run Gosh:
Download the project archive and extract the files.
Follow the installation instructions in the .\docs\Groovy Gosh Users Guide.pdf file.
Everything you need (except for ant) to build Gosh is included in the download. Navigate to .\gosh\build and run make.bat.
The Gosh project structure is designed to accommodate complex projects. This may include projects containing multiple JAR libraries and JNI DLLs, where different versions of the same library may exist on one machine. Gosh also supports convenient programmable runtime configuration using - drumroll please - a Groovy script.
One of the key differences between Gosh and the Groovy command-line tools is the emphasis on local, dynamic (runtime) project configuration. The Gosh project model follows a convention similar to what you would see in an application server, like a Tomcat web application. The standard Groovy command-line tools use a global configuration file that applies to all scripts. Although these tools support dynamically changing the classpath, the support is not obvious and somewhat awkward.
Conversely, in Gosh, there is no global configuration at all. JAR files (and also DLLs) are local to the project, and are loaded dynamically. Gosh also supports a local configuration script, written in Groovy, that lets you conditionally define external dependencies. This makes it easy to use different library versions in different projects on the same machine, something which Groovy isn't particularly good at at them moment. It also makes it almost foolproof to distribute an entire Groovy-based application to different machines (xcopy or zip the project).
Note that you can run multiple scripts from a single Gosh project. That includes Windows Services. So you can define, for example, 5 Windows Services and 20 utility scripts in the same project, all using the same set of JAR files and DLLs.
A Gosh project consists of a root folder containing the following:
When you run a Groovy script using Gosh, this is what happens:
Although it looks like a lot is going on here, the logic is actually very streamlined and fast. We've taken great pains to minimize the startup time, and the performance is generally acceptable.
You can initially configure a Windows Service using a simple DOS batch file. Additional configuration is accomplished using Windows administration tools and by directly editing the Windows Registry. The tools are a little crude still, but none of this is very difficult. The documentation here should give you a clear understanding of what is necessary to configure and maintain a Gosh-based Windows Service.
To create (or recreate) a Windows Service, you will need to define a batch file. The batch file will call another batch file, goshservice.bat, with a set of parameters, as in the code example below. Goshservice.bat wraps the call to JavaService.exe, which requires relatively complex command line syntax.
The parameters you pass to goshservice.bat are defined as follows:
Parameter |
Description |
|---|---|
JAVASERVICE_STUB |
Each service needs a renamed copy of JavaService.exe to function. The batch file makes a copy for you, in the location you specify, and uses it to run the service. |
SERVICE_NAME |
The name of the service. Must be unique. |
GROOVY_SCRIPT |
The groovy script to run as a service. |
LOGS_FOLDER |
Standard out and standard err streams will be written to this folder, as files. Note that each service needs a unique folder! |
After you run your batch file, the new service will be accessible for additional configuration from the Windows Services tool. You can rerun the batch file with different parameters, but remember that you will have to redo the manual configuration steps each time.
Most Windows Services require some additional setup. Open the Services tool to finish configuring the service.
At a very minimum, you should verify the configuration settings for the following items:
Once you are done, you can start the service.
Windows stores information about how to run services in the registry. If you want to play around with some of the service settings, and you are comfortable working directly with RegEdit.exe, you can save yourself some time and effort over recreating and reconfiguring the service each time. Note that when you change a registry setting, you will have to restart the service for it to become effective.
The following figure shows typical registry settings for the Gosh Sample Service, included in the sample project. You may notice a number of familiar parameters, such as the classpath and the maximum heap size. These can all be edited, and it is pretty obvious what each one means.

At this point, you are probably wondering what the difference is between a regular Groovy script and Groovy script that runs as a Windows Service.
There is a difference. A Groovy script does a job, and when it is finished, it ends. With a Windows Service, the program doesn't end until Windows asks it to. You can implement this - very simply - by creating a loop that checks a flag to exit.
That is really all there is to it. The service instance is one of the bindings. service.shutdownRequested returns true when Windows has requested that the service be shutdown. service.sleep is a variation on Thread.sleep() that returns immediately if the service has been requested to shut down.
There are several examples in the .\gosh\sample project, included in the build.
The winntservice example implements a complete Windows Service, ready to install and run. To use:
There are also a few command-line examples in the same project.
Gosh automatically creates a number of bindings. All of these are available to your script as variables, both when run as a service and when run from the command-line.
Name |
Type |
Description |
|---|---|---|
args |
List |
When run from the command-line, this contains the command-line arguments. When run as a service, this is an empty list. Gosh does not support passing parameters to a service. |
service |
ServiceRunner |
Provides state information about the service. When running from a command line, the state information never changes, so you have to shut down the process manually. |
systemClassLoader |
GoshClassLoader |
The Java system classloader. This classloader allows you add add JAR files and new classpaths at runtime. |
groovyClassLoader |
GroovyClassLoader |
The Groovy classloader. Note that the parent of the groovyClassLoader is the systemClassLoader. |
fs |
FileSystem |
Supports finding the root path of your project, creating files from the root of your project (rather than the current folder) using relative paths, and changing the java.library.path, among other things. |
scriptFile |
File |
The canonical path to the initial Groovy script. |
The classloader architecture in Gosh differs somewhat from the architecture found in other the other command-line runners for Groovy. Gosh replaces the RootClassLoader with the GoshClassLoader, which is a very simple override of UrlClassLoader.
Gosh is broken into two JAR files. The first, dasboot.jar, contains the minimal number of classes to boot Gosh. This includes the main entry class, the GoshClassLoader, and a small number of supporting classes. Once dasboot.jar is loaded, the system classloader gets set to an instance of GoshClassLoader, and all the other class libraries, including gosh.jar, are added to it.
Once that is done, Gosh creates a GroovyClassLoader, which is a child of the system classloader. This classloader is pointed to the root folder of the project, where it interprets uncompiled Groovy scripts.
In all cases, we have attempted to use the simplest, tightest classloader structure that works. This results in optimal loading and execution times.
The following are known limitations of Gosh: