[[scripting]]
= Scripting

Scripting is a feature of {brandname} Server which allows invoking server-side scripts from remote clients.
Scripting leverages the JDK's javax.script ScriptEngines, therefore allowing the use of any JVM languages which offer one.
By default, the JDK comes with Nashorn, a ScriptEngine capable of running JavaScript.

== Installing scripts
Scripts are stored in a special script cache, named '___script_cache'.
Adding a script is therefore as simple as +put+ting it into the cache itself.
If the name of the script contains a filename extension, e.g. +myscript.js+, then that extension determines the engine that
will be used to execute it.
Alternatively the script engine can be selected using script metadata (see below).
Be aware that, when security is enabled, access to the script cache via the remote protocols requires
that the user belongs to the pass:['___script_manager'] role.

== Script metadata
Script metadata is additional information about the script that the user can provide to the server to affect how a
script is executed.
It is contained in a specially-formatted comment on the first lines of the script.

Properties are specified as +key=value+ pairs, separated by commas.
You can use several different comment styles: The `//`, `;;`, `#` depending on the scripting language you use.
You can split metadata over multiple lines if necessary, and you can use single (') or double (") quotes to delimit your values.

The following are examples of valid metadata comments:
[source,javascript]
----
// name=test, language=javascript
// mode=local, parameters=[a,b,c]
----

=== Metadata properties

The following metadata property keys are available

* mode: defines the mode of execution of a script. Can be one of the following values:
** local: the script will be executed only by the node handling the request. The script itself however can invoke clustered operations
** distributed: runs the script using the Distributed Executor Service
* language: defines the script engine that will be used to execute the script, e.g. Javascript
* extension: an alternative method of specifying the script engine that will be used to execute the script, e.g. js
* role: a specific role which is required to execute the script
* parameters: an array of valid parameter names for this script. Invocations which specify parameter names not included in this list will cause an exception.
* datatype: optional property providing information, in the form of
Media Types (also known as MIME) about the type of the data stored in the
caches, as well as parameter and return values. Currently it only accepts a
single value which is `text/plain; charset=utf-8`, indicating that data is
String UTF-8 format. This metadata parameter is designed for remote clients
that only support a particular type of data, making it easy for them to
retrieve, store and work with parameters.

Since the execution mode is a characteristic of the script, nothing special needs to be done on the client to invoke scripts in different modes.

== Script bindings
The script engine within {brandname} exposes several internal objects as bindings in the scope of the script execution.
These are:

* cache: the cache against which the script is being executed
* marshaller: the marshaller to use for marshalling/unmarshalling data to the cache
* cacheManager: the cacheManager for the cache
* scriptingManager: the instance of the script manager which is being used to run the script. This can be used to run other scripts from a script.

== Script parameters
Aside from the standard bindings described above, when a script is executed it can be passed a set of named parameters which also appear as bindings.
Parameters are passed as +name,value+ pairs where +name+ is a string and +value+ can be any value that is understood by the marshaller in use.

The following is an example of a JavaScript script which takes two parameters, +multiplicand+ and +multiplier+ and multiplies them.
Because the last operation is an expression evaluation, its result is returned to the invoker.
[source,javascript]
----
// mode=local,language=javascript
multiplicand * multiplier
----

To store the script in the script cache, use the following Hot Rod code:

[source,java]
----
RemoteCache<String, String> scriptCache = cacheManager.getCache("___script_cache");
scriptCache.put("multiplication.js",
  "// mode=local,language=javascript\n" +
  "multiplicand * multiplier\n");
----

== Running Scripts using the Hot Rod Java client
The following example shows how to invoke the above script by passing two named parameters.

[source,java]
----
RemoteCache<String, Integer> cache = cacheManager.getCache();
// Create the parameters for script execution
Map<String, Object> params = new HashMap<>();
params.put("multiplicand", 10);
params.put("multiplier", 20);
// Run the script on the server, passing in the parameters
Object result = cache.execute("multiplication.js", params);
----

== Distributed execution
The following is a script which runs on all nodes.
Each node will return its address, and the results from all nodes will be collected in a List and returned to the client.
[source,javascript]
----
// mode:distributed,language=javascript
cacheManager.getAddress().toString();
----
