Strange Loops

No Matter Where You Go, There You Are

Controlling the Mac With Java (and a Little AppleScript)

| Comments

A couple of weeks ago, a friend forwarded me this presentation about Scripting in the Java Platform. I didn’t get the chance to read through and try out some ideas from the presentation until this weekend. 

My main takeaway from the presentation is developing applications on the Java platform with the right language for the problem. For example, my core business logic (representing the “hard” parts of my architecture) might be built with Java / Scala to provide the additional guarantee of type safety and then utilizing a dynamic language like JRuby, Jython, Groovy et al for scripting, writing unit tests. 

From the presentation I was introduced to a new CLI tool available in Java 6: jrunscript

The -q option shows all the scripting engines available. When I run it on my Mac, 

dc@feynman:jrunscript$ jrunscript -q

Language ECMAScript 1.6 implemention “Mozilla Rhino” 1.6 release 2

Language AppleScript 2.0.1 implemention “AppleScriptEngine” 1.0

ECMAScript was not surprising. I had known that a Javascript interpreter had been embedded in Java 6 for awhile but I found the AppleScript engine interesting. I’ve always thought that AppleScript was a weird language. Weird but useful on the Mac. If I could use AppleScript to extract data out of applications running on my Mac, I could process the data with Java (or another JVM based language like clojure).

For a first pass, I wanted to make a Java + AppleScript program put up a Growl message. After a quick crash course with AppleScript and Script Editor, I had this:

and on the Java side:

There were a couple of gotchas which I’ll summarize.

1) You can’t appear to set arbitrary variables with the various Binding/ScriptContext methods. 

2) To pass values, you have to define a “main” function for the script. That’s what this line was doing

applescript.put(“javax_script_function”, “growlNotification”);

It set growlNotification as the “main” function for the script.

3) growlNotification has 2 parameters. To pass arguments, I needed to define a List interface and add my two arguments there. This sort of made sense since the key we use to set the binding says “ARGV”. When I initially passed my 2 arguments via an array, I received an error message. After a little bit of trial and error, I found that using a List interface worked. The documentation around this is spotty but the use of a List is somewhat intuitive. 

What’s next? Possibly doing this with Clojure and learning more about the various application APIs (aka dictionaries in AppleScript parlance).