This is the mail archive of the kawa@sources.redhat.com mailing list for the Kawa project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Dynamic Web pages in Kawa


Some readers might be interested in a servlet I've written for
implementing dynamic Web pages in Kawa, when the application needs
session-tracking. The idea is that it's useful to view this as a state
machine. There's a state stored on the server; submitting a form sends an
action plus inputs to the server, which then makes a transition to a new
state, storing that in place of the old. The new state determines an
output page, which the server then displays.

Having programmed several applications of dynamic Web pages, I find that
it's useful to have the transition network - the details of how actions
determine transitions from state to state, and which pages are emitted as
a result - all in one place. (*) This is not how JSP and ASP encourage one
to code. It's also useful to be able to test the individual Web pages
without a server, by calling them directly from the Kawa top-level
interpreter. And since the details of associating state with a session and
updating it when input arrives are independent of the particular
transition network, these should be taken care of by the servlet.

To keep the semantics simple, and make testing from the TLI easy, I
compile Web pages into string-valued functions. (Page files get the
extension .pfn, for Page FunctioN; the servlet must be configured so that
the .pfn extension in a URL invokes it.). Each page is headed by a list of
its arguments. Passing information to the pages via arguments makes
explicit what they depend on, so makes them easier to maintain.

I've pinched the syntax from Bruce Lewis's BRL, so I use square brackets
for inserting the results of Kawa expressions into a page. So here's a
little .pfn file:
  (args title state)
  <html>
  <title> [ title ] </title>
  <h1> [ title ] </h1>
  [ (state->view state) ]
  </html>

I'm not sure that I'm as keen on square brackets as Bruce is (see his
advocacy at http://brl.sourceforge.net/brl_4.html ), but they do have the
advantage that one can preview such pages on a browser and check the HTML
content that way without confusing it by unrecognised HTML elements.

To read BRL pages, Bruce hacks the Kawa lexical analyser so that
characters between ] and [ are treated as strings. I didn't do that,
partly because I wanted my system to be independent of changes to Kawa's
internals. Instead, my servlet first passes a .pfn page through a
pre-processor which replaces ]...[-quoted text by strings, making the file
legal S-expressions. These are then fed to the page compiler, which
converts them to a lambda expression, which is then eval'ed to get a
function. When it comes time to use the page, the servlet supplies this
function with its arguments, calls it, and sends the resulting string
back to the Web server's output stream.

My .pfn pages can include other pages. Since pages are functions, to
include a page, one writes a function call. However, the name of the
function is replaced by the name of another page:
  (args title state)
  [ ("PageHeader" title) ]
  ... content ...
  [ ("PageFooter") ]
The page compiler replaces these by expressions which look up the included
file, compile it, then call it. For efficiency, I could cache the computed
page functions, but don't yet. Of course, these included pages can also be
tested directly from the Kawa TLI.

What about state handling? The servlet assumes that the application's
state is stored in a special slot in the Session instance. (This and
following paragraphs will make more sense if you know how Java implements
session-tracking.) To define the state transition network, the developer
must supply a next-page function, which takes a state, action and inputs
as arguments, and returns a next state and the name of a page to be
output. 

For example, I might write a search-engine application where the user
submits some keywords on a form and asks for them to be searched for. My
form must be coded to send the action 'search to the servlet, which will
pass it as a symbol to the next-page function. The servlet will also pass
the current state to this function, together with the data submitted, as a
map from HTTP names to values. My next-page function might return either
an error page and error state, if the keywords aren't found, or a success
page listing the answers to the search, and a state which indicates where
in this listing the reader is.

To my mind, one of the biggest design errors in HTML is the action URL in
forms. In the days of CGI, this usually named a script to process the
form's inputs; the browser would treat the name of this script as the name
of the resulting page. This meant that if a form could display several
different pages depending on the inputs (e.g. a success page or an error
page), the script would have to redirect to one or other of these, to
overcome the fact that the page name is hard-coded in the action URL. I
remember fighting with this about five years ago; from postings in various
fora about location headers, redirection headers, and browser
compatibility, so were a lot of other people!

In contrast, my action URLs are literally actions. To tell the servlet
which action a form wishes to invoke on the stored state, the form's
action URL must literally name an action - e.g. 
  <FORM ACTION=search.action METHOD=GET>
The servlet must be configured so that the .action extension also invokes
it. When it receives such a URL, it strips off the extension and any
directory part, and treats the rest as the name of the action, passing it
to the next-page function as above. Having computed the name of
the next page, the servlet will then do a redirect to it, so that the
browser sees a sensible name.

(Actually, if the session-tracking is implemented by URL rewriting, the
action URL must include the session id. The person coding the form will
have to call one of my standard functions, which encapsulates Java's
encodeUrl, to insert this.)

The code is available, should anyone be interested. It probably is not
terribly efficient yet.


(*) Note: this is one way to achieve a concise specification of how a Web
application behaves and how its pages are interrelated, rather than
splitting the information up between the pages. Another approach I've been
experimenting with is described on my U. of Minho site (in Portugal, so
access may sometimes be a bit slow), at
http://shiva.di.uminho.pt/~popx/talk.html with an example at
http://shiva.di.uminho.pt/~popx/web2.html . It assumes knowledge of
algebraic specification - there are some examples in one of the
specification languages, CafeOBJ.


Jocelyn Paine
http://www.ifs.org.uk/~popx/
+44 (0)7768 534 091 





Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]