Saturday, 20 June 2009

A Minimal Java Applet in Clojure

Clojure's ahead-of-time compilation features allow it to operate seamlessly with Java classes, but one quirk that I noticed when writing a Java applet was that the security environment in applets tends not to be too happy with reflective method calls. Overriding an applet's paint method like this is therefore a no-go:

(defn -paint [instance g]
(.drawString g "Hello from Clojure!" 50 50))

The problem here is that the .drawString method is reflectively invoked against the given Graphics object.

This can be overcome with type-hints, letting the compiler know what the given 'g' is so that it can generate the code for a direct call, keeping the applet security manager happy.

A minimal applet might therefore look something like this:

(ns djw
(:import (java.awt Graphics2D))
:name DJW
:extends java.applet.Applet))
(defn -paint [instance #^Graphics2D g]
(.drawString g "Hello from Clojure!" 50 50))

Note the type-hint, #^Graphics2D in the signature of the paint function.

If you're interested, the associated HTML file to run this in appletviewer or in a browser looks like this:

<object classid="java:DJW.class" type="application/x-java-applet" archive="applet.jar,clojure.jar" width="200" height="100" codebase=".">

Notice that clojure.jar is in the archive field of the object tag, along with applet.jar (containing the precompiled class files for the Clojure applet).

No comments:

Post a Comment