Link Details

Link 197429 thumbnail
User 310560 avatar

By mpassell
via blog.grovehillsoftware.com
Published: Jun 29 2009 / 05:16

I recently worked with my client to add an extension mechanism (in this case, a very simple plug-in system) to their intranet Java web application. It allows professional services staff to extend the app as needed. Our first thought was to go with JavaScript via the Java Scripting API, but we ended up using Groovy instead.
  • 33
  • 0
  • 1859
  • 509

Comments

Add your comment
User 313761 avatar

bodhuin replied ago:

1 votes Vote down Vote up Reply

Why not simply use the Java Scripting API as well for Groovy ?
Add as library: groovy-all-1.6.3.jar for instance (the one for embbeded use).

Use it Like:


import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptEngineManager;
...
ScriptEngineManager sme = new ScriptEngineManager();
se = sme.getEngineByName("groovy");
try {
System.out.println(se.eval("(1..10).sum()"));
se.put("first", "HELLO");
se.put("second", "world");
System.out.println(se.eval("first.toLowerCase() + second.toUpperCase()"));
} catch (ScriptException ex) {
Logger.getLogger(Scripting.class.getName()).log(Level.SEVERE, null, ex);
}
String fact = "def factorial(n) { n == 1 ? 1 : n * factorial(n - 1) }";
try {
se.eval(fact);
Invocable inv = (Invocable) se;
Object[] params = {new Integer(7)};
Object result = inv.invokeFunction("factorial", params);
System.out.println(result);
} catch (NoSuchMethodException ex) {
Logger.getLogger(Scripting.class.getName()).log(Level.SEVERE, null, ex);
} catch (ScriptException ex) {
Logger.getLogger(Scripting.class.getName()).log(Level.SEVERE, null, ex);
}


User 310560 avatar

MatthewPassell replied ago:

1 votes Vote down Vote up Reply

Thanks for the feedback!

When I was first experimenting with JavaScript, I used a similar approach to that. I implemented the functions in JavaScript necessary to satisfy the ScriptingInterface and then used the Invocable.getInterface() method (see http://java.sun.com/javase/6/docs/api/javax/script/Invocable.html ) to get an Object (probably a dynamic proxy) that supposedly implemented the interface. There were a few problems with this approach. If the script failed to include a function or otherwise contained mistakes, I didn't find that out until trying to call the associated method, making it impossible to provide useful validation. Also, the interface grew to have 10 methods, most of which had obvious and simple default implementions. However, there was no way for the scripted code to extend an abstract class, except perhaps using some mixed Java/JavaScript hackery.

When I switched to Groovy and started using the GroovyClassLoader directly, I immediately got useful compilation error messages with descriptions and line numbers. I was also able to write Groovy classes that extended an abstract adapter class providing default implementations for 9 out of the 10 methods - a major time saver for most scripts. It's possible that the ScriptEngine implementation for Groovy would have more responsive error reporting than the one for JavaScript, but I don't believe I would have been able to extend an abstract class.

--Matt

Add your comment


Html tags not supported. Reply is editable for 5 minutes. Use [code lang="java|ruby|sql|css|xml"][/code] to post code snippets.