The example we are talking about can be found in ucwTutorialExample
How webactions workThe webactions are a much more traditional web development framework. I cite from the manual:
The webactions framework supports a programming methodology called Model View Controller (or MVC). In a dynamic web application the pieces are these:So webactions have much more in common with web development applications written in other languages, examples which come to my mind are .adp, .jsp or .asp pages.
1. Model - this is the code that implements the data objects being manipulated by users of the web site. In an online store the model includes the notions of a shopping cart and orders and so on. This is the code that must be written specifically for the objects being modeled.
2. View - the html pages that show the user a view of the model. These pages are usually clp pages in the webaction framework. There will be some clp functions to implement the dynamic parts of the pages.
3. Controller - the code that accepts user input and passes control to the model to process the input and finally selects a view to send back to the user. This code is supplied with the webaction framework.
I'd argue that starting with webactions is much easier and "more comfortable" and less problematic then starting web-programming with ucw.
The programming exampleWe use the same data model as for the ucw Tutorial, it can be found at ucwTutorialDatamodel. We can start with presenting that page in simple html:
< ?xml version="1.0" encoding="UTF-8"?> < !DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> < html> < head> < title>Friedrichs webactions tutorial< /title> < link rel="stylesheet" type="text/css" href="/css/qss.css" /> < /head> < body> < h1> Welcome page< /h1> < p> Welcome to our "impressive" entry page. You will encounter the miracles of Webactions here but before we can proceed let us know who you are< /p> < form action="print-name" method="post" < table> < tr> < td>Your name:< /td> < td> < input type="text" maxlength="20 name="name" /> < /td> < /tr> < /table> < p> < input type="submit" value="Submit" /> < /form> < /body> < /html>
Very simple and understandable by anyone having seen html before ;-)
The webactions side The whole code for just getting to that pages is:
(defvar *example-app* nil) (setf *example-app* (webaction-project "example-app" :destination "/home/frido/lib/cl/web-pages/tutorials/" :index "index" :project-prefix "/lsp/wa-tutorial/" :map '(("index" "greetings-page.clp"))))
So let's see: we define a
webaction-project with the name "example-app", the files for this applicaton can be found below the
:destination directory. The entry point is "index" and the project is published below "lsp/wa-tutorial". It currently consist just of one entry called "index" which will in the end render the "greetings-page.clp".
That's the file name I gave to the above printed html-page.
Webactions to depens on AllegroServe, however I have some Apache running here as the primary web server so we have to setup this properly. I decided to run it behind the Apache which just tunnels this stuff through to PortableAllegroServe. This can be done easyily e.g in httpd.conf like this:
ProxyPass /lsp/ http://localhost:8081/lsp/ ProxyPassReverse /lsp/ http://localhost:8081/lsp/
That's enough to get this example running. (of course you have to load mod_proxy for that to work). If you have problems setting up this combination, just let me know and I see whether I can help you with it.
Ah yes a thing you should not forget: Starting the server. That's the easy part a
(start :port 8081) is sufficient. Logging will take place on the command line but changing that is not very difficult.
Acting in webactionsAs you can see I want the following action to take place: "print-name". Now here comes the map into play. You just put all the files which make up a project into the
:mappart of the webactions project. So we do that also:
The webactions way is as follows:
- Display a form
- Have an action defined which acts on submitting the form
- have another page for displaying the results and/or next forms
So we extend the map with:
("print-name" action-print-name) ("display-name" "display-name.clp"))))
Writing the actionYou can name the actions as you like. I stick to the convention adding an action to the name to signal that this function is for acting on submit of the form.
Now in actions the "application" logic takes place. You modify the state of you model, query or set a variables for the next form. In this case it's very simple. We just store the name somewhere and render the next page. I will just use clp pages for that. You can use some lisp-generated html for that if you like to. But just let us go strongly with how things are done in other server pages.
(defun action-print-name (req ent) (declare (ignore ent)) (let ((name (request-query-value "name" req))) (setf (request-variable-value req "name") name) "display-name"))
As you can see this looks very "traditional". I can get the value of the
input field with
request-query-value. And then I have the choice on where to save it. I can save it just for one request (as done here with
request-variable-value, I can save in for the session with
(setf (websession-variable session key) value... or I could save it away for e.g. in a database.
Now there's just one thing left. Displaying the result to the user. For that I wrote another .clp page which just the following "extra":
Welcome < clp_value name="name" safe request />. Nice to have you here.
Here you can see a special tag starting with
clp_. This are tags which are replaced by webaction before beeing send to the browser. I saved the name in a request so I "pick" it from there. that the
request part of the tag. The
safe is just for escaping all the things which might be in the value. E.g I could have written Friedrich and this would then be rendered strong. Other things (far worse things could have happen if I hand over this stuff unchecked), so you have some "safety" belt...
ConclusionIf you compare the steps in ucw Tutorial with the written stuff here, you probabyl agree that webactions are much less demanding. If you ever have encountered some sort of server pages you understand webactions immediatly. The logic is probably easy to understand and you do not have to understand the whole bunch of components, actions, continuations.
However it is quite useful to have a few components build in, E.g in webactions there is a login component, there are the validation functions, and quite a few other components like dates etc. All this has to be written for webactions... So in the end you have to decide what *You* found easier. Getting into UCW or writing more yourself.