seancorfield
unread,Sep 26, 2010, 11:44:16 PM9/26/10Sign in to reply to author
Sign in to forward
You do not have permission to delete messages in this group
Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message
to cfmljure
Over the last few days I've been wrestling with meshing idiomatic
Clojure usage against cfmljure and Leiningen structured projects.
If you've looked at cfmljure, you'll have noticed the big admonition
that your Clojure source files must be on your classpath... sort of...
What I say in the documentation is that the clj/ folder needs to be on
your classpath and then cfmljure 'magics' the file paths so that they
are relative to your classpath:
Given a Leiningen project 'foo' you have a structure like this:
clj/
foo/
src/
foo/
core.clj
So when you tell cfmljure to use namespace 'foo.core' it knows to load
'foo/core.clj' and the classpath-relative file path is 'clj/foo/src/
foo/core.clj' and everything is fine and dandy... until you write
something more complicated.
Normally in a Clojure file, such as task/core.clj, you'd have
something like:
(ns task.core
(:use [clj-sql.core :as sql :exclude (do-insert insert-record)])
(:use [task.db])
(:use [clojure.string :as s :only (lower-case upper-case)]))
Everything you :use has to be on your classpath, either in a loaded
JAR or in source form.
When you're running Leiningen, it manipulates the classpath to have
{project}/lib, {project}/lib/*.jar and {project}/src on the classpath
(and {project}/test if you're testing things). That means that the
namespace declaration above finds clj-sql.core in lib/clj-
sql-0.0.3.jar, clojure.string in lib/clojure-1.3.0-master-SNAPSHOT.jar
(or clojure-1.2.0.jar depending on which version you're using) and
then it looks for task/db.clj on the classpath - underneath {project}/
src.
Because of the file path munging cfmljure does to work with clj/ being
on your classpath, the namespace declaration doesn't 'magically work'
in Clojure code loaded by cfmljure - unless you update the classpath
of your JEE/Servlet container to also point to the right place.
The bottom line is: simple stuff 'just works' (as long as you copy or
symlink clj/ to your classpath) but real projects are going to require
you to modify your classpath to suit Clojure's world view - unless I
can find a magical way around this! I've tried JavaLoader but it isn't
compatible with something that Clojure does so it doesn't work... you
can't even instantiate the Clojure RT (runtime).
This also means that the project argument is mostly useless as you
move to multi-file projects because {project}/src has to be on your
classpath and cfmljure might just as well load files without the clj/
{project}/src/ prefix anyway. Note that the clj/ prefix is also
unnecessary when your project really is on the classpath.
The current state of cfmljure is that the basic / advanced examples
work with just clj/ symlinked or copied onto your JEE/Servlet
container's classpath. The work-in-progress task example requires
classpath changes in order to work since it relies on external JARs
and it has multi-file code.
If anyone is an expert in manipulating classpaths 'on the fly', I'm
open to suggestions. Otherwise, I may leave the task example
unfinished in the context of cfmljure (i.e., undocumented and not
runnable without classpath changes) but continue to work on it as a
useful multi-file CRUD application and refactor things into a more
generic data access library with an example task manager client - as
part of some other work I'm doing to build a full, production-quality,
hybrid CFML / Clojure application.