Login | Register   
RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


An XQuery Servlet for RESTful Data Services : Page 4

Find out how to expose XQuery data integration services by invoking them through a Java servlet using a REST interface.


WEBINAR: On-demand Event

Unleash Your DevOps Strategy by Synchronizing Application and Database Changes REGISTER >

Implementing the XQuery RESTful Servlet
The examples shown in the previous two sections illustrate the requirements for a RESTful servlet. Queries must be protected from the outside world, but easily deployed by copying them into a deployment directory that is accessible to the server. Queries can be parameterized using URI parameters and/or the content of a HTTP request. The result of a query is returned to the client as the result of the HTTP request.

This servlet is written in Java and implements the Servlet API. It uses XQJ, a Java API that serves as "the JDBC for XQuery," to invoke XQueries. To improve performance, the servlet prepares each query and places it in a HashMap the first time a client invokes that query. You can see the complete servlet code in Listing 1. Here's an outline of the structure of that program.

When the servlet is initialized, the init() method shown below creates an empty HashMap to hold prepared queries, sets indentation properties, and connects to the data sources used on the server.

public void init() { xqueryMap = new HashMap(); indentationProperty = new Properties(); indentationProperty.setProperty("indent", "yes"); try { dataSource = new DDXQDataSource( new FileInputStream(XQueryServlet.CONFIG_FILE)); connection = dataSource.getConnection(); } catch (Exception exception) { System.out.println("Could not initialize DataDirect " + "XQuery due to an Exeption:"); exception.printStackTrace(); } }

When the servlet terminates, the destroy() method closes all open connections.

public void destroy(){ try { if(connection != null){ connection.close(); } } catch(XQException anException){ //just making sure that a close took place. //no real work to perform on this Exception } }

HTTP requests from the client result in calls to doPost(), doGet(), or doPut(), but all these methods delegate to a method called doXQuery(), which actually executes the requested query and creates the result.

The doXQuery method first obtains a prepared query by calling findXQuery(), then creates XQuery external variables with the same names and values as parameters found in the HTTP URI. These variables have type xs:string, but the query can cast them to any desired type. The servlet parses any HTTP content in the request as XML and binds it to the variable $content, which can be used in a query. Finally, doXQuery executes the query and writes the result to the return buffer.

The findXQuery() method takes the name of a requested query as a parameter and returns a prepared query. The findXQuery() method first checks the HashMap to see if this query has already been prepared and is up to date; if so, it simply returns the existing prepared query. Otherwise, it looks for the query in the XQuery deployment directory (which is specified in the WEB.XML file shown in Listing 3), prepares the query, adds it to the HashMap, and returns the prepared query. Here's the findXQuery method code:

private XQPreparedExpression findXQuery(String shortName) throws Exception{ //TODO: is the date needed? //Date now = new Date(); String xqueryFileName = shortName + XQueryServlet.XQUERY_FILE; XQueryMapEntry entry = null; entry = (XQueryMapEntry)xqueryMap.get(shortName); if (entry != null) { File xqueryFile = new File(xqueryFileName); if (entry.getDate().before(new Date( xqueryFile.lastModified()))) { // The prepared query is stale - prepare again entry.setQuery(connection.prepareExpression( new FileReader(xqueryFileName))); return entry.getQuery(); } else { // The prepared query exists and is up to date return entry.getQuery(); } }

Figure 2. Data Integration with an XQuery Servlet: The servlet uses the REST interface to select and parameterize XQuery queries. XQuery can query each data source and integrate results, eliminating the need for many APIs.
else { // This query has not yet been prepared and // added to the map entry = new XQueryMapEntry(); entry.setQuery(connection.prepareExpression( new FileReader(xqueryFileName))); xqueryMap.put(shortName, entry); return entry.getQuery(); } }
Figure 2 shows the revised architecture after implementing the XQuery servlet.

As you've seen, it's not terribly difficult to create an XQuery servlet that implements the Java Servlet API, using XQJ to issue XQueries. But it's a powerful idea, because developers can develop data services by writing queries in XQuery, testing them, and simply copying them to the deployment directory. The servlet makes deployed queries instantly available to users, providing an HTTP interface determined by the query name and its parameters. This development/deployment simplicity is an extremely productive way to create data services.

Editor's Note: The author, Jonathan Robie, is the XQuery Technology Lead for DataDirect, a vendor of XQuery products. We have selected this article for publication because we believe it to have objective technical merit.

Jonathan Robie is the XQuery Technology Lead at DataDirect Technologies, which specializes in data integration, data connectivity and mainframe integration products. He is a co-inventor of XQuery and an editor for many of the specifications which define the XQuery language. He is also a co-inventor of Quilt, a predecessor of XQuery, and XQL, a predecessor of XPath.
Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date