Kawa makes it easy to set up a web site without configuration files. Instead, the mapping from request URL to web page script matches the layout of files in the application directory.
Many web servers make it easy to execute a script using a script
processor which is selected depending on the extension of the
requested URL. That is why you see lots of URLs that end in
.jsp. This is bad, because it
exposes the server-side implementation to the user: Not only are such
URLs ugly, but they make it difficult to change the server without
breaking people’s bookmarks and search engines. A server will usually
provide a mechanism to use prettier URLs, but doing so requires extra
effort, so many web-masters don’t.
If you want a script to be executed in response to a URL
http://host/app/foo/bar you give the script the name
app/foo/bar, in the appropriate server “application”
directory (as explained below). You get to pick the name
Or you can use the name
bar.html, even though the file named
bar.html isn’t actually
an html file - rather it produces html when evaluated. Or better: just use
a name without an extension at all.
out what kind of script it is based on the content of the file,
rather than the file name. Once Kawa has
found a script, it looks at the first line to see if it can recognize
the kind (language) of the script. Normally this would be a comment
that contains the name of a programming language that Kawa
knows about. For example:
;; Hello world page script written in -*- scheme -*- #<p>Hello, <b>&(request-remote-host)</b>!</p>
(Using the funny-looking string
-*- scheme -*- has the
bonus is that it recognized by the Emacs text editor.)
A script named
+default+ is run if there isn’t a matching script.
For example assume the following is a file named
;; This is -*- scheme -*- (make-element 'p "servlet-path: " (request-servlet-path))
This becomes the default script for HTTP requests that aren’t handled
by a more specific script.
returns the "servlet path", which is the part of the requested URL
that is relative to the current web application. Thus a request for
http://host:port/app/this/is/a/test will return:
The easiest way to run a Kawa web server is to use the web server built in to JDK 6 or later.
kawa --http-auto-handler context-path appdir --http-start port
This starts a web server that listens on the given port,
using the files in directory appdir to handle
requests that start with the given context-path.
The context-path must start with a
"/" (one is added if
needed), and it is recommended that it also end with a
(otherwise you might get some surprising behavior).
You can specify multiple
For example use the files in the current directory to handle all requests on the standard port 80 do:
kawa --http-auto-handler / . --http-start 80
There are some examples in the
the Kawa source distribution. You can start the server thus:
bin/kawa --http-auto-handler / testsuite/webtest/ --http-start 8888
and then for example browse to
For lots of information about the HTTP request, browse to
You can also can use a “servlet container”
such as Tomcat or Glassfish with self-configuring script.
See Servlets for information on how to install
these servers, and the concept of web applications.
Once you have these server installed, you create a
web application with the following in the
appdir/WEB-INF/web.xml configuration file:
<web-app> <display-name>Kawa auto-servlet</display-name> <servlet> <servlet-name>KawaPageServlet</servlet-name> <servlet-class>gnu.kawa.servlet.KawaPageServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>KawaPageServlet</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> </web-app>
This creates a web application where all URLs
are handled by the
gnu.kawa.servlet.KawaPageServlet servlet class,
which is included in the Kawa jar file.
KawaPageServlet class handles the searching
and compiling described in this page.
When Kawa receives a request for:
it will look for a file:
If such a file exists, the script will be executed, as described
below. If not, it will look for a file name
+default+ in the same
directory. If that desn’t exist either, it will look for
in the parent
directory, then the grand-parent directory, and so on until it gets to
the appname web application root directory. So the default script is
If that doesn’t exist then Kawa returns a 404 "page not found" error.
Once Kawa has found a script file corresponding to a request URL, it needs to determine if this is a data file or a web page script, and in the latter case, what language it is written in.
Kawa recognizes the following "magic strings" in the first line of a script:
The Scheme language.
The XQuery language.
Some other language known to Kawa.
Kawa also recognizes Emacs-style "mode specifiers":
-*- scheme -*-
The Scheme language.
-*- xquery -*-
The XQuery language (though Emacs doesn’t know about XQuery).
-*- emacs-lisp -*-
-*- elisp -*-
The Emacs Lisp extension language.
-*- common-lisp -*-
-*- lisp -*-
The Common Lisp language.
Also, it also recognizes comments in the first two columns of the line:
A Scheme or Lisp comment - assumed to be in the Scheme language.
Start of an XQuery comment, so assumed to be in the XQuery language.
If Kawa doesn’t recognize the language of a script (and it isn’t named +default+) then it assumes the file is a data file. It asks the servlet engine to figure out the content type (using the getMimeType method of ServletContext), and just copies the file into the response.
Kawa automatically compiles a script into a class. The
class is internal to the server, and is not written out to
disk. (There is an unsupported option to write the compiled file to a
class file, but there is no support to use previously-compiled
classes.) The server then creates a module instance to handle the
actual request, and runs the body (the
of the script class. On subsequence
requests for the same script, the same class and instance are reused;
run is re-executed.
If the script is changed, then it is re-compiled and a new module instance created. This makes it very easy to develop and modify a script. (Kawa for performance reasons doesn’t check more than once a second whether a script has been modified.)