James Williams
LinkedInMastodonGithub

JSR 223 Scripting API with Griffon

Tags: Griffon

So you would really like to benefit from the features of Griffon but don't exactly know Groovy? One of the previously unexplored areas is JSR 223: Scripting API. In this tutorial, we will use JSR 223 to embed scripts into our application and run non-Groovy code in response to application events.

Getting Started

If you don't have Griffon installed already, go and get it. If you are using Griffon with Java 6, you already have JSR 223 and support for Rhino(which we'll be using for our examples). Alternatively, the concepts apply to any JSR 223 language such as JRuby or Jython.

Scripting API Hello World

For our first foray into Griffon powered by JSR 223, we'll keep it simple and code a basic UI with a label, textfield, and button. Our view looks like this:

application(title:'JSR223Hello', size:[100,200], pack:true, locationByPlatform:true) {
    hbox {
        label('Name')
        textField(columns:25, text:bind(target:model, targetProperty:'name'))
        button(text:'Click', actionPerformed:{controller.hello()})
    }
}

We've also bind to a model property name and invoke a actionPerformed closure on button click. Before we get around to defining the actual hello closure, we have to do a little setup work to initialize the ScriptingEngineManager. I executed the following code in Startup.groovy but it could have been executed earlier if desired:

import javax.script.ScriptEngineManager

Thread.start {
    def model = app.models.JSR223Hello
    model.manager = new ScriptEngineManager()
    model.engine = model.manager.getEngineByName("js")
}

In the above snippet, we retrieve an instance of the model and instantiate the ScriptEngineManager and Javascript engine. Because we retain a instance of the manager, we could theorhetically use several engines concurrently. Now on to the part that actually does something. Given that I'm a relative novice in Javascript and this is a simple demo, our code just retrieves the name typed in the textfield and constructs a Hello, < name > dialog box. Here's the controller with the uninteresting bits cut out:

class JSR223HelloController {
    // these will be injected by Griffon
    def model
    def view

    // ...

    def hello = {
        def js = "importPackage(javax.swing);"+
            "JOptionPane.showMessageDialog(null, 'Hello, ${model.name}');"

        model.engine.eval(js)
    }
}

If you are planning to use several functions, it would probably be best to put them in the resources directory as either a big file or mini-scripts and then evaluate and invoke them on demand.

Please note that Groovy remains the official language of Griffon until otherwise noted. No expressed efforts are planned at this time to improve integration with other languages other than is already provided by JSR 223.