Webjure: simple web app programming for clojure

765 views
Skip to first unread message

Tatu Tarvainen

unread,
Jan 15, 2008, 12:21:47 PM1/15/08
to Clojure

I have been working on a simple web "framework" for programming web
apps using clojure.

I'm planning to put it to sourceforge under the CPL license very soon.

Features:

Basic dispatching to clojure functions:
Functions can be registered to the servlet's dispatch table with
(webjure/publish <fn> <url-pattern>)

Where <fn> is a 3 argument handler function (method, request and
response) and
<url-pattern> is an url pattern (like "/foo" or "/bar*"). The shortest
matching handler
will be called for a request.

HTML generation expressions:
HTML output can be generated from clojure forms with html-format.

(webjure/html-format
(webjure/response-writer resp)
`(:html
(:body
(:a {:href "http://clojure.sf.net" :style "font-weight: bold;"}
"Clojure site"))))

SQL queries:
Simple SQL query (with query parameters) support using JDBC.
(sql/query *db* "SELECT * FROM cities WHERE country_iso_code = ?"
"FI")
Returns a sequence of rows where each row is a sequence of values.
The returned result sequence has a meta attached to it that provides
information on the result set columns and size.

Trying it out:
You can try the current version by downloading
http://homepage.mac.com/tatu.tarvainen/webjure.war
into a servlet container's webapps directory (tested with Jetty 6.1.7
on Mac OS X and Linux).

When the servlet container is started, point your browser to
http://localhost:8080/webjure/index
Demos included:
- simple html generation (the index page)
- request header dump
- SQL listings as tables (requires the "toursdb" directory from derby)
- AJAX REPL (very buggy and basic functionality)

Extract the war to look at the source files.

Also: this is running with a slightly patched version of clojure
20080106, but the classloader
issues should be resolved in the SVN version, so I should be able to
get that working soon.



Stuart Sierra

unread,
Jan 15, 2008, 5:43:41 PM1/15/08
to clo...@googlegroups.com
On Jan 15, 2008 12:21 PM, Tatu Tarvainen <tatu.ta...@mac.com> wrote:
> I have been working on a simple web "framework" for programming web
> apps using clojure.

Very cool. I've been hoping for something like this.

It ran without a hitch on Jetty 6.1.6. The AJAX repl didn't print the
results of expressions in Firefox, and it wouldn't load at all in IE7,
but that's probably a JavaScript issue.

Thanks for putting this together!
-Stuart

Rich Hickey

unread,
Jan 15, 2008, 10:26:30 PM1/15/08
to Clojure


On Jan 15, 12:21 pm, Tatu Tarvainen <tatu.tarvai...@mac.com> wrote:
> I have been working on a simple web "framework" for programming web
> apps using clojure.
>

Very neat! Thanks. Same results for me Jetty 6.1.6 on OS X.

This will be a fun application of Clojure.

Rich

Tatu Tarvainen

unread,
Jan 23, 2008, 12:43:41 PM1/23/08
to Clojure


On 16 tammi, 05:26, Rich Hickey <richhic...@gmail.com> wrote:
>
> Very neat! Thanks. Same results for me Jetty 6.1.6 on OS X.

I've put the code up to google project hosting. I decided to go with
the new BSD license.
It's available at: http://code.google.com/p/webjure/

It runs against the latest SVN version of clojure. I'm using Maven2 so
I had to make
one minor tweak to clojure pom file (because maven has one artifact
per project, the boot.clj has to
be included in the created jar).

I added:
<resources>
<resource>
<directory>src/</directory>
</resource>
</resources>

to the <build> section.

>
> Rich

- Tatu

Robin

unread,
Jan 23, 2008, 4:59:56 PM1/23/08
to Clojure
Works on OSX 10.5, Jetty 6.1.7, and Clojure 20080106.

What is the best way to setup automatic reloading of modified .clj on
each request?

Thanks,

Robin

Robin

unread,
Jan 23, 2008, 5:26:51 PM1/23/08
to Clojure
I force reloading demos.clj before each dispatch WebjureServlet.java:
190:

loadFromResource("demos.clj");
dispatch.invoke(method, request, response);

The auto-reloading is nice for development and experimenting.

Robin

Tatu Tarvainen

unread,
Jan 24, 2008, 1:40:39 PM1/24/08
to Clojure


On 24 tammi, 00:26, Robin <robi...@gmail.com> wrote:
> I force reloading demos.clj before each dispatch WebjureServlet.java:
> 190:
>
>   loadFromResource("demos.clj");
>   dispatch.invoke(method, request, response);
>
> The auto-reloading is nice for development and experimenting.

Another way to experiment is to use the socket shell (which is
configured in the servlet).
The Shell opens up a socket listener which can be telnet'ed to and
behaves like the normal
Clojure REPL.

It can be used from emacs as an inferior lisp, by setting:
(setq inferior-lisp-program "telnet localhost 27272")

The functionality is working in the current SVN version.


>
> Robin

- Tatu

Robin

unread,
Jan 24, 2008, 2:00:32 PM1/24/08
to Clojure
Nice, the shell works for me.

rcb@rcb:~$ telnet localhost 27272
Trying ::1...
telnet: connect to address ::1: Connection refused
Trying ::1...
telnet: connect to address ::1: Connection refused
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Welcome to webjure shell. Happy hacking!
webjure=> (+ 1 1)
2webjure=> (rest [1 2 3 4 5])
clojure.lang.APersistentVector$Seq@e46688dewebjure=>

In order to print vectors that are returned I use this:

(import (quote (java.io BufferedWriter OutputStreamWriter
ByteArrayOutputStream)))
(defn pp [form]
(let [bytearray (new ByteArrayOutputStream )]
(with-open wtr (new BufferedWriter (new OutputStreamWriter
bytearray "US-ASCII"))
(. clojure.lang.RT (print form wtr)))
((memfn toString) bytearray)))

webjure=> (pp (rest [1 2 3 4 5]))
(2 3 4 5)

Robin

Tatu Tarvainen

unread,
Jan 24, 2008, 2:49:48 PM1/24/08
to Clojure

> webjure=> (+ 1 1)
> 2webjure=> (rest [1 2 3 4 5])
> clojure.lang.APersistentVector$Seq@e46688dewebjure=>
>

The printing stuff has been fixed in the SVN version along with other
improvements to the shell.

> Robin


- Tatu
Reply all
Reply to author
Forward
0 new messages