<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>robert zubek / blog &#187; lisp</title>
	<atom:link href="http://robert.zubek.net/blog/tag/lisp/feed/" rel="self" type="application/rss+xml" />
	<link>http://robert.zubek.net/blog</link>
	<description></description>
	<lastBuildDate>Thu, 01 Apr 2010 05:40:27 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Clojure Web Server (in less than 100 lines)</title>
		<link>http://robert.zubek.net/blog/2008/04/26/clojure-web-server/</link>
		<comments>http://robert.zubek.net/blog/2008/04/26/clojure-web-server/#comments</comments>
		<pubDate>Sun, 27 Apr 2008 07:06:09 +0000</pubDate>
		<dc:creator>robert</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[clojure]]></category>
		<category><![CDATA[lisp]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://robert.zubek.net/blog/?p=23</guid>
		<description><![CDATA[(Edit: Welcome reddit readers. The following is a howto on setting up an embedded Jetty server in Clojure, and writing a minimal servlet that serves up dynamic content.) Last week I discovered a very nice language named Clojure. It&#8217;s based on Lisp, but hosted on the Java platform, and running inside the JVM. It has [...]]]></description>
			<content:encoded><![CDATA[<p>(Edit: Welcome reddit readers. The following is a howto on setting up an embedded Jetty server in Clojure, and writing a minimal servlet that serves up dynamic content.)</p>
<p>Last week I discovered a very nice language named <a title="Clojure" href="http://clojure.sourceforge.net/" target="_blank">Clojure</a>. It&#8217;s based on Lisp, but hosted on the Java platform, and running inside the JVM. It has some lovely features, like native support for Java collections, and a clean API that ditches a lot of the old ANSI CL library cruft.</p>
<p>But the best part for me was language interop: Clojure can effortlessly load and use any external Java library. And there is a ton of good ones out there, including a rich set that comes with the Java platform. (This may seem like a minor point, but most free Lisps lack good libraries; only the non-free Allegro CL has really extensive, cross-platform ones.)</p>
<p>So I decided to take the language for a spin, especially exercising the language interop bit. For example, by building a little web server to serve up some dynamic content. You know, web development 101 kind of stuff. This turns out to be really easy to do. <img src='http://robert.zubek.net/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Since Clojure is backed by Java, we can use an existing server library to do the heavy lifting for us. Several high-quality ones are available - I went with Jetty, a servlet-based engine that&#8217;s really easy to embed in custom applications. Using a servlet container will take care of all the mundane bookkeeping for us.</p>
<p>In the following posting, I&#8217;m reproducing the steps required to get a Clojure-based web server up and running, in much less than 100 lines of code. Hope you find it interesting!</p>
<p><span id="more-23"></span></p>
<p>I&#8217;ll split this into three parts:</p>
<ol>
<li>Getting Jetty and setting up your Clojure environment</li>
<li>Creating a server that only serves up static pages</li>
<li>Modifying the server to provide dynamic content</li>
</ol>
<p>Let&#8217;s go through them.</p>
<p> </p>
<h4>1. Getting Jetty and environment setup.</h4>
<p>(The following requires Clojure release 2008/03/29 or later.)</p>
<p>Jetty is a huge library, but we&#8217;ll only need three jars from it. So let&#8217;s do the following:</p>
<ul>
<li>Download <a title="Downloading Jetty" href="http://docs.codehaus.org/display/JETTY/Downloading+Jetty" target="_blank">Jetty 6.1.9</a>, or whichever is latest, from the official site</li>
<li>Get the following jar files from the archive, and place them in some preferred directory (I put them under clojure/lib):
<ul>
<li>jetty-6.1.9.jar</li>
<li>jetty-util-6.1.9.jar</li>
<li>servlet-api-2.5-6.1.9.jar</li>
</ul>
</li>
<li>In whatever script / batch file / elisp command you use to start up your Clojure instance, modify your classpath to include them. In my case, I end up with the enormous:</li>
</ul>
<blockquote>
<li>&#8220;java -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=4096 -cp c:/users/rob/documents/clojure/clojure.jar;c:/users/rob/documents/clojure/lib/<strong>jetty-6.1.9.jar</strong>;c:/users/rob/documents/clojure/lib/<strong>jetty-util-6.1.9.jar</strong>;c:/users/rob/documents/clojure/lib/<strong>servlet-api-2.5-6.1.9.jar</strong> clojure.lang.Repl c:/users/rob/documents/clojure/src/boot.clj&#8221;</li>
</blockquote>
<p>To verify, start up your Clojure instance, and try creating a new Jetty Server instance &#8211; it should look something like the following:</p>
<pre style="padding-left: 30px;">Clojure
user=&gt; (import '(org.mortbay.jetty Server))
nil
user=&gt; (new Server)
Server@1f0f8ff
user=&gt;</pre>
<p>All right, now we&#8217;re ready to have some fun.</p>
<p> </p>
<h4>2. Writing a server for static pages</h4>
<p>Jetty comes with a default servlet for static html pages. We just need to configure it.</p>
<p>We could do this from an xml file, as recommended for Jetty deployment in production environments. But that&#8217;s more work than is needed for this experiment.  <img src='http://robert.zubek.net/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />   Instead, we&#8217;ll configure a small and minimal server instance from Clojure code itself.</p>
<p>First, a big bunch of imports:</p>
<pre style="padding-left: 30px;">(import
 '(java.io File)
 '(javax.servlet.http HttpServlet HttpServletRequest HttpServletResponse)
 '(org.mortbay.jetty Server Handler Connector NCSARequestLog)
 '(org.mortbay.jetty.handler HandlerCollection ContextHandlerCollection RequestLogHandler)
 '(org.mortbay.jetty.nio BlockingChannelConnector)
 '(org.mortbay.jetty.servlet Context DefaultServlet ServletHolder SessionHandler))</pre>
<p>Now let&#8217;s add a few constants that we&#8217;ll need later on (customize as needed, of course):</p>
<pre style="padding-left: 30px;">;; server port
(def *port* 8080)</pre>
<pre style="padding-left: 30px;">;; static pages will be served from this directory
(def *wwwdir* "C:/Users/Rob/Documents/Projects/Clojure Http Server/pages")</pre>
<pre style="padding-left: 30px;">;; log files go here
(def *logdir* "C:/Users/Rob/Documents/Projects/Clojure Http Server/log")</pre>
<pre style="padding-left: 30px;">;; specifies naming pattern for log files
(def *logfiles* "log.yyyy_mm_dd.txt")</pre>
<p>The Jetty server itself contains some connectors, which read data from sockets and feed it to a bunch handlers. Let&#8217;s make one.</p>
<pre style="padding-left: 30px;">;; create connector on the specified port
(defn make-connectors [port]
  (let [conn (new BlockingChannelConnector)]
    (. conn (setPort port))
    (into-array [conn])))</pre>
<p>One of the built-in handlers is a logger, which just writes out an access log file. Another built-in one is a context handler, which contains a set of servlets. It preprocesses any received data, and then hands it over to one of its servlets, based on the path being requested in the URL.</p>
<p>Here&#8217;s how I configure both of them:</p>
<pre style="padding-left: 30px;">;; configures a default servlet to serve static pages from the "/" directory
(defn configure-context-handlers [contexts]
  (let [context (new Context contexts "/" (. Context NO_SESSIONS))]
    (. context (setWelcomeFiles (into-array ["index.html"])))
    (. context (setResourceBase (. (new File *wwwdir*) (getPath))))
    (. context (setSessionHandler (new SessionHandler)))
    (. context (addServlet (new ServletHolder (new DefaultServlet)) "/*"))
    context))</pre>
<pre style="padding-left: 30px;">;; set up handlers: the context ones, and a logger to track all http requests
(defn make-handlers [contexts]
  (let [handlers (new HandlerCollection)
        logger (new RequestLogHandler)
        logfile (new File *logdir* *logfiles*)]</pre>
<pre style="padding-left: 30px;">    (. logger (setRequestLog (new NCSARequestLog (. logfile (getPath)))))
    (. handlers (addHandler logger))
    (. handlers (addHandler contexts))
    handlers))</pre>
<p>All that&#8217;s left is standing up the actual server. That&#8217;s frighteningly easy:</p>
<pre style="padding-left: 30px;">;; make an empty collection of context handlers - we'll configure it later
(defn make-contexts []
  (new ContextHandlerCollection))

;; make an instance of the http server
(defn make-server
  ([] (make-server *port*))
  ([port]
     (let [contexts (make-contexts)
           connectors (make-connectors port)
           handlers (make-handlers contexts)
           server (new Server)]
       (. server (setConnectors connectors))
       (. server (setHandler handlers))
       (configure-context-handlers contexts)
       server)))</pre>
<p>And that&#8217;s it! Go ahead, try it!</p>
<p>First, place an &#8220;index.html&#8221; page in the directory you specified under <strong>*wwwdir*.</strong> Then run the server:</p>
<pre style="PADDING-LEFT: 30px">user=&gt; (def server (make-server))
2008-04-26 23:32:02.752::INFO:  Logging to STDERR via org.mortbay.log.StdErrLog
#&lt;Var: user/server&gt;
user=&gt; (. server (start))
2008-04-26 23:32:10.863::INFO:  jetty-6.1.9
2008-04-26 23:32:10.898::INFO:  Opened C:\Users\Rob\Documents\Projects\Clojure Http Server\log\log.2008_04_27.txt
2008-04-26 23:32:10.962::INFO:  Started BlockingChannelConnector@0.0.0.0:8080
nil</pre>
<p>&#8230; and then navigate over to the right page:</p>
<p><a href="http://robert.zubek.net/blog/wp-content/uploads/2008/04/clojure-server-1.jpg"><img class="aligncenter size-full wp-image-24" title="clojure-server-1" src="http://robert.zubek.net/blog/wp-content/uploads/2008/04/clojure-server-1.jpg" alt="" /></a></p>
<p>To stop the server, just call the method with the same name:</p>
<pre style="padding-left: 30px;">user=&gt; (. server (stop))
nil
 </pre>
<h4>3. Servlet that produces dynamic content</h4>
<p>The next step is writing our own servlet, which will serve arbitrary, dynamic content. The Java Servlet API is quite powerful, and makes it easy to build all sorts of wacky web wonders.</p>
<p>Let&#8217;s start by writing our own request processing function: it will take an HTTP request and response objects, and just write out current time as the response:</p>
<pre style="PADDING-LEFT: 30px">(defn process [#^HttpServletRequest req #^HttpServletResponse resp]
  (let [out (. resp (getOutputStream))]
    (. out (println (str "Test Successful at " (new java.util.Date)))))) </pre>
<p>(The type hints aren&#8217;t strictly necessary, but they&#8217;re there for my sanity, to remind me what Java classes are hiding behind the various variables.)</p>
<p>Also, make a new servlet that will use this function to process each request:</p>
<pre style="padding-left: 30px;">;; implementation of an HttpServlet, overriding just one function:
;;   protected void doGet(HttpServletRequest req, HttpServletResponse resp)
(defn make-test-servlet []
     (proxy [HttpServlet] []
       (doGet [#^HttpServletRequest req #^HttpServletResponse resp]
          (process req resp))))</pre>
<p>Finally, hook it up to the context handler, so that it will serve all requests for the &#8220;/test&#8221; URL. We just modify the function mentioned above, by adding a single line highlighted below:</p>
<pre style="padding-left: 30px;">(defn configure-context-handlers [contexts]
  (let [context (new Context contexts "/" (. Context NO_SESSIONS))]
    (. context (setWelcomeFiles (into-array ["index.html"])))
    (. context (setResourceBase (. (new File *wwwdir*) (getPath))))
    (. context (setSessionHandler (new SessionHandler)))
    (. context (addServlet (new ServletHolder (new DefaultServlet)) "/*"))
    <span style="text-decoration: underline;"><strong>(. context (addServlet (new ServletHolder (make-test-servlet)) "/test"))</strong></span>
    context))</pre>
<p>That&#8217;s that! Now run the server again, and check out the results:</p>
<p><a href="http://robert.zubek.net/blog/wp-content/uploads/2008/04/clojure-server-2.jpg"><img class="aligncenter size-full wp-image-25" title="clojure-server-2" src="http://robert.zubek.net/blog/wp-content/uploads/2008/04/clojure-server-2.jpg" alt="" /></a></p>
<p> </p>
<h4>Final Words</h4>
<p>This is clearly just an experiment, and not a production-ready system. But using Jetty as the server engine makes the system easy to build and very robust - it&#8217;s easy to imagine how one could go about building an actual, fully-featured web service around this technology.</p>
<p>Hope this was amusing!</p>
<p> </p>
]]></content:encoded>
			<wfw:commentRss>http://robert.zubek.net/blog/2008/04/26/clojure-web-server/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>SBCL + Emacs + Windows Vista</title>
		<link>http://robert.zubek.net/blog/2008/04/09/sbcl-emacs-windows-vista/</link>
		<comments>http://robert.zubek.net/blog/2008/04/09/sbcl-emacs-windows-vista/#comments</comments>
		<pubDate>Thu, 10 Apr 2008 04:49:05 +0000</pubDate>
		<dc:creator>robert</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[emacs]]></category>
		<category><![CDATA[lisp]]></category>
		<category><![CDATA[vista]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://robert.zubek.net/blog/?p=21</guid>
		<description><![CDATA[Here are my steps for setting up SBCL (Steel Bank Common Lisp) and Slime (Emacs Lisp mode) to work under Windows Vista. It&#8217;s mostly straightforward, except for dealing with spaces in path names. It turns out that slime.el uses the (split-string) function to pull apart the Lisp command line, which won&#8217;t work with the default &#8220;c:\program [...]]]></description>
			<content:encoded><![CDATA[<p>Here are my steps for setting up SBCL (Steel Bank Common Lisp) and Slime (Emacs Lisp mode) to work under Windows Vista.</p>
<p>It&#8217;s mostly straightforward, except for dealing with spaces in path names. It turns out that <em>slime.el</em> uses the (split-string) function to pull apart the Lisp command line, which won&#8217;t work with the default &#8220;c:\program files\&#8230;&#8221; location. Here&#8217;s how to fix that, using symbolic links (yes, Windows supports them too!).</p>
<p>The following was tested on a Vista box, SBCL 1.0.13, and Slime 2.0 on Emacs 22.2.1.</p>
<p>Installing SBCL:</p>
<ol>
<li>Download and install SBCL. By default, it will install to <em>c:\Program Files\Steel Bank Common Lisp\1.0.13</em></li>
<li>Run <em>cmd.exe as Administrator</em> (required for symbolic links)</li>
<li>Set up a link from SBCL install directory, to some location without spaces. Note that the syntax is an inverse of the Unix &#8216;ln&#8217; command.<br />
<blockquote><p>C:\Users\Rob\Documents&gt;ver<br />
Microsoft Windows [Version 6.0.6000]</p>
<p>C:\Users\Rob\Documents&gt;mklink /d SBCL &#8220;c:\Program Files\Steel Bank Common Lisp\1.0.13&#8243;<br />
symbolic link created for SBCL &lt;&lt;===&gt;&gt; c:\Program Files\Steel Bank Common Lisp\1.0.13</p>
<p>C:\Users\Rob\Documents&gt;dir sbcl*<br />
&#8230;<br />
04/09/2008 09:07 PM &lt;SYMLINKD&gt; SBCL [c:\Program Files\Steel Bank Common Lisp\1.0.13]</p></blockquote>
</li>
</ol>
<p>Installing Emacs and Slime:</p>
<ol>
<li>Download Emacs, unzip it to any location (eg. <em>c:\Program Files\emacs</em>). If desired, run the <em>emacs\bin\addpm.exe</em> program to add a link to the start menu.</li>
<li>Download Slime, and unzip it under your <em>emacs/site-lisp</em> directory.</li>
<li>Add the following to your <em>~/.emacs</em> file:<br />
<blockquote>
<div>(setq inferior-lisp-program &#8220;c:/users/rob/documents/sbcl/sbcl.exe &#8211;core c:/users/rob/documents/sbcl/sbcl.core&#8221;)<br />
(require &#8216;slime)<br />
(slime-setup) </div>
</blockquote>
</li>
<li>Restart Emacs, and then run <em>M-x run-lisp</em> to test whether Lisp starts up.</li>
<li>Start slime with<em> M-x slime</em>. Happy hacking!</li>
</ol>
<p> </p>
]]></content:encoded>
			<wfw:commentRss>http://robert.zubek.net/blog/2008/04/09/sbcl-emacs-windows-vista/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
	</channel>
</rss>
