Use XQuery for the presentation layer

Separate concerns without being tied to a particular language

Many Web applications use the Model-View-Controller (MVC) pattern to separate the three concerns. These applications frequently use PHP or JavaServer™ Pages (JSP) technology in the presentation layer. While those technologies are widely accepted and certainly effective, they do not represent a language-independent means of presentation. On the other hand, like Structured Query Language (SQL), XQuery is a lookup specification tied to the XML standard, which is language- and platform-independent. Using XQuery for presentation enables view-side developers to create robust presentation effects without tying the view to any particular underlying application server or programming language. In this article, explore the advantages of XQuery over other view technologies, how XQuery is implemented in the presentation layer, and a realistic example of such an implementation.

Brian M. Carey, Information Systems Consultant, Triangle Information Solutions

Photo of Brian CareyBrian Carey is an information systems consultant who specializes in the architecture, design, and implementation of Java enterprise applications.



10 March 2009

Also available in Chinese Russian Japanese Portuguese

Advantages of using XQuery for presentation

Frequently used acronyms

  • Ajax: Asynchronous JavaScript + XML
  • HTML: Hypertext Markup Language
  • IP: Internet protocol
  • JAR: Java Archive
  • PHP: PHP Hypertext Preprocessor
  • RSS: Rich Site Summary
  • URL: Uniform Resource Locator
  • W3C: World Wide Web Consortium
  • WAR: Web Archive
  • XML: Extensible Markup Language

By now, just about the entire Web development community understands the benefits of the MVC pattern. This is the pattern that separates the model (information content) from the view (what the user sees on the screen) from the controller (what happens in response to user input or a browser that points to a URL).

Most developers, when opting to implement some variation of the MVC pattern, usually choose Java™ Platform, Enterprise Edition 5 (Java EE) technology. This is certainly a robust solution, as the Java programming language is state-of-the-art technology. Further, popular frameworks, such as Spring and Struts, facilitate an MVC pattern in distributed object applications.

But the immutable law of software development is that best practices are always evolving. If that weren't the case, then Twitter would have been written in Pascal. Standards evolve, and best practices reinvent themselves or are sometimes completely supplanted by newer methodologies and solutions. The short conclusion is that even though Java Enterprise technology is frequently implemented, it is also yesterday's news. And the same can just as easily be said of other MVC implementations distinct from the Java programming language.

So what's the contemporary answer? XQuery as the view used in conjunction with XML as the data represents an even better way to split the concerns. There are reasons for this, which I will describe.

XQuery is married to XML

Develop skills on this topic

This content is part of a progressive knowledge path for advancing your skills. See Querying XML from Java applications

Although software development best practices are always evolving, some technologies are here for the long haul. One of those technologies is XML. XML presents information in a hierarchical structure with elements and attributes usually written in easy-to-read language. In other words, XML represents the best of both worlds: information that can be read by humans and computers alike.

As it stands, XML is the almost universally accepted means of information interchange within the software development community. This is especially true when platform and language independence is a requirement, such as with Web services. It is also used for Web feeds because both RSS and Atom rely on XML. The returned results from Representational State Transfer (REST) invocations are often in XML format. It is even frequently used for software configuration purposes.

Given the ubiquitous nature of XML, it makes sense to use it as the model in an MVC pattern. And since the prevailing standard for querying XML is with XQuery, it makes even more sense to use that technology when establishing the view. XQuery further sells itself in this way because it also enables transformation. The developer can extract the necessary information from an XML document and also display it in a manner fitting to the application requirements.

Using XQuery prevents "cheating"

Sometimes developers are tempted to use hacks as a quick fix to problems. This is not necessarily the fault of the developers because sometimes software delivery deadlines dictate shortcuts to make things happen quickly rather than properly. But this is a political discussion for another article.

MVC developers can frequently "cheat" by including business logic code directly in the presentation layer, instead of the service layer where it belongs. The most popular example of this is using scriptlets in JSP code. Most JSP developers have been tempted (and, truth be told, have probably succumbed to the temptation) to do this at one time or another.

The good news about using XQuery for the view is that developers simply can't do that anymore. You cannot write business logic in XQuery because XQuery focuses exclusively on querying and transformation. Purists might argue that you should perform querying in another layer as well, but bear in mind that, with XQuery, variables can be externally bound, effectively enabling an adaptable query based on variables defined from another layer.

XQuery does not bind the application to a particular language

XML is the preferred means of data exchange between software applications when language independence is desired. A PHP application can read the exact same XML document that a Java application can read, although they use completely different means of doing so.

Conversely, a Java bean, which is frequently used as the model in a Java Enterprise application, cannot easily be read by a PHP application. Likewise, a Java application cannot read a PHP array that maps attribute names to values. In those cases, the model is bound directly to the programming language, which inhibits data exchange.

XML is not so constrained. Almost every language (if not every language) recognizes the importance of reading, parsing, and creating XML documents for data representation. XML documents can be shared from application to application with nary a concern about the language used by each application in the process.

Recall from the previous section that software best practices are always evolving. It is likely that XML will outlast whatever prevailing languages exist today, and this means applications that use XML for the model (as opposed to a model confined to a specific language) can be updated with next year's preferred technology at minimal impact. For example, if your model is Java beans, and next year you need to upgrade your application to .NET, you will also need to update the model in accordance with your language of choice for that environment. However, if your model is XML, no update is required because .NET can read XML documents.

Building an XQuery-based MVC application

One morning, while you browse through your e-mail and sip your daily dose of coffee, your manager pops into your office and informs you that you must deliver the corporate Web site, fishinhole.com, in a language-agnostic manner. He also informs you, with apparent glee, that not only must you deliver the Web site with language independence in mind, but you must also retain the MVC pattern. Then he mercifully turns around and leaves.

Much of what your manager said is lost because you were busy concentrating on the ketchup stain on his pocket, but the essence of it is clear. Using a popular design pattern (MVC), you must rewrite the code of the corporate Web site so the model and the view are not bound to a particular programming language. That's when you put your thinking cap on and ponder the implementation.

The implementation

You understand that no software application is completely language-independent (yet) because every piece of software must be written in some language. Still, the possibility of moving fishinhole.com in that direction is quite feasible with the right technologies.

With that in mind, you retain the controller in the Java programming language. This is the code that actually forwards a URL request to the proper resource. You also retain the Spring framework, which is written in the Java programming language. Spring brings a lot to the table beyond simple MVC capabilities, such as middle-tier access, transaction management, aspect-oriented programming (AOP), dependency injection, and so on.

For language independence, you adopt XML as the model. The reasons for choosing XML, coincidentally, are identical to the reasons you once read in an article on IBM's developerWorks Web site about using XQuery for the presentation layer.

XQuery seems like the natural choice for the view. Once again, XQuery provides not only a facility to query XML documents but also to transform them. This way, the resulting query not only returns the correct results but also transforms those results into HTML format, which any browser can view.

Next, you need an XQuery implementation. The optimal choice for this is XQuery API for Java (XQJ) library from DataDirect. The reason that this is the optimal choice is because XQJ, like your controller, is written in the Java programming language. The XQJ library is also the most popular and robust XQuery implementation written in the Java programming language.

What about the platform? The Web site (fishinhole.com) is already deployed to an Apache Tomcat application server. Because everything that you pondered about the code rework is compliant with Apache Tomcat, you decide that the next iteration of the application can be deployed to that server as well.

The business requirements

Thankfully, your manager didn't change the business requirements. He just dictated a change to the underlying implementation. So all you need to do is deliver the exact same set of requirements as they currently exist using MVC with XQuery.

The requirements are simple. The Web site enables users to browse a catalog of lures based on usage and configuration. Usage can be one of two options (casting or trolling). Configuration can be one of two options (spoon or minnow). The idea is that when a user selects a usage option and a configuration option and then clicks a Search button, the screen displays a list of lures that match the selected criteria.

It's also important to note that an outstanding requirement of this application is to respond to user input with limited page refreshes. This is currently done with an Ajax implementation. You realize that this is a non-negotiable point from the marketing department, so you also continue with the Ajax implementation.

The model

As stated previously, the model is retained in XML format. The model needs to maintain several pieces of information about each lure, including price, configuration, availability, shipping region, and usage. As a result, your model looks just like the document fragment in Listing 1.

Listing 1. The model in XML format
<lures>
 <casting>
  <minnows brand="Yohuri" style="deep" size="3">
   <minnow color="midnight blue">
    <international-prices>
     <price denomination="dollar">3.25</price>
     <price denomination="euro">4.25</price>
     <price denomination="canadian-dollar">4</price>
     <price denomination="peso">100</price>
    </international-prices>
    <availability>
     <shipping>
      <delay>0</delay>
     </shipping>
     <regions>
      <shipping-region>United States</shipping-region>
      <shipping-region>European Union</shipping-region>
      <shipping-region>Canada</shipping-region>
      <shipping-region>Mexico</shipping-region>
     </regions>
    </availability>
   </minnow>
...
</lures>

The XML document itself should be self-explanatory. Each element and attribute is intuitively named so that even the casual reader familiar with the XML specification can visually parse the information.

The controller

The idea behind the controller is to provide code that can use XQJ to query and transform the aforementioned XML document. You determine that a simple servlet, which uses XQJ as a dependency, is sufficient for this purpose. This keeps the Java code to a minimum and achieves your goal of language independence for the model and view.

The Ajax function mentioned earlier is invoked when the user clicks the Search button. This function relies on the simple servlet to obtain the HTML fragment (which is transformed XML) and dynamically replace the contents of a DIV tag with that HTML fragment. It is important to note here that this Ajax implementation uses a POST, as opposed to a GET, to process the request.

Because the Ajax implementation uses a POST method, the simple servlet must therefore implement the doPost, as opposed to the doGet, method. Listing 2 shows that implementation.

Listing 2. The doPost method
public void doPost(HttpServletRequest request, HttpServletResponse response) 
	throws ServletException, IOException {
 try {
	PrintWriter out = response.getWriter();
		
	String usage = request.getParameter("usage");
	String configuration = request.getParameter("configuration");
				
	if (usage != null && !usage.equals("") && !usage.equals("0")) {
		if (configuration != null && 
		 !configuration.equals("") && !configuration.equals("0")) {
			String xqFile = "c:/fishinhole/searchResults.xq";
			String lures = fetchLuresByUsageAndConfiguration
			 (usage, configuration, xqFile);
			System.out.println(lures);
			out.write(lures);
		}
	}
 } catch (Exception e) {
	e.printStackTrace();
 }

In a nutshell, this method reads two POSTed parameters (configuration and usage), queries the XML document based on the values of those parameters, and returns the transformed XML document back to the response. The contents of this response are replaced with the contents of the DIV tag in the original page, as mentioned previously.

First, the method obtains the writer for the HttpServletResponse object. This is where your output is written.

Next, the code obtains the values of two parameters: usage and configuration. These parameters are set in the POST that Ajax invokes on the main catalog page.

The next couple lines are error proofing. They basically trap for null or empty values in the event that the user clicks the Search button without selecting valid options for both usage and configuration.

Next, the location of the XQuery file is specified. I will disclose the contents of this file in more detail a little later. For now, it's important to understand that this file contains the actual XQuery code that parses and transforms the XML document that is the model.

The fetchLuresByUsageAndConfiguration method, in Listing 3, is a local method that relies on XQJ to fulfill the query and transformation portion of the code.

Listing 3. The fetchLuresByUsageAndConfiguration method
private String fetchLuresByUsageAndConfiguration(String usage, 
	String configuration, String xqFile) throws Exception {
		
	// Data source for querying
	DDXQDataSource dataSource = new DDXQDataSource();

	// Connection for querying
	XQConnection conn = dataSource.getConnection();
		
	XQExpression expression = getGenericExpression(conn); 
		
	expression.bindString(new QName("configuration"), configuration, 
		conn.createAtomicType(XQItemType.XQBASETYPE_STRING));

	expression.bindString(new QName("usage"), usage, 
		conn.createAtomicType(XQItemType.XQBASETYPE_STRING));

	FileReader fileReader = new FileReader(xqFile);
	XQSequence results = expression.executeQuery(fileReader);

	return results.getSequenceAsString(new Properties());
}

private XQExpression getGenericExpression(XQConnection conn) throws XQException {
	XQExpression expression = conn.createExpression();
		
	expression.bindString(new QName("docName"), "c:/fishinhole/fishinhole.xml",
		conn.createAtomicType(XQItemType.XQBASETYPE_STRING));

	return expression;
}

You'll see the details of this method anon. For now, please note that it returns a String object, which is simply the HTML fragment that represents the transformed XML. Finally, the string that was returned in the previous line is written to the response.

The fetchLuresByUsageAndConfiguration method relies on three parameters. The first is the lure usage. The second is the lure configuration. The third is the location of the XQuery file mentioned previously.

First, the code instantiates (with an empty constructor) a DDXQDataSource object. The DDXQDataSource class, as with most of the classes in this method, is from the XQJ library.

Next, the data source object is used to obtain an XQConnection object. This object is then passed into the getGenericExpression object. In that method, you bind the parameter name, docName, to the string location of the XML document that represents the model. An XQExpression object, with the bound value, is returned back to the fetchLuresByUsageAndConfiguration method.

Then two more strings are bound to the XQExpression object. Not surprisingly, these are the configuration and usage values, respectively.

A standard FileReader object is instantiated with the location (as a string) of the XQuery file in the constructor. With this FileReader object, the XQExpression object then executes the query in the file, using the previously bound values.

The results of that query are returned as a String object. This is the String object that is the HTML fragment.

The view

While the model for the new and improved version of fishinhole.com is in XML format, the view is determined from XQuery. XQuery enables not only querying of XML documents, but also transformation. In this case, the transformation is from XML to HTML and, therefore, easily visible with any Web browser. Listing 4 shows the XQuery that performs the query and the transformation.

Listing 4. The XQuery file (searchResults.xq)
declare variable $docName as xs:string external;
declare variable $configuration as xs:string external;
declare variable $usage as xs:string external;

<table width="100%" class="searchResultsTable">
	<tr>
		<th>Brand</th>
		<th>Color</th>
		<th>Configuration</th>
		<th>Size</th>
		<th>Usage</th>
	</tr>

{
if ($configuration = 'minnow' and $usage = 'casting') then
for $minnows in doc($docName)//casting/minnows
return
<div>
	{
	for $minnow in $minnows/minnow
	return
		<tr>
			<td>{data($minnows/@brand)}</td>
			<td>{data($minnow/@color)}</td>
			<td>{$configuration}</td>
			<td>{data($minnows/@size)}</td>
			<td>{$usage}</td>
		</tr>
	}
</div>
...

The first thing to note in Listing 4 is the first three lines. You might recall that these are the same three variables that were bound to values within the controller code.

Next comes the first part of the transformation. In this case, the transformation starts with a TABLE element and its respective headers.

Next comes some actual XQuery code. This code performs querying so that only the results that match the user-provided configuration and usage are returned. In this specific case, if the configuration value is minnow and the usage value is casting, a query matching those two values is executed and the results returned. Please note that for the sake of space not all cases are provided in Listing 4.

The specific query here locates all minnows elements within each casting element. Within each minnows element, all minnow elements are then located and relevant values are extracted. The relevant values are brand (an attribute), color (an attribute), configuration (a bound value), size (an attribute), and usage (another bound value).

Also note that the results are each returned within HTML TD elements, or table cells. All of the table cells are wrapped within a table row (TR), which in turn is wrapped in a DIV element. This part of the transformation puts the results of the query into an HTML table.

The catalog page

The catalog page is the entry point for the application. This is where the user has the option to select the usage and configuration criteria. When the user clicks the Search button, the results that match the selected criteria are displayed on the page in an easy-to-read format.

Most of this page is written in HTML. However, Ajax is also required to prevent a page refresh when the user clicks the Search button. And the j in Ajax stands for JavaScript. So, there is JavaScript code in this page as well. Listing 5 displays that code.

Listing 5. The JavaScript code that invokes Ajax
function search() {
	var usageElement = document.getElementById("usageSelect");
	var configurationElement = document.getElementById("configurationSelect");
	
	var usage = usageElement.options[usageElement.selectedIndex].value;
	var configuration = 
	 configurationElement.options[configurationElement.selectedIndex].value;
	
	if (usage == "0") {
		alert("Please select a usage!");
		return;
	}
	
	if (configuration == "0") {
		alert("Please select a configuration!");
		return;
	}
	
	var parameters = {};
	parameters["usage"] = usage;
	parameters["configuration"] = configuration;
	
	var resultsDiv = document.getElementById("searchResults");
	
	ajax("./updateResults",parameters,function(success,response) {
		resultsDiv.innerHTML = response;
	});
}

This JavaScript function executes when the user clicks the Search button. The first few lines retrieve the values from the drop-down list boxes in which the user selects usage and configuration, respectively. What follows is some validation logic to ensure that the user actually selected values prior to clicking the Search button.

Next, an empty array is created. The array is then populated with the values that were established by the user's selections from the drop-down lists. In this case, the JavaScript array acts like a hash map. In other words, the values are not associated with numerical index values within the array but actual string values. The string values are, not surprisingly, called usage and configuration, respectively.

Next, a JavaScript variable is associated with the DIV element in which the results are displayed.

Finally, the Ajax code is invoked. The URL used is ./updateResults, and this URL is mapped to the servlet controller that was explained previously (in Listing 2). The parameters array is passed in so the values that the user selected can be processed by the servlet. After a successful response, the innerHTML property of the DIV element is populated with transformed XML (or HTML) returned by the servlet controller.

Putting it all together

The important thing to note here is the configuration. In this case, both the model and the XQuery file are placed in the c:/fishinhole directory. The sample code reviewed so far and the downloadable code provided with this article both rely on those two files in that location. Fortunately, this is easily modifiable if that's not possible for any particular deployment.

Because of intellectual property reasons, the libraries required by the provided WAR file are not included within the archive. These libraries are:

  • commons-logging.jar
  • ddxq.jar
  • ddxqsaxon8.jar
  • ddxqsaxon8sa.jar
  • spring.jar
  • spring-web.jar
  • spring-webmvc.jar

For information about obtaining these files, see Resources.

After you include the JAR files listed above in the WEB-INF/lib directory of the included WAR file, you are ready to deploy. While it is beyond the scope of this article to provide an in-depth explanation of deploying a WAR file, it is a simple administrative task that you can accomplish using Tomcat's included manager application.

After you deploy the application, point your browser to the URL:

http://<server>:<port>/FishinHole/catalog.htm

where <server> is the IP address of your Web application server and <port> is the port for your Web application server. For most local deployments, you can use http://localhost:8080/FishinHole/catalog.htm.

The catalog page first displays with absolutely no catalog items. This is because you haven't selected lure criteria yet. In the drop-down list boxes, select Casting in the Usage list and Minnow in the Configuration list. Then, click the Search button. It might take a few seconds the first time, but ultimately you should see what is in Figure 1.

Figure 1. The results
Screen capture of results on catalog page

You show your results to your manager, who seems none too pleased that you were able to meet these requirements. He sulks out of your office, knowing that it will be that much harder for him to get your job. You sit back and take another sip of your latte.

Conclusion

Using XML as the model and XQuery as the view is a powerful way to provide a language-agnostic solution while still retaining the benefits of using the MVC pattern. The history of software development has proven solutions that are independent of a particular software implementation have more longevity and, in the long run, are more cost effective. Using XQuery to query against and transform an XML model is an excellent way to make that happen in a contemporary Web application.


Downloads

DescriptionNameSize
The WAR file sans librariesFishinHole.war11KB
The XML document that represents the modelfishinhole-xml.zip1KB
The XQuery filesearchResults-xq.zip1KB

Resources

Learn

  • An introduction to XQuery (Howard Katz, developerWorks, June 2001, updated January 2006): Look at the W3C proposed standard for an XML query language, including background history, a road map into the documentation, and a snapshot of the then-current state of the specification. Also, get a quick look at some key features of XQuery's surface syntax.
  • Use XQuery from a Java environment (Brett McLaughlin, developerWorks, April 2008): Learn how to search documents with XQuery from Java applications.
  • Ajax: The author finds Wikipedia a good place to start learning about almost any subject. Ajax is no exception.
  • IBM XML certification: Find out how you can become an IBM-Certified Developer in XML and related technologies.
  • XML technical library: See the developerWorks XML Zone for a wide range of technical articles and tips, tutorials, standards, and IBM Redbooks.
  • developerWorks technical events and webcasts: Stay current with technology in these sessions.
  • developerWorks podcasts: Listen to interesting interviews and discussions for software developers.

Get products and technologies

  • Spring: Get the downloads necessary to compile and run the code presented in this article. This is where you'll find spring.jar, spring-web.jar, and spring-webmvc.jar.
  • Apache Tomcat: Download and try the application server on which these code samples were tested.
  • Java: Obtain Sun's standard edition of the Java programming language.
  • An XQJ Tutorial: Introduction to the XQuery API for Java: In this tutorial, find instructions to download and use XQJ. This is how you'll obtain ddxq.jar, ddxqsaxon8.jar, and ddxqsaxon8sa.jar.
  • Commons Logging: Get the commons-logging.jar that supports several popular logging implementations.
  • IBM trial software for product evaluation: Build your next project with trial software available for download directly from developerWorks, including application development tools and middleware products from DB2®, Lotus®, Rational®, Tivoli®, and WebSphere®.

Discuss

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into XML on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=XML, Java technology, Open source
ArticleID=374557
ArticleTitle=Use XQuery for the presentation layer
publish-date=03102009