Using Qexo, you can run an XQuery program as a Servlet. This makes it easy to have them be executed by a web server.
See this article for a simpler how-to for deploying a servlet.
Suppose the file hello.xql contains an XQuery "program".
(Below we show an example of what you can do with Kawa-XQuery servlets.)
You compile hello.xql to servlet using the following command.
$KAWA --xquery --servlet -C hello.xqlHere
$KAWA is how you invoke the Kawa application.
For example if you use kawa-1.7.jar, you can do:
java -jar kawa-1.7.jar --xquery --servlet -C hello.xql
The -C flag tells Kawa to compile the following source
files. The --xquery flags tells Kawa that the source files are
in the XQuery language. (The default language is Scheme.) The
--servlet tells Kawa to generate a servlet.
The result of the compilation is usually a single class file
hello.class that implements
javax.servlet.http.HttpServlet.
Sometimes Kawa will need to generate some extra helper classes;
these will all have the form hello$XXX.class.
To copy or install all the generated classes you should
type hello*.class.
There are a number of Web servers that can run servlets,
and most of them have various fancy ways of creating "web applications".
Here are some simple instructions for running your servlet
under Tomcat.
Tomcat is a web server
written in Java and released by the Apache Foundation's Jakarta project.
The instructions here assume version 4.0 of Tomcat,
and that $CATALINA_HOME is where Tomcat is installed.
You first need to install the Kawa jar file
kawa-1.7.jar somewhere where Tomcat can find it.
For example install it in $CATALINA_HOME/lib/kawa-1.7.jar.
You next need to install your servlet.
In Tomcat (and the Servlet specification) a servlet is part of a
"web application". If you call your application myutils,
you need to create directories $CATALINA_HOME/webapps/myutils,
$CATALINA_HOME/webapps/myutils/WEB-INF, and
$CATALINA_HOME/webapps/myutils/WEB-INF/classes.
You then copy your servlet class files hello*.class
into the latter directory.
After you have started up Tomcat, it by default listens to port 8080.
To try out your servlet, point a browser to the URL
http://localhost:8080/myutils/servlet/hello.
See the Tomcat documentation for how you can customize how Tomcat maps URLs to servlets and how they are executed.
cgi-wrapper program that lets you
run servlets
as if they were CGI scripts.
There are also useful functions for getting
HTTP request
information,
setting HTTP
response headers,
and the unescaped-data function for raw HTMP/XML output..
This example generates a response listing some of the properties of the request. An explanation follows.
define function invoke-row ($field,$style) {
<tr><td>{$field}</td><td><{$style}>{invoke($request,$field)}</></td></tr>}
define function do-invoke ($field,$style) {
invoke-row($field,$style),"
" }
<p>Hello, the request was {$request}.
The response was {$response}.</p>,
<pre>The request URI was (using path) {$request/requestURI}.
The request method (using path) was {$request/method}.
The path-info (using path) was {$request/pathInfo}</pre>,
<table>
<tr><th>Field name (using invoke)</th><th>field value</th></tr>
{do-invoke("getRequestURI","strong"),
do-invoke("getContentType","code"),
do-invoke("getProtocol","u"),
do-invoke("getRemoteAddr","code"),
do-invoke("getRemoteHost","code"),
do-invoke("getScheme","code"),
do-invoke("getServerName","code"),
do-invoke("getServerPort","code"),
do-invoke("getAuthType","code"),
do-invoke("getMethod","code"),
do-invoke("getPathInfo","code"),
do-invoke("getPathTranslated","code"),
do-invoke("getQueryString","code"),
do-invoke("getRemoteUser","code"),
do-invoke("getRequestURI","code"),
do-invoke("getServletPath","code")
}</table>
This program illustrates how you can use the prefined variables
$request and $response. The former is
the most useful, as it contains the information that the browser
sent to the servlet. The $response variable has more
exotic uses for controlling the response.
Both variables are passed to the servlet by the servlet engine,
and have the types javax.servlet.http.HttpRequest
and javax.servlet.http.HttpResponse respectively.
The program first defines the function invoke-row, which takes
two parameters, in addition to the implicit $request parameter.
The body of the function is an "element constructor expression"
which contructs a table row (<tr>) element.
This looks like plain HTML (actually XML), but you can nest arbitrary
expressions in them using curly braces to "escape" nested expressions.
The $field parameter is a string that names a 0-argument
Java method of the $request object.
The built-in Kawa method invoke takes an object, a
Java method name, and optionally some methods args. It calls the named
method with the given arguments.
The result from invoke is wrapped in an HTML style
tag that is specified by the $style parameter.
The result is made into a table row.
The do-invoke function is just a simple wrapper that calls
invoke-row. It then appends a newline using the
comma operator, which concatenates the operands to create a sequence.
In this case the result is a sequence with two values:
a <tr> element node, and a newline string.
This effecticely adds a newline in the HTML after the
<tr> element, which makes the HTML more readable.
The other reason for adding the do-invoke function
is to illustrate how you can pass complex values around, with the
result of one function being "pasted" into the result of another.
Note that the Kawa implementation does not actually do any
copying in this case; the elements are written directly into the
servlet result buffer.
The main body of the function is two "element constructor expressions",
the pre and the table constuctors,
which again are concatenated using the comma operator, resuling in
a sequence consisting of two elements.
The pre element contaisn the nested
expression $request/requestURI. This is a convenience
feature of Kawa-XQuery. It means to extract the requestURI
"property" of the $request object.
A property name like "requestURI" is mapped into a
method name "getRequestURI", and basically the
expression $request/requestURI is equivalent to
invoke(request, "getRequestURI").
The final part of the program just makes a lot of calls to
do-invoke to build a big <table>.
The Kawa servlet wrapper automatically wraps the entire result
in a <html>...</html> wrapper.
You can see a sample of the generated output,
using the URL http://localhost:8080/myutils/servlet/hello/mypath.
The Qexo debugging page has some general
notes on Qexo error behaviour and debugging.
Here are some notes specific to using servlets and
KawaPageServlet.
If you request an .xql after editing it,
KawaPageServlet will automatically re-compile it.
This makes it easy to test out changes.
If you make a syntax error, the result sent to the browser
will contain the error messages from the compiler.
If a run-time errors causes an uncaught run-time exception, Tomcat will
return to your browser a stack trace showing which methods were active when
the exception was created.
The methods that
Tomcat re-directs the standard error output
to the file KawaPageServlet compiles
from your XQuery program will be in that stack trace with
(if you're lucky) line numbers
referring to the lines in your XQuery program.
You may have to dig through the stack trace, and ignore methods belonging
to the Kawa or Tomcat run-time environment. You may also have to
look for the root cause.
$CATALINA_HOME/logs/catalina.out.
This includes data written using the standard trace function.
Per Bothner
Last modified: Wed Dec 1 16:40:47 PST 2004