I have now seen several projects ending at a point where the actual configuration depended on things only available at run-time.
The typical way to configure a Java program is to read one or more property files according to some application specific rules and then take action depending on their values. At one point or another this breaks down and you need actual program logic in your configuration which then can be indicated with a flag and adding code to your application which then handles the flag.
I was wondering if a tiny Lisp configuration reader module might be a better option, where the file to be read is not a property file but a Lisp program which is then eval'ed to create a final datastructure representing the configuration. A minimal set of functions in the runtime library would then allow string manipulation and perhaps even calling into the JVM. Just think of "construct an URL based on the current hostname".
I am not interested in a full Lisp engine with bells and whistles but just a small library for this purpose which can be enclosed in even small programs without a large jar containing the Lisp engine.
So does such a library exist?
- Small size
- Just need read file + eval and the ability to read the resulting data structure from the main Java program
- A small Lisp runtime library
- Speed is of lesser importance.
- Actively maintained.
Suggestions?
Edit 2012-01-20: I initially found all the candidates undesirable, but have decided to use this as a Maven exercise on the side with the 1998 jscheme 1.4 release. Project at https://github.com/ravn/jscheme-1998
Edit 2012-12-11: It turned out that the integration layer between the program being interpreted in Scheme and the host Java program was more important that I originally thought, and that I needed in a project to be able to provide classes with JAX-WS annotaions at runtime, which I could not do with JScheme but I could do with Groovy. The idea of a small configuration library which allows code snippets in the libraries is still valid, but I ended up needing more for it to be useful.
Good, much smaller solution is an embedded Scheme for Java. Out of many implementations, I found and tested JScheme. (API looks okay: http://jscheme.sourceforge.net/jscheme/doc/api/index.html)
A simple main program in Java:
And an example
config.scm
:The scheme is being interpreted at startup every time, so this is good choice for configurations. Advantages to JScheme include:
Benchmark update: this code runs in 0.13 seconds time. Compared to the Clojure version's time this is pretty fast.
I know you want a small size and runtime. Scheme is the usual choice for easy embedding, and would be my first choice. But I have no information on that field, though. My second choice is Clojure:
A respective code with using Clojure:
with
hello.clj
being:Running
time java ClojTest
for a while yields in an average of 0.75 seconds. Clojure compiling the script has quite a penalty!Clojure is excellent, it is embeddable and has very good interoperability for calling Java libraries. However it is not particularly small (you get a full compiler and quite a decent runtime library included). Still worth considering if you have a broader requirement for this kind of functionality - I've found Clojure to work as an excellent dynamic "glue" for Java code.
Otherwise, your best bet is probably a tiny embedded Scheme interpreter.
It may be possible to use the early (1998) version of JScheme at this link, which is only about a 30k jar file: http://norvig.com/jscheme.html
Otherwise, it's probably possible to write something even more minimal in a few hundred lines of Java.... it's probably only a weekend project considering how small the core of Scheme is. The following page is quite interesting if you want to write a mini-interpreter for Scheme: http://archives.evergreen.edu/webpages/curricular/2000-2001/fofc00/eval.html
Try SISC, it is a reasonably small (300kb jar) Scheme implementation with no bells and whistles. Glueing it with Java is trivial, and an execution speed is quite impressive for a pure interpreter.