Exposing an XQuery as a RESTful Data Service
The main task of a servlet is to respond to an HTTP request by assembling a response to be returned to the client. You've seen how XQuery excels at data integration tasks, treating all data sources as XML and returning XML as the result of any query, making XQuery a natural choice for data integration in servlets that return their results as XML or HTML.
First, I'll discuss how to expose an XQuery to the client using HTTP
GET or HTTP
POST operations, and then I'll discuss the design of the sample Java servlet that deploys the queries.
Calling an XQuery with GET
First, consider how to expose an XQuery so it can be called using HTTP
GET. The following code shows an XQuery containing an external variable, called
user:
declare variable $user as xs:string external;
<portfolio>
<user>{ $user }</user>
{
for $h in collection('HOLDINGS')/holdings
where $h/userid = $user
return
<stock>
<ticker>{ xs:string($h/stockticker) }</ticker>
<shares>{ xs:string($h/shares) }</shares>
</stock>
}
</portfolio>
You'd access this query using a URL similar to the one shown below, which specifies the name of the query (in the URL parameter "q") and a value for the external variable:
http://tagsalad.org/xquery?q=portfolio&user=jonathan
Using the servlet described later in this section, a developer can write an XQuery, test it locally, and then deploy it by placing it in a server-side deployment directory, where the query is protected from the outside world. After deployment, HTTP clients can invoke the query and obtain results using the simple URL shown above.
Calling an XQuery with POST
GET requests are fine for simple queries, but when query parameters have complex structure or need to be given XML Schema datatypes, it is generally better to specify parameters in the content of an HTTP
POST requestthe approach generally used for SOAP web messages. The following example shows an XQuery and an XML message that contains the query parameter. If an HTTP request has content, the servlet attempts to parse it as XML, binding the result to the variable
$content:
portfolio.xquery -- a query with an external variable
declare variable $content as document-node() external;
let $user := string($content/parameters/user)
return
<portfolio>
<user>{ $user }</user>
{
for $h in collection("HOLDINGS")/HOLDINGS
where $h/USERID = $user
return
<stock>
<ticker>{ xs:string($h/STOCKTICKER) }</ticker>
<shares>{ xs:string($h/SHARES) }</shares>
</stock>
}
</portfolio>
To run the XQuery post a message to the URL that specifies the name of the query (in the URL parameter '
q') and carries the parameters as
POST data to obtain query results. Here's an example of the URL and the HTTP
POST content:
http://tagsalad.org/xquery?q=portfolio
HTTP CONTENT:
<parameters><user>Jonathan</user></parameters>
To make such queries work, you need an intermediary to accept the web requests (GET or POST) and run the appropriate query. That's what the XQuery RESTful servlet does.