Introduction to BeanShell

The BeanShell scripting language is a thin wrapper around the Java language and runtime system. BeanShell provides convenient scripting functions that reduce the ceremony requirement of Java, but the underlying data types are the same as Java and the object system is the Java runtime. In addition, much of the BeanShell syntax is the same as Java version 1.4 (newer Java language features such as lambda expressions, var args and block comments are not supported).

BeanShell scripts are usually entered in files that have the extension “.bsh”. This is a convention and not a strict requirement. For example, the PIN file is a BeanShell script ending in “.pin”, and BeanShell commands can also be entered interactively at the command prompt.

Let’s start with the classic beginner program that prints a message:

print("Hello world");

To follow along with this exercise enter this line of script into a file named “hello.bsh” that is stored in the scripts directory.

Let’s look at the syntactic elements in this simple command. This script contains a call to a function named ‘print’. The syntax for a function call is the name of the function followed by matching parenthesis. Within the parenthesis are the arguments to the function. The print function takes a single argument, and that is the value to be printed: in this case a literal string “Hello world”. The line ends with a semicolon which marks the end of the statement.

We can execute this program in several ways:

  1. Drag and drop the script file on to the Application Launcher window. This will start up a MapViewer application that will run the script and print the message on the console window. After the script has finished the new MapViewer application will remain active and ready for further commands.

  2. Drag and drop the script file on to the main viewer window of an active Patchworks or MapViewer application. When the script file is dropped it will begin execution in the context of the active application, and you can use method calls to the API to control the application.

  3. By ‘sourcing’ the script in to an active BeanShell interpreter. Both the Patchworks and MapView applications have consoles where you can enter BeanShell commands. The ‘source’ function is used to tell BeanShell to read commands from the file and interpret them as though they were commands that had been typed in.

Let's choose to use the third method to invoke the script. Using the Patchworks application open the Patchworks console window from the Tools menu. Enter the command

source("../scripts/hello.bsh");

This command finds the script from in a location that is located relative to the PIN file that was used to load the model. The result of running this script is that the following message is displayed on the console:

[Note]Print function output

The print function has an interesting behaviour. If the Patchwork script console has not been used the print function will display output on the terminal window that shows the messages from the Patchworks application. However, as soon as the Patchworks console has been opened the then the print function output will always display in the Patchworks console, regardless if the console is visible or not.

In order to always print information to the terminal window use the Java functions System.out.prntln() or System.err.println().

[Important]Pasting text into the console

There are known issues when pasting large amounts of text in to the Patchworks console. For more than a few lines of commands it is best to save these commands in to a script file and then use the source command to load the file.

Pretty much any value can be used as the argument to the print function: strings, numbers, Boolean values, an expression, another function, etc. For example, the following script makes a similar output, but uses an expression to concatenate the two words to print:

firstName = "John";
print("Hello "+firstName);

This example introduces the concept of a variable that is used to hold a value. As mentioned previously, BeanShell has a relaxed syntax where variables names do not have to be declared before they are assigned to. The variable named ‘firstName’ is created in the namespace in the first line, and the value retrieved on the second line.

Variable names are composed of alphanumeric characters plus the underscore and dollar sign characters and are not allowed to start with a number. Upper and lower case are significant, so the names e and E represent different variables. There are a number of reserved words that make up the language that cannot be used for variable names, such as “if else return break for int double float new while public private” (do a web search for Java reserved keywords to get the complete list).

By convention variable names begin with a lowercase letter, with interior word parts being capitalized (known as camel case).. This is a useful convention to follow, although you will sometimes find examples where people did not get the memo.

Just like other languages, a variable must be assigned a value before a value can be retrieved. The following script would be an error if the variable ‘surname’ has not been previously assigned to:

print("Hello "+surname);
surname = "Smith";

For those coming from languages where spaces (Python) and line endings (VBA) are important, it is interesting to note that BeanShell (and Java) do not consider white space to be important. Statements can start anywhere on a line. Indentation is chosen to be visually pleasing but not consequential. Long statements can be continued on multiple lines (with line breaks) as long as the line breaks do not occur within a symbol or within a string literal. Our second example could be rewritten as follows:

firstName = "John"; print("Hello "+
            firstName);