Skip to main content

skip to main content

developerWorks  >  Web development  >

AjaXQuery

Using Ajax with XQuery In Web applications

developerWorks
Go to the previous pagePage 4 of 10 Go to the next page

Document options
PDF format - Fits A4 and Letter

PDF - Fits A4 and Letter
365 KB (26 pages)

Get Adobe® Reader®

Sample code


My developerWorks needs you!

Connect to your technical community


Rate this tutorial

Help us improve this content


A tale of two applications: part 1

Build your first application—an application that doesn't use Ajax with XQuery.

The business requirements

Congratulations! You have just been promoted to chief information officer (CIO) of FishinHole.com, an e-commerce corporation that markets fishing tackle over the Internet. Your marketing department has just informed you that there is a desperate need for a search facility on the Web site. This facility must let users search for lures by usage (casting or trolling) and configuration (minnow shaped or spoon shaped). This is a great chance for you to make a good first impression.

Before you got promoted, your predecessor kept the entire FishinHole.com catalog in XML format. So, you won't need to worry about querying against a relational database to fulfill these requirements. However, you will need to query the XML document as shown in Listing 1.


Listing 1. fishinhole.xml
	
<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>
...
               

The existing FishinHole.com Web site is already implemented as a Java enterprise application running with the Spring Framework on a Tomcat server. Those technologies will be left in place.



Back to top


Coding it out

The first thing you need to do is to put the framework in place, then you can build the actual implementation of this business requirement on top of that. By way of analogy, you first create the skeleton, then you put meat on the bones. So, you configure your web.xml file as shown in Listing 2.


Listing 2. web.xml
	
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xmlns="http://java.sun.com/xml/ns/javaee" 
	xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
		http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
	id="WebApp_ID" version="2.5">

  <display-name>FishinHole</display-name>
  
  <servlet>
  	<servlet-name>FishinHole</servlet-name>
  	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  	<load-on-startup>1</load-on-startup>
  </servlet>
  
  <servlet-mapping>
  	<servlet-name>FishinHole</servlet-name>
  	<url-pattern>*.htm</url-pattern>
  </servlet-mapping>
  
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
  </welcome-file-list>
 
</web-app>

               

Of particular importance in this listing is that the Web application is configured to use the DispatcherServlet that the Spring Framework provides. URLs that use the FishinHole context and end with the .htm extension will be intercepted by that servlet.

You are following conventional patterns for implementing the solution. One pattern is the familiar MVC pattern, which separates information representation (the model) from presentation (the view) from response to user input (the controller). This will be accomplished using the Spring Framework.

Another pattern you will implement is a strong separation of concerns between your controller and your data-access object. The old-schoolers may refer to this as the Business Delegate pattern. Sometimes, it is just called a service or a manager.

The first thing you implement is the data-access object, shown in Listing 3. This is the code that accepts criteria and queries the XML document for elements that match the criteria. You decide on a simple StAX parser for this purpose.


Listing 3. LuresDao
	
public class LuresDao {
	
private static final String XML_FILE			= "c:/fishinhole/fishinhole.xml";

public List<Lure> fetchLuresByUsageAndConfiguration(String usage,String configuration) {
	List<Lure> lures = new ArrayList<Lure>();
	
       try {
           XMLInputFactory inputFactory = XMLInputFactory.newInstance();
           
           InputStream in = new FileInputStream(XML_FILE);
           XMLEventReader eventReader = inputFactory.createXMLEventReader(in);
           boolean usageMatch = false;
           String currentBrand = null;
           Integer currentSize = null;
            
           while (eventReader.hasNext()) {      
              XMLEvent event = eventReader.nextEvent();      

             if (event.isStartElement()) {            	   
           	   if (event
			.asStartElement()
			.getName()
			.getLocalPart()
			.equals(usage)) {
            		   usageMatch = true;
           	   }
           	   
           	   if (event
			.asStartElement()
			.getName()
			.getLocalPart()
			.equals("minnows") 
			&& configuration.equals("minnow") && usageMatch) {
           		   QName qName = QName.valueOf("brand");
           		   currentBrand = event
						.asStartElement()
						.getAttributeByName(qName)
						.getValue();
          		   
           		   qName = QName.valueOf("size");
           		   currentSize = new Integer(event
								.asStartElement()
								.getAttributeByName(qName)
								.getValue());
           	   }

           	   if (event
			.asStartElement()
			.getName()
			.getLocalPart()
			.equals("spoons") 
			&& configuration.equals("spoon") && usageMatch) {
           		   QName qName = QName.valueOf("brand");
           		   currentBrand = event
						.asStartElement()
						.getAttributeByName(qName)
						.getValue();
            		   
           		   qName = QName.valueOf("size");
           		   currentSize = new Integer(event
								.asStartElement()
								.getAttributeByName(qName)
								.getValue());
           	   }

               if (event
			.asStartElement()
			.getName()
			.getLocalPart()
			.equals(configuration) && usageMatch) {
                	   QName qName = QName.valueOf("color");
                	   String color = event
						.asStartElement()
						.getAttributeByName(qName)
						.getValue();
                	  
                	   Lure lure = new Lure();
                	   lure.setConfiguration(configuration);
                	   lure.setColor(color);
                	   lure.setBrand(currentBrand);
                	   lure.setUsage(usage);
                	   lure.setSize(currentSize);
                	   lures.add(lure);
                	   
                     continue;
               }
             } else if (event.isEndElement()) {
           	   if (event.asEndElement().getName().getLocalPart().equals(usage)) {
           		   usageMatch = false;
           	   }
	       }
          }
        } catch (FileNotFoundException e) {
           e.printStackTrace();
        } catch (XMLStreamException e) {
            e.printStackTrace();
        }
        
        return lures;
	}
}
               

It is beyond the scope of this tutorial to explain the use of StAX. The basic idea behind this code is that the method fetchLuresByUsageAndConfiguration accepts two parameters: usage and configuration. Usage refers to how the lure is actually used (casting or trolling). Configuration refers to the physical shape of the lure (spoon or minnow). The method searches the XML document found at C:\fishinhole\fishinhole.xml for elements that match that criterion. It then translates those elements into a list of lure objects, simple beans with properties that identify important information about the lures.

The service component simply implements one method (also called fetchLuresByUsageAndConfiguration) and delegates that method to LuresDao.

The controller defines what happens when a user accesses the FishinHole Web context and the catalog.htm page, shown in Listing 4.


Listing 4. CatalogController
	
protected ModelAndView handleRequestInternal(HttpServletRequest request,
		HttpServletResponse response) throws Exception {
	ModelAndView mv = new ModelAndView();
	mv.setViewName("catalog");
	String usage = request.getParameter("usage");
	String configuration = request.getParameter("configuration");
	
	System.out.println("usage is " + usage);
	System.out.println("configuration is " + configuration);
	
	if (usage != null 
		&& !usage.equals("") 
		&& !usage.equals("0")) {
		
		if (configuration != null 
			&& !configuration.equals("") 
			&& !configuration.equals("0")) {
			List<Lure> lures = luresService
				.fetchLuresByUsageAndConfiguration(usage, configuration);
			mv.addObject("lures", lures);
			System.out.println("size is " + lures.size());
		}
	}
	
	return mv;
}
               

The idea here is that if catalog.htm looks at the URL string for two parameters—usage and configuration—and both of those parameters exist and have valid values, the controller invokes fetchLuresByUsageAndConfiguration on the service. The service, as you will recall, returns a list of lure objects that match those criteria. This list is then added to the model, where the JavaServer Pages (JSP) page can display it.



Back to top


Deployment

If you haven't done so already, this would be an excellent time to go the Downloads section and grab the first Web archive (WAR), FishinHole.war. For licensing reasons, the Java archives (JARs) needed to actually run the WAR—shown below—on the Tomcat server were not included:

  • ddxq.jar
  • ddxqsaxon8.jar
  • ddxqsaxon8a.jar
  • commons-logging-1.1.1.jar
  • jstl.jar
  • log4j-1.2.9.jar
  • spring-web.jar
  • spring-webmvc.jar
  • spring.jar
  • standard.jar

The good news is that all the JAR files except for the first three can be found within the Spring distribution. The others are part of XQJ. See Resources for information on downloading these technologies.

When you have obtained the necessary JAR files, simply include them in the WEB-INF/lib directory of the WAR file. This is as simple as treating the WAR file as a standard compressed file (for example, a file in ZIP format) and adding those files to that location.

When the WAR file is complete, you need to put the data and configuration files in place. For purposes of this tutorial, it's assumed that these files will reside in the C:\fishinhole directory. In that directory, you should have the following files:

  • fishinhole.xml
  • searchResults.xq

The second file will not be used in this part of the tutorial, but go ahead and put it there anyway as a forward-looking measure.

If you need to change the location of the files for any reason, please make sure that you update the appropriate line in Listing 3.

Now, launch Tomcat and deploy the WAR file. Doing so requires a basic understanding of Tomcat server administration, which is beyond the scope of this tutorial. It is assumed that you are running the server on localhost (127.0.0.1) and using port 8080 to listen for requests. The latter is the Tomcat default.



Back to top


The fruits of your labor

Open a browser, and point your URL to http://localhost:8080/FishinHole/catalog.htm. You should see something like Figure 1.


Figure 1. The Catalog page
A screen shot shows the Catalog page with a menu and Latest News on the left side bar.  In the main content is a selection area with Preferred Lure Type and drop boxes for Usage and Configuration followed by a search button.

Now, from the Usage drop-down list, select Trolling; from the Configuration drop-down list, select Minnow. Click Search. You should now see something like Figure 2.


Figure 2. The search results
Another screen shot of the Catalog page with the menu and Latest                   News Unchanged.  The Preferred Lure Type still has drop boxes for the                   Usage and Configuration followed by a Search button.  However, since the                   search has executed there are a series of columns filled with data                   showing Brand, Color, Configuration, Size and Usage. The drop boxes both                   read --Select--.

A couple of things should be noted at this point. First, did you notice how the entire page reloaded when you clicked Search? It was quick, but it happened. If you didn't notice, feel free to perform another search. Select a different combination, then click Search again. The entire page reloads.

Another thing to note is that the default options are selected from the drop-down lists. In this case, the --SELECT-- options are preselected as opposed to the actual options that you selected. Yes, this is fixable with some JavaServer Pages Standard Tag Library (JSTL) work and server-side settings, but the point is that when the entire page is reloaded, you have to account for setting those values. If, however, only a small subset of the page is reloaded, independent of the drop-down lists, then you don't have to worry about tracking and resetting the appropriate values.



Back to top


An unexpected response

You show these results to your marketing department personnel and quickly learn that this solution is not acceptable. They inform you that entire page reloads and the default values being displayed in the drop-down lists after the search results are unacceptable to your customer base. They begin to question your ability as a CIO. You go home depressed.

That night you have a dream about Ajax.



Back to top



Go to the previous pagePage 4 of 10 Go to the next page