Foognostic blogs Seeking knowledge of foo

3Jan/10Off

Juggling versions of Clojure?

(Standard disclaimer: Clojure is a new hobby.)

EDIT: also try rake clojure:new:repl

I am looking forward to trying datatypes on Pokerepl. However, that means using the new branch of Clojure, and indirectly, more work on my part to clone/track/build/deploy the new branch.

Almost everyone would and should use Leiningen to experiment with the new branch. Simply update your project.clj something like this:

   :dependencies [[org.clojure/clojure "1.1.0-new-SNAPSHOT"]
                  [org.clojure/clojure-contrib "1.1.0-new-SNAPSHOT"]]

At the moment though, updating ~/.clojure was beyond the ken of any automated tool I knew of. So I wrote a Rakefile and gave it a cheesy name... juggling Clojure... hmm... howzabout Clojuggle? Well... yeah... sorry for that.

Back to the point: automating thorough (~/.m2 and ~/.clojure) updates and deployments of various versions of Clojure. Supporting common tasks (wipe, clone, build, &c.) for several branches of several repositories means a thousand tasks will bloom and make the tool hard to use.

Ruby and the Rake API make it easy to define or show tasks only when relevant. I really enjoyed writing this code. Anyways, typing rake brings you to this:

$ rake
Welcome! Try 'rake -T' for a list of useful tasks, or try
    rake clojure:master:all clojure-contrib:master:all

The default task provides some basic usage. Let's take a look at the initial set of tasks:

$ rake -T
rake clojure-contrib:master:all  # Do everything for master branch of clojure-contrib
rake clojure-contrib:new:all     # Do everything for new branch of clojure-contrib
rake clojure:master:all          # Do everything for master branch of clojure
rake clojure:new:all             # Do everything for new branch of clojure
rake default                     # HOWTO use this file

Fine, let's give it a whirl.

$ time rake clojure:new:all
# oodles of lines omitted
ci-build:

BUILD SUCCESSFUL
Total time: 25 seconds
rm -f /.../.clojure/clojure.jar
ln -s /.../clojuggle/src/clojure-new/clojure.jar /.../.clojure/clojure.jar

real    0m55.306s
user    1m10.544s
sys 0m6.873s

Three subtle points here. First, the "ci-build" line is the clue that the local Maven2 repository was updated:

$ ls -l ~/.m2/repository/org/clojure/clojure/
total 8
drwxr-xr-x  7 seths  staff  238 Jan  3 17:57 1.1.0-new-SNAPSHOT
-rw-r--r--  1 seths  staff  322 Jan  3 17:57 maven-metadata-local.xml

Point #2: the ~/.clojure directory has a symlink pointing into the clojuggle/src/clojure-new directory.

$ ls -l ~/.clojure/
total 8
lrwxr-xr-x  1 seths  staff  70 Jan  3 17:57 clojure.jar -> /.../clojuggle/src/clojure-new/clojure.jar

Point #3: a few more commands have surfaced from the Rakefile (e.g. clojure:new:update)

$ rake -T
# ... omitted
rake clojure:blast:it            # Removes files for clojure from $HOME/.clojure and .m2
rake clojure:new:publish         # Push build to local m2 repo and ~/.clojure
rake clojure:new:update          # Update the new branch of clojure

So that's all well and good, but what if you wanted to support Technomancy's fork of Clojure? You would do two things. First this:

$ cat > user.yml
technomancy-clojure:
  clone-from: git://github.com/technomancy/clojure.git
  branches: [master, new]
  use-jar: clojure.jar

And then something like this:

$ rake -T
 # ... omitted
rake technomancy-clojure:master:all  # Do everything for master branch of technomancy-clojure
rake technomancy-clojure:new:all     # Do everything for new branch of technomancy-clojure

DANGER!

Do NOT use this tool to develop on various versions of Clojure. The wipe task always deletes files, so eventually you will lose changes unintentionally. Eventually 'git status' will be used to prevent wiping changes but not yet.

Penultimately, despite all this I still don't have the new branch working with Slime/Swank. It doesn't help that the pom.xml of contrib on the new branch wants 1.1.0-alpha of Clojure. Minor nits though that can be worked out.

Finally, if anyone is still reading and cares about these sort of things, I picked Ruby, v3 of the GPL, and Mercurial/BitBucket because I have strong feelings about those things.

Please respond in some way if you have any questions!

tl;dr: Leiningen is great -- try using it with the new branch of Clojure!

Tagged as: No Comments
24Jan/09Off

introducing jawarepl

JAWAREPL is a JAva Web Application Read Eval Print Loop. It loads a Spring-based Java .war file into groovysh, and then makes its fully actived Spring beans easy to use.

Here's a quick example. It uses 'petclinic', one of the sample apps included with Spring:

$ groovysh
. /Users/moi/Documents/code/jawarepl/jawarepl.groovy
inst = new JAWAREPL();

Here's how you configure it:

inst.war_path = "/path/to/petclinic/dist/petclinic.war";
inst.context_paths = [ "WEB-INF/applicationContext-hibernate.xml" ];
ctx = inst.context;

After that, the sky's the limit! Start grabbing beans out and call all the methods you want. Put this into groovysh:

clinic = ctx.getBean("clinic");
clinic.vets.each {
   println "vet = ${it.lastName}, ${it.firstName}";
   it.specialties.each {
       println "    $it";
   }
}

And this should come out:

vet = Carter, James
vet = Douglas, Linda
    dentistry
    surgery
vet = Jenkins, Sharon
vet = Leary, Helen
    radiology
vet = Ortega, Rafael
    surgery
vet = Stevens, Henry
    radiology

Just to demonstrate that it's not only for reading data, here is another sample where it adds a visit to the petclinic.

owner = clinic.findOwners("Schroeder")[0];
owner.pets.visits.each { println "$it.date, $it.description" }
[2009-01-24, 2009-01-24], [JAWAREPL test, JAWAREPL test]
visit = new org.springframework.samples.petclinic.Visit();
visit.date = new Date();
visit.pet = pets[0];
visit.description = "JAWAREPL test2";
clinic.storeVisit(visit);
...
Hibernate: insert into visits (visit_date, description, pet_id) values (?, ?, ?)
owner = clinic.findOwners("Schroeder")[0];
owner.pets.visits.each { println "$it.date, $it.description" }
[2009-01-24, 2009-01-24, 2009-01-24], [JAWAREPL test,
JAWAREPL test2, JAWAREPL test]

More detailed instructions are available on bitbucket.

JAWAREPL has been tested on three of the sample Spring apps and a basic Grails app. Those are pretty trivial samples and even so, it was a minor task to make them all work; the Grails war had none of the GORM mojo stitched in so it was really not very useful (patches anyone?) That being said, I would not expect a complex war file to load smoothly. I seem to recall some sort of mock/mini JNDI provider in Spring if that what goes wrong. I will try to look at any bug reports, or much better yet patches.

   

Foognostic blogs is Digg proof thanks to caching by WP Super Cache