Friday, January 23, 2009

calling java from arc

Rainbow adds six builtin functions for calling java code from arc. Theoretically this is all you need to interact with any java library from arc code.

java-new (classname . args)

Create and return a new instance of classname, passing args to the constructor

java-class (classname)

Return a java-object wrapping the class identified by classname

java-invoke (obj method . args)

Invoke method on obj with args. 'defcall binds this function to java-object so that you should only rarely need to call this explicitly. Return the value of the method if there
is any, wrapping into arc types where possible.

java-static-invoke (classname method . args)

Invoke static method on classname with args.

java-static-field (classname fieldname)

Return the value of the specified static field

java-implement (interfacename strictly methods)

Returns a java-object which implements the java interface identified by interfacename, the implementation being provided by the arc code given in methods, where methods is a hash mapping method-name to corresponding implementation. The strictly parameter determines whether an error should be raised if methods does not include all of the methods defined on the interface. java-implement is necessary for implementing, for example, mouse and keyboards handlers for a desktop application, or servlets and filters for a web application.

Following in the arc tradition of using arc-code wrappers for builtin functions (eg 'w/stdout for 'call-w/stdout, 'atomic for 'atomic-invoke, 'thread for 'new-thread), rainbow provides some wrappers to make java interaction a little less ugly and possibly a little more arcish. The 'implement macro removes some boilerplate around 'java-implement, so you can create an implementation of, for example, an iterator (where xs is a list) thus:

(def to-iterator (xs)
(implement "java.util.Iterator"
hasNext (fn () xs)
next (fn () (pop xs))))

The 'bean function instantiates and configures a java object via its setter methods. Here is an example of creating a JFrame object, specifying its bounds and title:

(def frame (left top width height title)
(bean "javax.swing.JFrame"
'bounds (list left top width height)
'title title
'contentPane (box 'vertical)))

Behind the scenes, bean is going to call setBounds, setTitle, and setContentPane on a newly-instantiated JFrame object, finally returning the JFrame.

There are lots more goodies defined in rainbow's swing.arc, but that's a topic for another day.