« November 2009
SunMonTueWedThuFriSat
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
     
       
Today
XML

Blog::Navigation

GetJava Download Button
Get the Source
Personal Blog

Blog::Referers

Today's Page Hits: 159

Powered by Roller Weblogger.
« JVM Talks... | Main | Half empty or half... »
20070321 Wednesday March 21, 2007

Script Beans?

When we expose Java objects (or other language objects!) to a scripting language, we may want flexibility. Most scripting languages on the Java platform support JavaBean conventions. For example, JavaScript allows property style access for "getXXX" methods. Some language engines (for example, Groovy) treat java.util.Map's specially to provide map.key_name style access. But, we may want more flexiblity in addition to bean conventions. For example, we may want java.sql.ResultSet to be accessed with the natual obj.column_name syntax. But, instead of such ad-hoc special cases, we may want to have a generic way.

Also, while jsr-223 has API support to call a specific script function or method, there is no way to "reflect" on script objects. For example, you can't find out the all methods and properties supported by a specific script object. There is no engine independent way to reflect script objects - you have to use Scriptable interface for Rhino , GroovyObject interface for Groovy and IRubyObject interface for JRuby and so on.

HotSpot Serviceability Agent (SA) is a core dump/hung process debugger for HotSpot JVM. It supports JavaScript based command line interface - much like dbx/gdb's shell-like scripting interface. I had used Mozilla Rhino API directly to implement that -- because it was done before the advent of jsr-223. I am porting this to use jsr-223 API. Previously, I had used Scriptable, ScriptableObject and Function interfaces from Mozilla Rhino. I had changed this to use the following interfaces:



ScriptObject

/**
 * Any Java object supporting this interface can be
 * accessed from scripts with "simpler" access pattern.
 * For example, a script engine may support natural
 * property/field access syntax for the properties exposed
 * via this interface. We use this interface so that we
 * can dynamically add/delete/modify fields exposed to
 * scripts. Also, script engines may expose this interface for
 * it's own objects.
 */
public interface ScriptObject {
  // special value to denote no-result -- so that
  // null could be used as proper result value
  public static final Object UNDEFINED = new Object();
  // empty object array
  public static final Object[] EMPTY_ARRAY = new Object[0];

  /*
   * Returns all property names supported by this object.
   * Property "name" is either a String or an Integer".
   */
  public Object[] getIds();

  /**
   * Get the value of the named property.
   */
  public Object get(String name);

  /**
   * Get the value of the "indexed" property. 
   * Returns UNDEFINED if the property does not exist.
   */
  public Object get(int index);

  /**
   * Set the value of the named property. 
   */
  public void put(String name, Object value);

  /**
   * Set the value of the indexed property. 
   */
  public void put(int index, Object value);

  /**
   * Returns whether the named property exists or not.
   */
  public boolean has(String name);

  /**
   * Returns whether the indexed property exists or not.
   */
  public boolean has(int index);

  /**
   * Deletes the named property. Returns true on success.
   */
  public boolean delete(String name);

  /**
   * Deletes the indexed property. Returns true on success.
   */
  public boolean delete(int index);
}



Callable.java

/**
 * This interface is used to represent "function/method" valued
 * properties in ScriptObjects.
 */
public interface Callable {
  /**
   * Call the underlying function passing the given
   * arguments and return the result.
   */
  public Object call(Object[] args) throws ScriptException;
}



Just to be sure: please note that I am thinking of ScriptObject and Callable as two way interfaces. Script engines would expose it's objects (all or some of it's objects) as ScriptObjects. Also, from Java code we can expose ScriptObject objects to script engines and the engines will support special obj.field and obj.method(...) syntax in the respective language.

Why can't we just use BeanUtils and avoid reinventing the wheel? For example, we can probably make use of BeanUtils API to expose objects to scripts and requires jsr-223 script engine implementers to treat DynaBeans specially to provide easier syntax. And optionally expose (some or all of) their own objects with DynaBean interface.

The ScriptObject and Callable interfaces could help in inter scripting language communication as well -- there is no need to specify a strongly typed Java interface to communicate b/w two dynamically typed languages (using say, Invocable.getInterface() ). For example, you can access Groovy object from a JRuby script and vice versa and both sides could use natural syntax to access ScriptObjects.Please let me know your comments. We can probably try this out with script engines @ scripting.dev.java.net



( Mar 21 2007, 02:28:41 PM IST ) Permalink del.icio.us | furl | simpy | slashdot | technorati | digg

Comments:

Post a Comment:

Comments are closed for this entry.
Copyright (C) 2005, A. Sundararajan's Weblog