Monday, March 17, 2014

Native script engine with JSR 233 and ProActive

Behind the cryptic name of JSR 223 lies an interesting feature of Java: the ability to run script engines inside the JVM. You might know dynamic languages that integrate with the JVM using this JSR such as Groovy, Jython or JRuby

At Activeeon, we also use this capability to enable the users to customize parts of a workflow. It is possible to specify pre, post, selection and cleaning scripts using the JSR 223. These scripts are often used to customize the task execution, to setup or clean the environment before running the task.

Last year we introduced a new type of task where you can directly write scripts. It is known as the script task and again leverages the JSR 223 to easily integrate with scripting languages. You can quickly test it on by following the quick start tutorial. It uses the JDK Javascript engine to run the well known Hello World example. 

The JSR 223 is an interesting and quite old (8 years!) specification. It lacks a few features that probably prevented it to become more popular. For instance, there is no way to secure the classes and methods the script runtime has access to, i.e sandboxing. It can become problematic if you intend to run scripts provided by end users as this is a big hole in your system's security. In ProActive, it is not really an issue as users tends to have full access to the system. Most of the installation are dedicated to a small set of power users and not opened to everyone. Then system policies are often in place to prevent abuse. For others it can become a problem and the Riviere Groovy User Group recently organized a hackathon to secure Groovy script execution. The solution is specific to Groovy and goes beyond JSR 223, you can find more details here

As I mentioned at the beginning, several dynamic languages running on the JVM are supported as script engines but surprisingly I could not find any implementation that supported Bash. Sometimes you have existing scripts that you would like to use inside a ProActive workflow. Sometimes Bash is just the right tool to do simple things (pipe to the rescue!). Well Bash is still a scripting language so why not create a JSR 223 implementation for Bash? And by the way could it work for BAT scripts too? 

Ta-dah! Here comes the JSR 223 for native scripts:

It enables you to create a script engine inside the JVM that will handle BAT and Bash scripts. For instance it means that you can write ProActive script tasks like this one: 

The implementation is fairly simple and you can take a look at the source code on Github. The idea is just to take the script, write it to a file and run a native process, Bash or Cmd.exe with this script file as a parameter. My first version passed the script content directly as a parameter but I quickly hit a limitation on the size of the command line… You can also access the output of the script easily using JSR 223. 

You can easily test it by cloning the project, building it and running the script engine directly as shown below: 

One interesting feature of script engines is the ability to pass data in and out, aka bindings. In the case of native scripts, you can define bindings that will be visible from the native script as environment variables. Due to the fact that the native script engine is a native process there is no easy way to modify bindings within the script and get them once the script engine exits. The only output you get from a native process is the exit code. As a workaround, you can always use a file and read it back in your application. A few common Java objects are supported as bindings as detailed here

If you want to integrate this particular script engine in your application, it is just a matter of adding the JAR to the classpath (no external dependencies required). To integrate it with ProActive, you need to have this JAR file on every ProActive node. The script engines are automatically detected and you can access them with names or extensions.

No comments:

Post a Comment