How to load program resources in Clojure

clartaq picture clartaq · Jan 11, 2010 · Viewed 10.5k times · Source

How do you load program resources such as icons, strings, graphical elements, scripts, and so on in a Clojure program? I am using a project layout similar to that in many Java projects where there is a "resources" directory hanging off of a "source" directory. A jar file is created from the source and includes the resources, but I can't seem to get the resources loaded as I would in Java.

The first thing I tried was something like

(ClassLoader/getSystemResource "resources/myscript.js")

But could never find the resource.

You can do something similar with

...
  (let [cls (.getClass net.mydomain.somenamespace)
        strm (.getResourceAsStream cls name)        ]
...

where name is the name of the resource to load, but the stream is nil.

You can try using the context class loader with something like

...

(let [thr (Thread/currentThread)
      ldr (.getContextClassLoader thr)
      strem (.getResourceAsStream ldr name)]
...

But strem is always nil.

In frustration, I've tried placing the resource files in just about every directory in the program. They get copied into the jar correctly, but I still can't seem to load them.

I've looked at the language sources for the load function and the run-time library, but am not "getting" it.

Any help would be appreciated.

EDIT: Here's a more concrete example. In Java, if you wanted to convert MarkDown to HTML, you might use the showdown.js script and write something like:

package scriptingtest;

import java.io.InputStreamReader;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;

public class Example {

    private Object converter;

    public String transformMarkDown(String markdownString) {
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("js");
        try {
            engine.eval(new InputStreamReader(getClass().getResourceAsStream(
                    "resources/showdown.js")));
            converter = engine.eval("new Showdown.converter()");
        } catch (Exception e) {
            return "Failed to create converter";
        }
        try {
            return ((Invocable) engine).invokeMethod(converter, "makeHtml",
                    markdownString).toString();
        } catch (Exception e) {
            return "Conversion failed";
        }
    }

    public static void main(String[] args) {
        System.out.println(new Example().transformMarkDown("plain, *emphasis*, **strong**"));
    }
}

when I create the project, it all gets compiled and packed into a jar. When run, the program outputs <p>plain, <em>emphasis</em>, <strong>strong</strong></p>

A literal translation to Clojure seems pretty straightforward, but I run into trouble trying to create the InputStreamReader -- I can't seem to write the code needed to find the script file in the jar.

Edit: Added "markdown" tag since the post gives two complete examples of approaches to processing markdown.

Answer

Joe Snikeris picture Joe Snikeris · Aug 4, 2011
(clojure.java.io/resource "myscript.js")