Deploying Clojure websites

* This page is related to "Clojure and Compojure to the rescue, again".

On my server I'm running one Java process, which handles four of my websites on four different domains. These are all running on Clojure + Compojure. Some people asked for details of how to do this, so here's a rough outline. For the sake of brevity I'm only going to talk about two domains here, though it scales up to however many you want pretty easily.

This is surely not the only way to do this, and probably not the best way, but it's what I've arrived at after a year of goofing off.

Summary: Emacs + SLIME + Clojure running in GNU Screen; all requests are handled by Apache and mod_proxy sends them to the appropriate Jetty instance / servlet.

Clojure, SLIME, ODBC, SQL Server

I had a lot of trouble connecting to an MS SQL Server at work via Clojure. Java 6 comes with a JDBC-ODBC bridge which worked fine from a Clojure REPL at a command prompt, or from inferior-lisp in Emacs, but in SLIME it would hang every time I tried to connect and I'd have to kill Java. Couldn't for the life of me figure out why.

I got it to work eventually by using Microsoft's own JDBC driver, which you can download here.

Once you put the downloaded .jar file on your CLASSPATH (in my case, sqljdbc4.jar) you can connect like this:

user> (def db {:classname "com.microsoft.sqlserver.jdbc.SQLServerDriver"
               :subprotocol "sqlserver"
               :subname "//server_hostname;database=SomeDatabase;user=SomeUser;password=SomePassword"})
#'user/db
user> (use 'clojure.contrib.sql)
nil
user> (with-connection db 
        (with-query-results rs ["SELECT * FROM whatever"] (prn rs)))
... results ...

Posted for the sake of Googlebot and for my own future sanity.

Practical Common Lisp (review)

My current "programming language of the week" is Common Lisp. I got a dead-tree hard copy of Practical Common Lisp as a going-away present from my last job. This week on a trip to Eugene, Oregon (as part of the process of getting my NEXT job, hopefully) I had lots of time to read through it. I "finished" it today, for some definition of "finish" which includes a "skipped over large chunks of chapters that were way over my head" clause.

I was amazed to learn from Peter Seibel's blog that as of May 2007, there were less than 10,000 copies sold. I think I am really clouded in my view of what kinds of things people know in the world at large. I know there must be some overwhelmingly large group of Windows-only programmers who only know C# and/or Java and nothing else, but perhaps because I live in the world of Linux and open source, I never come in contact with them. When I look around me (figuratively, online) I see Linux guys who know Linux and Perl and Ruby and *nix-style C++ and whatnot. So I often find it very difficult to extrapolate anything about the world at large based on what I see around me.

Either way, PCL is a good book. It has an immense amount of information in it. Almost overwhelmingly large amounts of information, somehow. It may be overwhelming simply because of how unfamiliar many of the concepts and terminologies are to one such as myself who doesn't come from a Lisp background. But there are also many things that I'm 100% sure I wouldn't understand at all if I didn't already know Ruby pretty well (largely because Ruby ganked so much stuff from Lisp). If I didn't have a Ruby background, I'd be even more lost than I was.

Whether Lisp is really practical or not, I'm not sure. For example, it takes a lot of housekeeping even to get a Lisp environment set up. Thankfully available on Peter's website is a pre-packaged "Lisp in a Box" that can at least get you to a REPL prompt with no effort. But then you have to start writing code. Lisp code can be compiled, or interpreted, or a combination of both(?), or both simultaneously(?). Or it can be typed manually into the REPL, and then run, or compiled, or dumped to a file. Or you can dump an image of the Lisp instance (image?) to file entirely. Often there's a mess of manual dependency-managing any time you use packages. And then there are special things you need to do to make sure certain kinds of macros and things load correctly when compiled and run from compiled form, or when saved to file in "readable" form and then re-read as lisp code at a later time. And there are certain things in Lisp that can't be output in "readable" format at all. Do I sound confused? I surely am. I found this writeup showing how one person gets started on a Lisp project, which is somewhat helpful.

Yeah, you can get SLIME for Emacs and then start banging away in the REPL, but losing everything when you close it isn't a lot of fun. So I'm getting by with typing stuff into an Emacs buffer and manually running top-level forms one at a time via a bunch of Emacs shortcuts. It still seems like I'm doing a lot of the work that my environment should be doing for me. But I suppose it's no worse than trying to set up a bunch of Makefiles to manage C++ code. And much of my trouble seems to be a product of my inexperience (but that can probably be said of anything).

Lisp does have a lot of things that are really interesting, like multi-methods and of course macros, which the book covers in a wonderful amount of detail. Even the exception/condition system is different (and arguably much more powerful) than other languages'. The Lisp language itself is simply more powerful than most other languages in many ways, is the only conclusion I can come to. It's more extensible and it gives you more options for abstracting things in ways that are impossible to do (easily) in other languages due to the syntax and available constructs the languages provide. At the same time, all this power comes at the expense of code that's nearly unreadable by my somewhat biased standards; nasty Perl-esque punctuation abounds, there are many inconsistencies in how things are called or passed parameters (often for "historical reasons", the bane of my existence), and given the ability of macros to drastically alter the way code looks and works and to define mini-languages inside Lisp itself, you're very often not quite sure what exactly you're looking at at any given moment.

But I highly recommend the book. For non-Lispers like myself, if nothing else it gives you a taste of language that's very different from probably anything you've seen before, and it can point you in many interesting directions you may never have thought possible. On the other hand, is Lisp a revolutionary Zen-like enlightenment-producing revelation of a language which will expand your programmer mind into vast new dimensions of coding efficiency and bliss? I have yet to take sip of the Kool-Aid required to answer that question, but who knows.