/site/ucw-boxset/ucw_dev/docs/ucw-intro/ucw-intro.html
HTML | 1448 lines | 1402 code | 19 blank | 27 comment | 0 complexity | bbd353aeba5610d7e4175fbb3d19ecb0 MD5 | raw file
Possible License(s): LGPL-2.0, LGPL-2.1, CC-BY-SA-3.0, LGPL-3.0, BSD-3-Clause, GPL-2.0
Large files files are truncated, but you can click here to view the full file
- <html>
- <head>
- <title>UCW intro</title>
- <link rel='stylesheet' type='text/css' href='style.css'>
- </head>
- <!--Creative Commons License-->
- <a rel="license"
- href="http://creativecommons.org/licenses/by-nc-sa/2.5/"><img
- alt="Creative Commons License"
- align='right'
- src="http://creativecommons.org/images/public/somerights20.png"
- border="0">
- </a>
- <!--/Creative Commons License--><!-- <rdf:RDF xmlns="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
- <Work rdf:about="">
- <license rdf:resource="http://creativecommons.org/licenses/by-nc-sa/2.5/" />
- <dc:title>UCW intro</dc:title>
- <dc:date>2006</dc:date>
- <dc:description>You don't have to mention
- my name or where you got the content from if you want to use this
- work for your own purposes, just keep by this license (why would of
- course be another question ;)). If you want
- to use any of this for commercial use or in another way that's not
- covered by the licence, just send me an email (see somewhere on the
- page if present) and we can probably work something out.</dc:description>
- <dc:creator><Agent><dc:title>Ties Stuij</dc:title></Agent></dc:creator>
- <dc:rights><Agent><dc:title>Ties Stuij</dc:title></Agent></dc:rights>
- <dc:source rdf:resource="www.fallenfrukt.com" />
- </Work>
- <License
- rdf:about="http://creativecommons.org/licenses/by-nc-sa/2.5/"><permits
- rdf:resource="http://web.resource.org/cc/Reproduction"/><permits
- rdf:resource="http://web.resource.org/cc/Distribution"/><requires
- rdf:resource="http://web.resource.org/cc/Notice"/><requires
- rdf:resource="http://web.resource.org/cc/Attribution"/><prohibits
- rdf:resource="http://web.resource.org/cc/CommercialUse"/><permits
- rdf:resource="http://web.resource.org/cc/DerivativeWorks"/><requires
- rdf:resource="http://web.resource.org/cc/ShareAlike"/></License></rdf:RDF> -->
- <body>
- <h1>UCW intro</h1>
- <p>advertisement: ucw is now easily installable!! (experimental)
- <br>
-
- Get <a href='http://common-lisp.net/project/ucw/ucw-boxset.tar.gz'>http://common-lisp.net/project/ucw/ucw-boxset.tar.gz</a>, untar it, cd into the dir and execute:</p>
- <pre>
- YOURLISPHERE (-)-load start.lisp
- </pre>
- <p>last modified 4th of may 2006</p>
- <p>- added ucw-boxset info
- <br>
-
- - added debugging tools chapter
- <br>
-
- - added tabbed pane info in the templating chapter
- <br>
-
- - added info on slightly changed startup procedure
- <br>
-
- - fixed bugs concerning variable passing between pages in basics.lisp
- <br>
-
- - fixed little bug in the spliced-href slot</p>
- <p>table of content:
-
- <ul>
- <li><a href='#intro'>Introduction</a></li>
- <li><a href='#install'>Installation</a></li>
- <li><a href='#extra'>Add-ons</a></li>
- <li><a href='#testing'>Testing/Quickstart</a></li>
- <li><a href='#configure'>Configuration</a></li>
- <li><a href='#environment'>Setting up the environment (and a hello world on the side)</a></li>
- <li><a href='#mechanics'>Basic ucw mechanics</a></li>
- <li><a href='#templating'>Templating: nested components, containers and TAL</a></li>
- <li>Login sessions</li>
- <li>Downloading files</li>
- <li>Advanced form handling</li>
- <li>To backtrack or not to backtrack</li>
- <li>Ajax</li>
- <li>Really, really, really cool example application</li>
- <li><a href='#debugging'>Debugging tools</a></li>
- <li><a href='#source'>Source</a></li>
- <li><a href='#miscellaneous'>Miscellaneous</a></li>
- </ul>
- </p>
- <p><span id='intro'></span></p>
- <h2>Introduction</h2>
- <p>This text will introduce you in a mild mannered pace to the ways of this as of yet UnCommon Web
- framework, which is a framework to write web applications as you would write normal applications; e.g. with state. Check ucw's
- <a href='http://common-lisp.net/project/ucw/features.html'>features page</a> to get an impression of its features. Ucw is an
- open source project. Various people donate code on a regular basis. Check the
- <a href='http://common-lisp.net/cgi-bin/mailman/listinfo/bese-devel'>mailing list</a> for a flavour of the current topics. If you're
- wondering about the merits and weaknesses of either state or stateless web development check
- <a href='http://common-lisp.net/project/ucw/docs/html/rest/rest.html'>this rather nice one-page email conversation</a>
- between the creator of ucw and a non-believer. If you want to use ucw on a windows machine, I have got no experience or information on
- workability, but i would very much like to hear about your experiences.</p>
- <p>This introduction wants to introduce UCW in a slow and concise manner. We will start with
- the installation and an initial setup. Then slowly, through simple examples, the reader will be introduced to the
- various components. We will delve from the outside in and will perhaps some day hit upon the burning hot core. For the
- brilliant and the impatient this pace will just be to damn slow. Them I advice to read and watch some
- other tutorials and documentation. They are:</p>
- <ul>
- <li><a href='http://www.cliki.net/ucw%20Tutorial'>UCW Tutorial</a> - a cliki tutorial in progress, not dissimilar to mine, which
- sets up a quick working environment and explains the different components with a lot of code.</li>
- <li><a href='http://common-lisp.net/project/ucw/documentation.html'>the ucw documentation page</a> - diverse documentation sources
- which are a bit out of date. The email conversations are very interesting to get a good grasp of the use and limitations of ucw, and the
- video, although out of date, is interesting because you get to see ucw in action. Be warned: the source-code and the wiki example are a bit
- out of date last time I checked. Better to just download the source code, in which you will also find the wiki example.</li>
- <li>the source code - the docs section of the source code unlocks apache setup code, two quickstarts which may be a bit out of date, and
- more. Also check the examples directory relative to the root. It gives you a good idea how to code up various aspects of ucw and it harbors
- the wiki-example. It might just be a bit obvious but in the source code you can also read the source code; it offers great insight in the way ucw is put together.</li>
- </ul>
- <p><span id='install'></span></p>
- <h2>Installation</h2>
- <p>First off UCW doesn't do version numbers. Some people may remember it did and it did, but it doesn't anymore. Still there are two versions
- of UCW to choose from: ucw_dev and ucw_public, both held in a Darcs repository. ucw_dev is controlled by Marco Baringer, creator of
- ucw. Ucw_public is world writable. At the moment I would advise to go with ucw_dev which is also the focus of this intro. _public is not always in sync with _dev, although lately it does a good job of keeping up.</p>
- <h3>The (experimental) easy way</h3>
- <p>There's a shortcut nowadays. Marco Baringer made a UCW candybox
- with all the dependencies boxed up and ready to fire. At the moment
- it's quite experimental, but if it doesn't work at least you've got all
- the dependencies in one go. Try:</p>
- <p>wget <a href='http://common-lisp.net/project/ucw/ucw-boxset.tar.gz'>http://common-lisp.net/project/ucw/ucw-boxset.tar.gz</a>
- tar -zxf ucw-boxset.tar.gz
- cd ucw-boxset
- YOURLISPHERE (-)-load start.lisp</p>
- <p>This will start UCW with the built in httpd server backend. But if you
- want to get the dependencies seperately or want a different initial setup,
- read and get some of the following:</p>
- <h3>The (old and boring) hard way</h3>
- <p>To get _dev or _public, install Darcs on your computer and execute:</p>
- <pre>
- darcs get http://common-lisp.net/project/ucw/repos/ucw_dev
- </pre>
- <p>or</p>
- <pre>
- darcs get http://common-lisp.net/project/ucw/repos/ucw_public
- </pre>
- <p>Daily snapshots for ucw_dev are available at
- <a href='http://common-lisp.net/project/ucw/tarballs/ucw_dev-latest.tar.gz'>http://common-lisp.net/project/ucw/tarballs/ucw_dev-latest.tar.gz</a></p>
- <p>Daily snapshots for ucw_public are available at
- <a href='http://common-lisp.net/project/ucw/tarballs/ucw_public-latest.tar.gz'>http://common-lisp.net/project/ucw/tarballs/ucw_public-latest.tar.gz</a></p>
- <p>Now it is time for the dependencies. A word of caution: ucw has it's own versions for a number of libraries so even if
- you already have the latest version of some package, check this documentation or the readme supplied with the
- sources. As a rule of thumb, get the latest of everything and the ucw version if supplied.</p>
- <p>At the moment UCW requires the following
- dependencies:</p>
- <ul>
- <li><a href='#implementation'>a lisp implementation - one of the following: sbcl, cmucl, allegro, lispworks, openmcl</a></li>
- <li><a href='#arnesi'>arnesi - an all purpose lisp toolkit</a></li>
- <li><a href='#yaclml'>yaclml - yet another common lisp markup language</a></li>
- <li><a href='#parenscript'>parenscript - javascript in common-lisp</a></li>
- <li><a href='#iterate'>iterate - a lispy loop</a></li>
- <li><a href='#rfc2388'>rfc2388 - implements multipart/form specification</a></li>
- <li><a href='#rfc2109'>rfc2109 - implements cookie specification</a></li>
- <li><a href='#split-sequence'>split-sequence - splits sequences</a></li>
- <li><a href='#slime'>slime - Superior Lisp Interaction Mode for Emacs</a></li>
- <li><a href='#cl-ppcre'>cl-ppcre - regular expressions lib</a></li>
- <li><a href='#trivial-sockets'>trivial-sockets - handles stream sockets for undemanding network applications</a></li>
- <li><a href='#puri'>net.uri or PURI - parses URI's according to the RFC 2396 specification</a></li>
- <li><a href='#cl-fad'>cl-fad - a portable pathname library based on code from PCL</a></li>
- <li><a href='#cl-launch'>cl-launch - invokes lisp code from the command line</a></li>
- <li><a href='#detachtty'>detachtty - a screen-like detachment tool to be able to detach and reattach the lisp server from and to a console</a></li>
- <li><a href='#backend'>a server backend - be it mod_lisp (apache 1 or 2), araneida, allegroserve, portable aserve or the built in httpd server</a></li>
- <li><a href='#asdf'>asdf - a package loader facility</a></li>
- </ul>
- <p>A note on compatibility: Some configurations of implementation and server work better than others. Just report your bugs in the
- <a href='http://common-lisp.net/cgi-bin/mailman/listinfo/bese-devel'>mailinglist</a>, the list is quite responsive. As a pointer, an
- implementation/server-pair of sbcl or openmcl and mod_lisp seem too see the heaviest testing. The built-in httpd server also works well but
- isn't fit for production use.</p>
- <p><span id='implementation'></span></p>
- <h4>Implementation.</h4>
- <p>Pick one in the list above.</p>
- <h4>Debian</h4>
- <p>Someone from Debian (Luca Capello) is working hard to to support ucw out of the box, but he is not quite there yet. Keep an eye on the
- cl-debian mailing list
- (<a href='http://common-lisp.net/pipermail/cl-debian/2006-March/001113.html'>UCW status, seeing the light at the end of the tunnel</a>) for the latest developments.</p>
- <p><span id='arnesi'></span></p>
- <h4>Dependencies</h4>
- <h5>arnesi</h5>
- <p>Arnesi is a Common Lisp utility suite. It contains various "bits 'n
- pieces" of code which were useful while developing other code. It can
- be found on <a href='http://common-lisp.net/project/bese/arnesi.html'>http://common-lisp.net/project/bese/arnesi.html</a>.</p>
- <p>You will need the latest version:</p>
- <pre>
- darcs get http://common-lisp.net/project/bese/repos/arnesi_dev/
- </pre>
- <p>Daily snapshots are available at
- <a href='http://common-lisp.net/project/bese/tarballs/arnesi_dev-latest.tar.gz'>http://common-lisp.net/project/bese/tarballs/arnesi_dev-latest.tar.gz</a></p>
- <p><span id='yaclml'></span></p>
- <h5>yaclml</h5>
- <p>yaclml is a collection of macros and utilities for generating XML/HTML
- like markup from lisp code. It can be found on
- <a href='http://common-lisp.net/project/bese/yaclml.html'>http://common-lisp.net/project/bese/yaclml.html</a>. </p>
- <p>You will need the latest version:</p>
- <pre>
- darcs get http://common-lisp.net/project/bese/repos/yaclml/
- </pre>
- <p>Daily snapshots are available at: <a href='http://common-lisp.net/project/bese/tarballs/yaclml-latest.tar.gz'>http://common-lisp.net/project/bese/tarballs/yaclml-latest.tar.gz</a></p>
- <p><span id='parenscript'></span></p>
- <h5>parenscript - ucw version</h5>
- <p>Parenscript is a javascript compiler. You will need to get the latest development version:</p>
- <pre>
- darcs get http://common-lisp.net/project/ucw/repos/parenscript/
- </pre>
- <p>Daily snapshots are available at: <a href='http://common-lisp.net/project/ucw/tarballs/parenscript-latest.tar.gz'>http://common-lisp.net/project/ucw/tarballs/parenscript-latest.tar.gz</a></p>
- <p><span id='iterate'></span></p>
- <h5>iterate</h5>
- <p>Iterate is an iteration construct for Common Lisp. It can be found on</p>
- <a href='http://common-lisp.net/project/iterate/'>http://common-lisp.net/project/iterate/</a>
- <p>Download link: <a href='http://common-lisp.net/project/iterate/releases/iterate-current.tar.gz'>http://common-lisp.net/project/iterate/releases/iterate-current.tar.gz</a></p>
- <p><span id='rfc2388'></span></p>
- <h5>rfc2388 - ucw version</h5>
- <p>Rfc2388 is a lisp implemantation of RFC 2388, which is used to process form
- data posted with HTTP POST method using enctype "multipart/form-data".</p>
- <p>UCW uses its own fork of rfc2388. You can get the latest code from the
- darcs repository located at
- <a href='http://common-lisp.net/project/ucw/repos/rfc2388'>http://common-lisp.net/project/ucw/repos/rfc2388</a>:</p>
- <pre>
- darcs get http://common-lisp.net/project/ucw/repos/rfc2388/
- </pre>
- <p>Daily snapshots are available at <a href='http://common-lisp.net/project/ucw/tarballs/rfc2388-latest.tar.gz'>http://common-lisp.net/project/ucw/tarballs/rfc2388-latest.tar.gz</a></p>
- <p><span id='rfc2109'></span></p>
- <h5>rfc2109 - ucw version</h5>
- <p>Rfc2109 is the lisp implementation of the cookie protocol. You can get
- it at:
- <a href='http://common-lisp.net/project/rfc2109'>http://common-lisp.net/project/rfc2109/</a>:</p>
- <pre>
- darcs get http://common-lisp.net/project/rfc2109/rfc2109
- </pre>
- <p>Daily snapshots are available at
- <a href='http://www.common-lisp.net/project/rfc2109/release/rfc2109-latest.tar.gz '>http://www.common-lisp.net/project/rfc2109/release/rfc2109-latest.tar.gz </a></p>
- <p><span id='split-sequence'></span></p>
- <h5>split-sequence</h5>
- <p>splits sequences</p>
- <p>info: <a href='http://www.cliki.net/SPLIT-SEQUENCE'>http://www.cliki.net/SPLIT-SEQUENCE</a></p>
- <p>download: <a href='http://ww.telent.net/cclan/split-sequence.tar.gz'>http://ww.telent.net/cclan/split-sequence.tar.gz</a>
- (you might have to select a mirror first)</p>
- <p>If said link is dead, go to <a href='http://ww.telent.net/cclan-choose-mirror'>http://ww.telent.net/cclan-choose-mirror</a>
- to delete your CCLAN-SITE cookie and choose another mirror. At least some of them are definitely working. </p>
- <p><span id='slime'></span></p>
- <h5>SLIME</h5>
- <p>The Superior Lisp Interaction Mode for Emacs.</p>
- <p>Download and install the latest CVS version of SLIME from
- <a href='http://common-lisp.net/project/slime'>http://common-lisp.net/project/slime</a>.</p>
- <p>To checkout from CVS you must first login to the repository:</p>
- <pre>
- export CVSROOT=:pserver:anonymous@common-lisp.net:/project/slime/cvsroot
- cvs login
- </pre>
- <p>Enter anonymous when prompted for the password. You can then check out the latest version with:</p>
- <pre>
- cvs checkout slime
- </pre>
- <p>It's swank you want to add to your asd systems dir. To solve a current problem
- with cl-launch you might want to overwrite your swank.asd file with this one:</p>
- <a href='http://cl-debian.alioth.debian.org/repository/pvaneynd/slime/debian/swank.asd'>http://cl-debian.alioth.debian.org/repository/pvaneynd/slime/debian/swank.asd</a>
- <p>Check the description on cl-launch to see why.</p>
- <p><span id='cl-ppcre'></span></p>
- <h5>cl-ppcre</h5>
- <p>Edi Weitz's regular expression library: <a href='http://www.weitz.de/cl-ppcre/'>http://www.weitz.de/cl-ppcre/</a>.</p>
- <p>Download the latest version: <a href='http://weitz.de/files/cl-ppcre.tar.gz'>http://weitz.de/files/cl-ppcre.tar.gz</a></p>
- <p><span id='trivial-sockets'></span></p>
- <h5>trivial-sockets</h5>
- <p>Networking library to create small server applications. Download the latest version from:
- <a href='http://ww.telent.net/cclan/trivial-sockets.tar.gz'>http://ww.telent.net/cclan/trivial-sockets.tar.gz</a>
- (you might have to select a mirror first.</p>
- <p>If said link is dead, go to <a href='http://ww.telent.net/cclan-choose-mirror'>http://ww.telent.net/cclan-choose-mirror</a>
- to delete your CCLAN-SITE cookie and choose another mirror. At least some of them are definitely working. </p>
- <p>Or use asdf install.</p>
- <p><span id='puri'></span></p>
- <h5>net.uri/PURI</h5>
- <p>All of the backends (except araneida) depend on Franz's open-source
- net.uri library. It only works on Allegro but Kevin Rosenberg has made a portable version called PURI.</p>
- <p>For allegro users, NET.URI can be downloaded from here (it may be included in your
- version of acl):
- <a href='http://opensource.franz.com/uri/index.html'>http://opensource.franz.com/uri/index.html</a> </p>
- <p>If you're not using allegro you'll need puri which can be
- downloaded from <a href='http://puri.b9.com/download.html'>http://puri.b9.com/download.html</a></p>
- <p><span id='cl-fad'></span></p>
- <h5>cl-fad</h5>
- <p>A portable pathname library based on code from Peter Seibels book Practical Common Lisp. </p>
- <p>info: <a href='http://www.cliki.net/CL-FAD'>http://www.cliki.net/CL-FAD</a></p>
- <p>download: <a href='http://weitz.de/files/cl-fad.tar.gz'>http://weitz.de/files/cl-fad.tar.gz</a></p>
- <p><span id='cl-launch'></span></p>
- <h5>cl-launch</h5>
- <p>A bash script to make your Lisp software easily invokable from the shell command-line.</p>
- <p>info: <a href='http://www.cliki.net/cl-launch'>http://www.cliki.net/cl-launch</a></p>
- <p>download page: <a href='http://fare.tunes.org/files/cl-launch/'>http://fare.tunes.org/files/cl-launch/</a></p>
- <p>Download and add to your shell executable search path so ucw can find it while loading. Cl-launch can either be called cl-launch or
- cl-launch.sh, ucw will check for both. Also cl-launch depends on swank behavior other than that of the current cvs code, at least under sbcl, eg via swank-loader it looks for files under the load path, which is not what you want if you made a symbolic link to another dir. The easiest way to get around this problem is to overwrite your swank.asd file (in the slime directory root), with this one:</p>
- <a href='http://cl-debian.alioth.debian.org/repository/pvaneynd/slime/debian/swank.asd'>http://cl-debian.alioth.debian.org/repository/pvaneynd/slime/debian/swank.asd</a>
- <p>The downside might be that swank won't work anymore as it should, although i haven't heard anyone about this yet. Another approach is to copy your swank*.fasls from the slime directory to the relevant shadow directory under ~/.cache/...</p>
- <p>Check this thread for more info:</p>
- <a href='http://common-lisp.net/pipermail/slime-devel/2006-March/004664.html'>http://common-lisp.net/pipermail/slime-devel/2006-March/004664.html</a>
- <p>Yes, ucw is bleeding edge ;)</p>
- <p><span id='detachtty'></span></p>
- <h5>detachtty - ucw version</h5>
- <p>A screen-like detachment tool to be able to detach and re-attach the lisp server from and to a console.
- Ucw uses a custom detachtty version, e.g. detachtty-9 plus a patch by Kevin Rosenberg. It accepts an eval argument when
- invoking a lisp, with obvious benefits. Get it through Darcs:</p>
- <pre>
- darcs get http://common-lisp.net/project/bese/repos/detachtty/
- </pre>
- <p>Go to the directory root and compile and install:</p>
- <pre>
- make
- make install
- </pre>
- <p><span id='backend'></span></p>
- <h4>the backend</h4>
- <p>Ucw supports all the popular lisp backends. Whichever floats your boat. If you've got no clue which to choose I'd advice
- to go for mod_lisp. It works well with other languages, you get the benefit of apaches options and extras and all it does
- is pump the code straight to ucw so there's no trouble with quirks in the intermediate layer. Apache requires some work
- to function correctly, read the text below. The other backends should work out of the box, as long as they're recognized by
- asdf. aserve as well as portable aserve are in the package systems of gentoo and debian. Gentoo also supports mod_lisp
- and mod_lisp2 for apache and araneida. Read <a href='http://bc.tech.coop/blog/051219.html'>this blog post</a> by
- Bill Clementson to form a more balanced opinion.</p>
- <h5>mod_lisp/mod_lisp2 for apache</h5>
- <p>You can choose between apache 1 and 2. First of course you have to have a Apache web
- server up and runnnig; then you have to add the mod-lisp module by Marc
- Battyani which you find at <a href='http://www.fractalconcept.com/asp/html/mod_lisp.html'>http://www.fractalconcept.com/asp/html/mod_lisp.html</a></p>
- <p>First download the mod_lisp c file. Watch out, don't follow the logic of the website. Except for the windows version the
- info is outdated concerning the apache 1 version and info about apache 2 is non-existent. Go to subversion from the
- download page or click the links below:</p>
- <ul>
- <li>apache 1 .c file -
- <a href='http://www.fractalconcept.com:8000/public/open-source/mod_lisp/mod_lisp.c'>mod_lisp.c</a></li>
- <li>apache 1 binaries for windows - there is a link on the site for version 2.32 but it leads to nowhere</li>
- <li>apache 2 .c file - <a href='http://www.fractalconcept.com:8000/public/open-source/mod_lisp/mod_lisp2.c'>mod_lisp2.c</a></li>
- <li>apache 2 windows binary -
- <a href='http://www.fractalconcept.com:8000/public/open-source/mod_lisp/windows/mod_lisp2.zip'>mod_lisp2.zip</a></li>
- </ul>
- <p>As stated in the intro, if you want to use ucw on a windows machine you're on your own. I have got no experience or information.</p>
- <p>If you went for the c module on a unix clone, use the command.</p>
- <pre>
- apxs -i -c mod_lisp.c
- </pre>
- <p>or</p>
- <pre>
- apxs2 -i -c mod_lisp2.c
- </pre>
- <p>for respectively apache 1 or 2. This will install the module in the appropriate apache directory. Debian users using apt-get should get one
- of the apache dev versions to get apxs(2) installed. Then add the following lines to 'httpd.conf' or other relevant configure file in your
- apache configuration directory for both apache 1 and 2. Just be sure to change mod_lisp.so to mod_lisp2.so for apache 2.</p>
- <pre>
- LoadModule lisp_module /path/to/modules/directory/mod_lisp.so
- </pre>
- <pre>
- LispServer 127.0.0.1 3001 ucw
- </pre>
- <pre>
- <LocationMatch "/path/.*\.ucw">
- SetHandler lisp-handler
- </LocationMatch>
- </pre>
- <p>This means that ucw INTERNALLY talks to apache on port 3001 at the internet address 127.0.0.1 (so in this case your
- localhost). The locationmatch part redirects all traffic from (in this case) 127.0.0.1 with prefix "/path/" and files ending
- on .ucw to ucw. So http://127.0.0.1/path/something.ucw as well as
- http://127.0.0.1/path/anotherpath/somethingelse.ucw will be redirected, but not http://127.0.0.1/somethingfaulty.ucw or
- http://127.0.0.1/path/somethingfaulty.html .</p>
- <h5>allegroserve or portableaserve</h5>
- <p>Should you want to use the aserve backend you will need to download
- and install either the AllegroServe if you use acl or portableaserve for any other. AllegroServe doesn't seem to have an
- asdf file, you're going to have to load it manually or however AllegroServe handles it's own files. Portableaserve does however.</p>
- <p>AllegroServe can be downloaded from here (it may be included in
- your version of acl): <a href='http://opensource.franz.com/aserve/'>http://opensource.franz.com/aserve/</a></p>
- <p>portableaserve is hosted on sourceforge: <a href='http://portableaserve.sf.net'>http://portableaserve.sf.net</a></p>
- <p>portableaserve download: <a href='http://constantly.at/lisp/aserve.tar.gz'>http://constantly.at/lisp/aserve.tar.gz</a></p>
- <p>To use portableaserve you'll also need the Allegro Common Lisp compatibility package (acl-compat). It's part of
- portableaserve and so it's home is also the before-mentioned sourceforge site.</p>
- <p>acl-compat download: <a href='http://constantly.at/lisp/acl-compat.tar.gz'>http://constantly.at/lisp/acl-compat.tar.gz</a></p>
- <h5>araneida</h5>
- <p>Should you want to use the araneida backend you will need to download araneida. Get the latest version just to be on the
- safe side. Originally araneida was meant to live behind apache and it can of course still be configured as
- such. Explaining this is beyond the scope of this document but have a look at this
- <a href='http://www.accela.net/~dankna/guide.html'>site</a> for more info.</p>
- <p>info: <a href='http://www.cliki.net/Araneida'>http://www.cliki.net/Araneida</a>}</p>
- <p>download: <a href='http://common-lisp.net/project/araneida/release/araneida-latest.tar.gz'>http://common-lisp.net/project/araneida/release/araneida-latest.tar.gz</a></p>
- <p>or use darcs, although the connection seems a bit slow:</p>
- <pre>
- darcs get http://verisons.telent.net/araneida/
- </pre>
- <h5>httpd</h5>
- <p>Ucw's in-house server. It's a simple server bundled with ucw. Nice for testing.</p>
- <p><span id='asdf'></span></p>
- <h3>asdf</h3>
- <p>To download it or read up on it go to <a href='http://cliki.net/ASDF'>http://cliki.net/ASDF</a></p>
- <p>Asdf makes sure common lisp packages and the files in those packages get loaded in the correct order. I would
- suggest you read the manual at
- <a href='http://constantly.at/lisp/asdf/'>http://constantly.at/lisp/asdf/</a>. Really the first
- <a href='http://constantly.at/lisp/asdf/Using-asdf-to-load-systems.html#Using%20asdf%20to%20load%20system'>link</a>
- is all you need to know right now.</p>
- <p>Basically every lisp package you downloaded so far has defined an .asd file. Usually in the root of the directory. This
- file has to appear in the search path of asdf, which is a list of directories defined by the special variable
- asdf:*central-registry*. The directories are typically called "systems". Under a unix clone, make a symbolic link to a systems dir
- as described in the document or as shown below. If a package defines
- more than one .asd file, just shove the whole dir on the *central-registry*, again as described in the document or as shown below.</p>
- <p>For example: on some linux installations the directory /usr/share/common-lisp/systems is in the list of asdf:*central-registry*.
- Now create a symlink from a particular .asd file to
- /usr/share/common-lisp/systems :</p>
- <pre>
- ln -s /path/to/library/lib.asd /usr/share/common-lisp/systems
- </pre>
- <p>To shove a whole directory on the *central-registry* do the following in your lisp startup file or in the repl:</p>
- <pre>
- (push #P"/path/to/asd/files/" asdf:*central-registry*)
- </pre>
- <p>All the required packages need to be recognized by asdf if you don't want to load every file by yourself.</p>
- <p><span id='extra'></span></p>
- <h2>Add-ons</h2>
- <p>Ucw also provides some packages which are kept out of the core so as not to bloat the program. Well two to be exact: the ucw presentations package and the ucw forms package.</p>
- <h5>presentations</h5>
- <p>An advanced CRUD interface for UCW.</p>
- <pre>
- darcs get http://common-lisp.net/project/ucw/repos/ucw-presentations
- </pre>
- <h5>forms</h5>
- <p>A more advanced HTML form toolkit for ucw than the one that is used in the core package, uses yaclml and dojo.</p>
- <pre>
- darcs get http://common-lisp.net/project/repos/ucw-forms
- </pre>
- <p><span id='testing'></span></p>
- <h2>Testing/Quickstart (for the non-boxset way)</h2>
- <p>When you have set up all your dependencies correctly, you can test ucw by first creating the directory /etc/ucw/applications.d, firing up your favorite distribution and:</p>
- <pre>
- (load "/path/to/ucw/etc/start.lisp")
- </pre>
- <p>If all went well, you have started ucw with the httpd backend. Surf to
- <a href='http://127.0.0.1:8080'>http://127.0.0.1:8080</a> and again if all went well you should see the example page. That's it! Start hacking!!</p>
- <p><span id='configure'></span></p>
- <h2>Configuration</h2>
- <p>At the moment the methods to configure and start ucw are a bit under development. But things seem to be stabling out. The elegant production compliant way of starting ucw is by launching ucwctl, found in /path/to/ucw/bin/ucwctl. This will start your lisp as a deamon. To let ucw find the proper configuration files, copy the files under /path/to/ucw/etc/ to either /your/home/.ucw or /etc/ucw.</p>
- <p>Ucwctl depends on cl-launch, to which a number of ucwtl's configure options are passed. It provides a suite of launch options to invoke lisp from the command-line. Be sure to put a link to cl-launch somewhere in your application search path. For general cl-launch understanding, read the cl-launch documentation.</p>
- <p>It's of course convenient to put ucwctl in the *nix executable search path but contrary to cl-launch it is not mandatory. Here's the configuration part of the ucwctl help output; -a, -c, -l, -k, -s and -t are passed to cl-launch:</p>
- <pre>
- -a, --asdf-root DIRECTORY Register asdf search DIRECTORY
- -c, --config-file FILE Read FILE as config file.
- -h, --help Display this help and exit.
- -k, --stop-file FILE Use FILE as stop file.
- -l, --lisp NAME Use NAME (without PATH) as Common Lisp
- implementation.
- --log-root DIRECTORY Save the logs in DIRECTORY, overriding the
- --var-root option.
- --run-root DIRECTORY Created pid/socket in DIRECTORY, overriding the
- --var-root option.
- -s, --start-file FILE Use FILE as start file.
- -t, --timeout SECONDS Set timeout in SECONDS when trying to stop a
- a running session.
- -u, --ucwctl-file FILE Read FILE as the ucwctl.conf file.
- --var-root DIRECTORY Save the logs in DIRECTORU/log/ucw and create
- pid/socket in DIRECTORY/run/ucw, if the two
- options --log-root and --run-root are not set.
- </pre>
- <p>In /path/to/configdir/ucwctl.conf default values are provided except for the lisp implementation and the .asd directory. So at the least you'd want to change them to point to the proper lisp and dir, or just specify those on the commandline. If you want to specify different paths for --log-root and --run-root in your config file, add LOGROOT=/path/to/log-root and RUNROOT=/path/to/run-root, leaving VARROOT empty. If you run ucwctl as user and didn't change ucwctl or supplied different paths for log-root and run-root (which default to paths under /var) on the commandline, they will default to paths under /your/home/dir/var. You can also specify a different ucwctl.conf file instead of /path/to/config-dir.</p>
- <p>To be clear this is the hierarchy of where ucwctl will pick its configuration from. Higher up the list will be chosen over lower on the list:</p>
- <p>1) command line options
- <br>
-
- 2) -u|--ucwctl-file (if specified, exit if it cannot be read)
- <br>
-
- 3) ~/.ucw/ucwctl.conf (if it exists)
- <br>
-
- 4) /etc/ucw/ucwctl.conf (if it exists)</p>
- <p>A deeper discussion is available at:</p>
- <p>http://common-lisp.net/pipermail/bese-devel/2006-April/001932.html
- <br>
-
- http://common-lisp.net/pipermail/bese-devel/2006-April/001961.html
- <br>
- </p>
- <p>Now you can start ucw by invoking:</p>
- <pre>
- ucwctl start
- </pre>
- <p>Without having configured anything (in /path/to/conf.lisp) this will start ucw with the built-in httpd server, just as with cl-launch. But
- now you have log files and more importantly you are not tied to a particular console. Point your browser at
- <a href='http://127.0.0.1:8080/'>http://127.0.0.1:8080/</a> and hope for the best. Hook up slime through port 4005 if you also actually want to code something.</p>
- <p>To stop ucw type:</p>
- <pre>
- ucwctl stop
- </pre>
- <p>To attach to a running ucw server type:</p>
- <pre>
- ucwctl attach
- </pre>
- <p>This calls attachtty, installed alongside detachtty, and passes attachy the socket, the path of which is defined in the ucwctl startup script. De-attach attachtty by giving it a sighup signal, eg by closing your terminal window or by pressing ctl-\. Note that you should be a bit careful when you attach to a socket and you start typing away at the repl. By default cl-launch will terminate the running process when the debugger is invoked. This behavior is changeable; check the cl-launch script (or not, someone on the mailing-list pointed out a bug).</p>
- <p>To test if ucw works with your chosen backend open /path/to/conf.lisp (to be found in /etc/ucw/conf.lisp if you copied it from
- /path/to/ucw_dev/bin/etc/) and change:</p>
- <pre>
- (setf *ucw-backend-type* ':httpd)
- (setf *ucw-backend-host* "127.0.0.1")
- (setf *ucw-backend-port* 8080)
- </pre>
- <p>to:</p>
- <pre>
- (setf *ucw-backend-type* ':mod-lisp)
- (setf *ucw-backend-host* "127.0.0.1")
- (setf *ucw-backend-port* 3001)
- </pre>
- <p>or to:</p>
- <pre>
- (setf *ucw-backend-type* ':araneida)
- (setf *ucw-backend-host* "127.0.0.1")
- (setf *ucw-backend-port* 8080)
- </pre>
- <p>or to:</p>
- <pre>
- (setf *ucw-backend-type* ':aserve)
- (setf *ucw-backend-host* "127.0.0.1")
- (setf *ucw-backend-port* 8080)
- </pre>
- <p>Repeat your chosen startup procedure for ucwctl with th note that if you use mod_lisp you have
- to point your browser at
- <a href='http://127.0.0.1/index.ucw'>http://127.0.0.1/path/you/specified/in/apache/this/link/goes/to/the/root/index.ucw</a>, without
- the 8080 (defaults to the server root here).</p>
- <p>note also that the default conf.lisp configuration defaults to the configuration in /path/to/ucw_dev/src/default.lisp which is the default
- configuration ;-) So if you don't change anything in conf.lisp you might just as well omit it. </p>
- <p>The variables in conf.lisp that we didn't cover yet are:</p>
- <pre>
- (setf *ucw-swank-port* 4005)
- </pre>
- <p>- used to connect to emacs, et al.</p>
- <pre>
- (setf *ucw-server-class* 'standard-server)
- </pre>
- <p>- leave as is. I'm not even sure if there is a non-standard server we should be interested in.</p>
- <pre>
- (setf *ucw-inspector* t)
- </pre>
- <p>- let's you inspect ucw inside the html pages you made when set to t. Seeing is believing. Set to nil to see the page as normal.</p>
- <pre>
- (setf *ucw-debugger* t)
- </pre>
- <p>- sends debugging html to the client when set to t. Seeing is believing. Set to nil to not send debugging info to the client and to invoke the debugger in your editor.</p>
- <pre>
- (setf *ucw-log-level* '+INFO+)
- </pre>
- <p>- Sets the log-level threshold for the information that will be logged by the base ucw logger and which will be pumped to the ucw.log
- file. these are the log levels to choose from, together with their value:</p>
- <p>+dribble+ = 0
- <br>
-
- +debug+ = 1
- <br>
-
- +info+ = 2
- <br>
-
- +warn+ = 3
- <br>
-
- +error+ = 4
- <br>
-
- +fatal+ = 5</p>
- <p>So in our example debug info and dribble will not be logged to ucw.log.</p>
- <pre>
- (setf *ucw-applications-directory* "/etc/ucw/applications.d/")
- </pre>
- <p>- sets the applications directory, see next chapter</p>
- <pre>
- (setf *ucw-systems* '(:ucw.admin :ucw.examples))
- (setf *ucw-applications* '(it.bese.ucw::*admin-application*
- it.bese.ucw-user::*example-application*))
- </pre>
- <p>- supply ucw applications to load. See next chapter.</p>
- <p><span id='environment'></span></p>
- <h2>Setting up the environment (and a hello world on the side)</h2>
- <p>Note that this procedure is not strict necessary, you could just fiddle around in ucw-user, but you will want to have
- your own proper environment sooner or later. To get the best of both worlds (being lazy and having a proper set up
- environment), just download the <a href='ucw-intro_source.tar'>code</a> we're going to create below (mod_lisp
- users, check the www-dir stuff below for a correct setup). For the less lazy, create a directory where you want
- to keep your application code. (halfway ripped from the cliki tutorial. thanks ;-)).</p>
- <p>Create an asdf file called ucw-intro.asd will contain:</p>
- <pre>
- (defpackage :ucw.intro.system
- (:use :cl :asdf))
- </pre>
- <pre>
- (in-package :ucw.intro.system)
- </pre>
- <pre>
- (defsystem ucw-intro
- :version "0.0.0.0.1"
- :depends-on (:ucw)
- :author "a lonely clown"
- :components ((:file "packages")
- (:file "config" :depends-on ("packages"))
- (:file "hello-world" :depends-on ("config"))))
- </pre>
- <p>and a package file called packages.lisp:</p>
- <pre>
- (in-package :cl-user)
- </pre>
- <pre>
- (defpackage :ucw-intro
- (:use :common-lisp
- :it.bese.ucw
- :it.bese.arnesi
- :it.bese.yaclml))
- </pre>
- <p>make a symlink from your asd file to the applications.d dir you defined in the last chapter.</p>
- <p>Important: when ucw loads it checks this directory for .asd files of your ucw applications. To let them load
- correctly you have to synchronize four names in your applications with standard pre- and suffixes:
-
- <ul>
- <li>the name of your applications asd file: name.asd (in this case ucw-intro.asd)</li>
- <li>the name of your applications package: :name (in this case :ucw-intro)</li>
- <li>the name of your application: *name-application* (in this case *ucw-intro-application*, see below in the ucw-intro.lisp code)</li>
- <li>the asdf system name of your package as defined with defsystem: :name (in this case :ucw-intro)</li>
- </ul>
- </p>
- <p>This procedure might be streamlined in the future, but for now we have to deal with it.</p>
- <p>There is also an alternative way of loading your applications when loading ucw. In /etc/ucw/conf.lisp (or where-ever you decided
- to put the file), push the name of your applications asd system name on *ucw-systems* and push it's application name (see below in the
- ucw-intro.lisp code), on *ucw-applications* like it's done for the ucws example applications:</p>
- <pre>
- (defvar *ucw-systems* '(:ucw.admin :ucw.examples))
- (defvar *ucw-applications* '(it.bese.ucw::*admin-application*
- it.bese.ucw-user::*example-application*))
- </pre>
- <p>If you don't want them to load, take them away from both conf.lisp and /path/to/ucw_dev/src/default.lisp.</p>
- <p>Just loading the three files we define(d) in this chapter while ucw is running will also register them correctly, no matter how we name the
- before-mentioned names.</p>
- <p>We also need a www root directory. This is the directory where we store static files for the http server to see: css and
- javascript files, pictures and the like. Lisp servers handle the www directory a bit different than mod_lisp so we have
- to make apt provisions. Lisp servers can themselves map a path from an incoming uri to the underlying directories on a
- server. When we use mod_lisp we have to tell apache as well as lisp where to go.</p>
- <p>When you use a lisp server backend, just create a directory in the tutorial root and call it www if you
- want to be in sync with this tutorial. With mod_lisp make a link from a directory somewhere in the apache www tree and in range of
- the mod_lisp search path as explained in the installation section. With apache 2 a typical path would be
- /var/www/locahost/htdocs/. The apache 1 www root normally also lies somewhere within that vicinity.</p>
- <pre>
- ln -s /path/to/ucw-intro/www var/www/localhost/htdocs/ucw-intro
- </pre>
- <p>Or link the other way around. </p>
- <p>Now we create two new file in our example application root called ucw-intro.lisp and config.lisp. config.lisp:</p>
- <pre>
- (in-package :ucw-intro)
- </pre>
- <pre>
- (defvar *www-root*
- (merge-pathnames
- (make-pathname :directory '(:relative "www"))
- (asdf:component-pathname (asdf:find-system :ucw-intro))))
- </pre>
- <pre>
- (defparameter *ucw-intro-application*
- (make-instance 'cookie-session-application
- :url-prefix "/ucw-intro/"
- :www-roots (list *www-root*)
- :dispatchers (list (make-instance 'ucw::action-dispatcher)
- ;; hello world
- (url-dispatcher "hello-world.ucw"
- (call 'hello-world)))
- :debug-on-error t))
- </pre>
- <p>hello-world.lisp:</p>
- <pre>
- (in-package :ucw-intro)
- </pre>
- <pre>
- (defcomponent hello-world (simple-window-component) ()
- (:default-initargs :title "hi"
- :stylesheet '("stylesheet.css" "stylesheet2.css")
- :content-type "text/html; charset=utf-8;"
- :javascript '((:src "dojo.js")
- (:js (dojo.require "dojo.event.*"))
- (:script "var foo = 3;")))
- ;; (:entry-point "hello-world.ucw" (:application *ucw-intro-application* :class url-dispatcher))
- (:render () (<:as-html "hello world")))
- </pre>
- <p>Load the files into your image and surf to http://127.0.0.1(:8080)/ucw-intro/hello-world.ucw, cross your fingers... and... now you've printed "hello world"! (If the heavens are willing).</p>
- <p>In the next chapter we will see what applications actually are, and we will examine the contents of ucw-intro.lisp. Also we will discuss
- the mechanics of ucw. Actually the next chapter is the most important chapter of this intro. Finally the foreplay is
- over.</p>
- <p><span id='mechanics'></span></p>
- <h2>Basic ucw mechanics</h2>
- <p>In the course of this chapter we will take a flight through website-making history. We begin with traditional website-making
- techniques and we will quickly work our way up. In the process you
- can't help but be introduced to the basic building blocks of a ucw program: components, actions, entry-points, applications and
- render methods. <a href='ucw-intro_source.tar'>Ready made source</a> is available.</p>
- <h4>Components, render methods, applications and entry points</h4>
- <h5>Components</h5>
- <p>Component have more than one role. First they act as your
- basic storage unit. They are classes and you can define them in the same way, but they have added
- functionality given through meta object protocol modifications. To explain these modifications we need some background
- on the inner workings of ucw: When ucw receives a http request it checks if the request is a part of user session
- already in progress. If not it creates a new one. Such a session is made up of frames. Every new request makes a new
- frame which is referenced by a random string. Every frame copies the values of relevant components and their slots from
- the frame before, except of course when the values of a given class have changed. If a user wants to go back to a
- previous page, the appropriate frame is looked up with the help of the identifier string (be it through get or a cookie),
- and the original values are restored. So frames are the memory of a ucw session. Some of the modifications made to
- components facilitate this process of getting and setting values in frames under the cover.</p>
- <p>Components are also clothes-hangers for html output. You generate html by defining render methods on them. In the case of
- our example the method renders (as you say) the simple-window-component hello-world, which is a pre-defined component to create an empty
- canvas. You can nest render methods of other components, in which case you piece the data together to form a complete page. With this
- information we can step through conf.lisp and hello-world.lisp from the last chapter:</p>
- <p>config.lisp:</p>
- <pre>
- (in-package :ucw-intro)
- </pre>
- <pre>
- (defvar *www-root*
- (merge-pathnames
- (make-pathname :directory '(:relative "www"))
- (asdf:component-pathname (asdf:find-system :ucw-intro))))
- </pre>
- <pre>
- (defparameter *ucw-intro-application*
- (make-instance 'cookie-session-application
- :url-prefix "/ucw-intro/"
- :www-roots (list *www-root*)
- :dispatchers (list (make-instance 'ucw::action-dispatcher)
- ;; hello world
- (url-dispatcher "hello-world.ucw"
- (call 'hello-world)))
- :debug-on-error t))
- </pre>
- <pre>
- (in-package :ucw-intro)
- </pre>
- <p>hello-world.lisp:</p>
- <pre>
- (defcomponent hello-world (simple-window-component) ()
- (:default-initargs :title "hi"
- :stylesheet '("stylesheet.css" "stylesheet2.css")
- :content-type "text/html; charset=utf-8;"
- :javascript '((:src "dojo.js")
- (:js (dojo.require "dojo.event.*"))
- (:script "var foo = 3;")))
- ;; (:entry-point "hello-world.ucw" (:application *ucw-intro-application* :class url-dispatcher))
- (:render () (<:as-html "hello world")))
- </pre>
- <h5>Applications</h5>
- <p>First we define the filesystem directory which is going to function as www-root for static data such as images, style-sheets and
- the like. We feed it to the definition of our
- first application object. An application is an arbitrary conceptual construct with which you define a number of
- options for a block of web-pages/site-logic. It lets you specify if you want to use cookies, what charset you want to use,
- etc. A quick tour of the chosen options: In this instance we want to use cookies, which means that ucw starts searching
- for certain cookie information after it has looked for information in other places. The url
- prefix is the browser path relative to the server root. Www-roots is a list of pathnames the application searches to get
- to static data relative to the the APPLICATION root. They are set relative to the
- url-prefix, eg in this example from the outside the www-root of ucw-intro is 127.0.0.1/ucw-intro/. Debug-on-error will or will not throw you in the debugger when things go wrong in this application, depending on if it is set to t or nil. The dispatchers we will cover later on.</p>
- <h5>defcomponent and render methods</h5>
- <p>The simple-window-component class and the defmethod macro that defines it can together be seen as as a convenience layer which
- constructs the underlying building blocks a standard application wants to have. In this section you will learn the
- semantics of both and you will learn how to define the building blocks without them.</p>
- <p>A simple-window-component sets up your basic html layout. You can feed a title, stylesheets, content-types, and
- different ways to insert javascript to :default-initargs. All of them accept a list as well as a
- basic unit suitable for the keyword, although you probably don't want to pass a list to the title argument as that will just print a quoted
- list. You can specify one or more javascript source files with the :src key, using :script lets you insert javascript as
- is and :js lets you insert javascript in parenscript syntax. With this information it sets up a whole page, except for
- the body. That's left for the render method.</p>
- <p>Defcomponent defines components almost the same as defclass defines classes. :default-initargs, slots, etc... are simply passed
- to the underlying defclass. But it has some extra options. You can supply a default backtrack function with :default-backtrack, you can supply a render method with :render, you can supply an entry-point with
- :entry-point and you can supply an action with :action. More on those last two in the next section, and more on :default-backtrack in a future chapter.</p>
- <p>As stated before, a render method is a regular method that specializes on a given component to output html. It is called when the program
- decides when it's time to put together a page to show the user. More on program flow in the next section of this chapter. The
- defcomponent macro passes the arguments from the :render form to a defmethod and let's it specialize on the name given
- to defcomponent. If no name is given the name default…
Large files files are truncated, but you can click here to view the full file