[an error occurred while processing this directive]
> developer > web app development
Writing JSP Using the exteNd Composer JSP Tag Library
by exteNd Composer Product Team, eBusiness Integration Products, Novell
Date Created: 2001-12-18 15:47:00.000
  Introduction
  The tag
  The and tags
  The and tags
  The tag
  Deployment
  Conclusion
Introduction

The Composer JSP tag library provides an easy way to execute Composer Web Services and perform XPath operations on the XML output from within Java Server Pages. It presently consists of six tags that perform such tasks as service execution and conditional JSP processing based on evaluation of XPath expressions. 

NOTE: This article assumes the user has a basic knowledge of the eXtend Composer product and of XPath expression syntax. 

In a nutshell, an eXtend Composer Web Service takes an XML document as its input and returns an XML document as its output. For the sake of this example, let's assume that the XML input has been generated elsewhere (perhaps from a form on another web page) and is appropriately included in the HTTP request to our JSP. We'll focus solely on how to handle the XML output that the service returns. Our fictitious service will be called "OrderList".  "OrderList" represents a list of orders that might come out of an on-line bookstore database. Below is sample XML that our service might generate if a request was made for all the orders for a given week (it's a small bookstore): 

<ORDERLIST>

  <ORDER>

    <DATE>9/10/2001</DATE>

    <CUSTOMER>

      <NAME>Matthew Collins</NAME>

      <ADDRESS>2 Infinite Loop</ADDRESS>

      <CITY>Cupertino</CITY>

      <STATE>CA</STATE>

      <ZIP>95014</ZIP>

    </CUSTOMER>

    <ITEMLIST>

      <ITEM>

        <TITLE>Learning Cocoa</TITLE>

        <ISBN>0596001606</ISBN>

        <PRICE>34.95</PRICE>

      </ITEM>

    </ITEMLIST>

  </ORDER>

  <ORDER>

    <DATE>9/11/2001</DATE>

    <CUSTOMER>

      <NAME>Peter Holland</NAME>

      <ADDRESS></ADDRESS>

      <CITY>New York</CITY>

      <STATE>NY</STATE>

      <ZIP>10019</ZIP>

    </CUSTOMER>

    <ITEMLIST>

      <ITEM>

        <TITLE>Macs for Dummies</TITLE>

        <ISBN>0764507036</ISBN>

        <PRICE>21.99</PRICE>

      </ITEM>

    </ITEMLIST>

  </ORDER>

</ORDERLIST>     

As you can probably tell, we have a list of two different customer orders each for one book.  The JSP page we're creating will present order lists in this format in an HTML table.

the tag

The first thing our JSP page has to do is to execute the eXtend Composer service that we've cleverly named "OrderList". Below is a JSP snippet that does just that (note that the line numbers are only included for clarity):

1: <%@ page language="java"

2:          session="false"

3:          isThreadSafe="false"

4:          contentType="text/html; charset=ISO-8859-1" %>

5:

6: <%@ taglib uri="/composer" prefix="composer" %>

7:

8: <composer:execute name="orderlist" service="com.sample.OrderList" />

Let's take a closer look at what we're doing here. The first four lines identify this file as a JSP page. On the sixth line, we are defining our tag library via a URI (more on this in the section on deployment) and defining a prefix for it. The prefix assures that the JSP engine associates a custom JSP tag with the appropriate tag library.

Line 8 is where we actually execute the Composer Service. Note that the tag name includes the composer prefix as well as the tag name execute. In this example, the tag has two attributes: name and service.

The name attribute uniquely identifies a service's XML output on a JSP page. Since we allow multiple services to be executed on the same page, it provides a way for subsequent tags to refer to a previously executed service. That being the case, this attribute must be unique from the name attribute in other <composer:execute> tags within the same JSP page.

The service attribute defines the eXtend Composer service that we are executing. Note that the service name must be fully qualified; that is, it must include any context that the project was created or deployed with. In our case, that context is com.sample

As an aside, there are two additional attributes that are not used in this example. They are  optional and reasonable defaults; and they  are provided if they are not present:

root - in most cases, the input document to web-accessible Composer services is built dynamically based on the parameters in the HTTP request. This attribute specifies what the root element name of that dynamically generated document should be. If not specified, the default is "ROOT"

converter - specifies the converter class name used (default uses the converter class for "HttpUsingParams").

If the service executes successfully, we will have access to its XML output for use in our JSP. Let's look at what we can do with it.

the and tags

Since this is a list of orders, we need some way to iterate through the list. We also need a way to print portions of the list as we iterate through it. The <composer:forEach> and <composer:value> tags do just this. Let's take a look at another JSP snippet:

 1: <table border="1">

 2:   <tr>

 3:     <td><b>Customer</b></td>

 4:     <td><b>Order Date</b></td>

 5:     <td><b>Items</b></td>

 6:   </tr>

 7:   <composer:forEach name="orderlist" xpath="/ORDERLIST/ORDER">

 8:     <tr>

 9:       <td>

10:         <composer:value xpath="./CUSTOMER/NAME" /><br>

11:         <composer:value xpath="./CUSTOMER/ADDRESS" /><br>

12:         <composer:value xpath="./CUSTOMER/CITY" />,

13:         <composer:value xpath="./CUSTOMER/STATE" />

14:         <composer:value xpath="./CUSTOMER/ZIP" />

15:       </td>

16:       <td>

17:         <composer:value xpath="./DATE" />

18:       </td>

19:         <ul>

20:           <composer:forEach xpath="./ITEMLIST/ITEM">

21:               <li><composer:value xpath="./TITLE" /></li>

22:           </composer:forEach>

23:         </ul>

24:     </tr>

25:   </composer:forEach>

26: </table>

 

In the first six lines we start the HTML table and create a row with our column headers. On line 7 we call the <composer:forEach> tag with two attributes. The name attribute should be the same as the name that we specified in a previous <composer:execute> tag. Again, this tells the tag library what service this tag should process against. The xPath attribute defines the XPath expression that should be applied to the XML. In <composer:forEach> tags, this expression should evaluate to a Nodelist ; in our case, it's a list of <ORDER> nodes. If the expression does not evaluate to a Nodelist  (or to an empty list of nodes), the <composer:forEach> body will not be executed. 

Since <composer:forEach> is an iteration tag, the body will execute the same number of times as there are nodes in the Nodelist generated by the XPath expression. In our example, there are 2 nodes, so the body will be executed twice. The body content can consist of JSP, HTML or other custom tags. In the above example, the body first creates a new HTML table row. It then creates three columns, the first two of which contain <composer:value> tags.

The <composer:value> tag provides a way to print out the result of an XPath expression as a string. Furthermore, it is aware of the context in which it is being called. If a relative XPath expression is used, it is evaluated within the context of the nearest Composer ancestor tag. If none exists, it defaults to the root of the XML output document. In our example above, because the first <composer:value> tag is nested within a <composer:forEach> tag, its relative XPath expression ./CUSTOMER/NAME will be evaluated in the context of the current /ORDERLIST/ORDER being iterated on. The same holds true for the other <composer:value> tags within <composer:forEach>.

It is also important to note that we've omitted the name attribute from the <composer:value> tags. As is the case with all the Composer tags, if the name attribute is missing, the name of the nearest ancestor is used (in our case, the <composer:forEach> tag). If no ancestor is available, the default name service1 is used. If there is no corresponding <composer:execute> tag with name service1, the page will generate an error. Thus, it is a good practice to qualify tags with the name attribute where it might lead to confusion.

Going back to the example, in the third column we use another <composer:forEach> tag to iterate through the items in order. Note that its XPath expression is also relative to the expression of the ancestor <composer:forEach> node. This code generates an unordered HTML list of the items in the order.

the and tags

Since the JSP is responsible for generating output seen directly by the end-user, a certain degree of output flexibility is needed when it generates its HTML from the service output XML. XPath is a powerful expression language, but there are some commonly used expressions that are encapsulated as tags to aid in clarity and ease of use.

The <composer:hasvalue> and <composer:hasnovalue> tags will conditionally execute based on whether their XPath expressions evaluate to a string of a certain length. The <composer:hasvalue> tag will evaluate if the length of the string resulting from the XPath expression is greater than zero. Conversely, the <composer:hasnovalue> tag will evaluate if the string length is equal to zero (or if the expression doesn't evaluate to anything). The same effect can be accomplished with the more generic <composer:if> tag described below, but the XPath expression involved is more complex (and definitely less readable). Let's take our example a little further (note that this example replaces lines 9-15 in the previous example):

 9:  <td>

10:    <composer:value xpath="./CUSTOMER/NAME" /><br>

11:    <composer:hasvalue xpath="./CUSTOMER/ADDRESS">

12:      <composer:value xpath="./CUSTOMER/ADDRESS" /><br>

13:    </composer:hasvalue>

14:    <composer:value xpath="./CUSTOMER/CITY" />,

15:    <composer:value xpath="./CUSTOMER/STATE" />

16:    <composer:value xpath="./CUSTOMER/ZIP" />

17:  </td>

Lines 11-13 make a slight change to the processing of the address node. If for some reason the address node is not present or has no value (as is the case with the second order in our XML sample), the printing of the node value and the <br> tag will be skipped. This prevents the empty line that would normally be printed for the second order in our example XML without the <composer:hasvalue> condition.

the tag

There will be cases where we need to conditionally evaluate using criteria more complex than what has been presented thus far. The <composer:if> tag provides the ability to specify an XPath expression that evaluates to a Boolean value.  If that value is true, the body will be processed; if the value is false, it is skipped. Let's demonstrate with our final example (this replaces lines 15-17 in the previous example):

15:         <composer:if xpath="string(./CUSTOMER/STATE)=&quot;CA&quot;">

16:           <b>

17:         </composer:if>

18:         <composer:value xpath="./CUSTOMER/STATE" />

19:         <composer:if xpath="string(./CUSTOMER/STATE)=&quot;CA&quot;">

20:           </b>

21:         </composer:if>

22:         <composer:value xpath="./CUSTOMER/ZIP" />

23:       </td>

The business requirements of our fictitious bookstore dictate that the order summary page must print the state name in a bold font if it's equal to "CA". We accomplish this with two <composer:if> tags that correspond to the opening and closing bold tags. The XPath expression of both tags takes the string value of the expression ./CUSTOMER/STATE and checks if it's equal to the string "CA". Note that we use the &quot; XML escape sequence since putting the single apostrophe directly within the xpath attribute will generate a parser error. The end result is if the state is CA, it will be printed with enclosing bold tags.

The <composer:if> node will accept any XPath expression. For the tag to make sense of the expression, the XPath needs to evaluate to a Boolean value. If it doesn't, the node (and its body) is ignored.

deployment

We've presented a quick overview of the Composer JSP tag library tags. Now let's take a look at deployment. For purposes of this example, we'll be deploying our JSP page within a J2EE-compliant WAR file. The structure of the file will look something like this:

As you can see, the JSP file is in the root of the WAR. Within the WEB-INF/lib directory we have the JAR containing the Composer web service we've created. Within the WEB-INF directory there are two files. The first, composer-taglib.tld is the Tag Library Definition file. This must be included for the JSP engine to make sense of the custom tags we're using (this file should have been installed during eXtend Composer installation). There also needs to be an entry made in the web.xml file to map the URI we're using to the corresponding TLD file. Remember the <%@ taglib %> tag at the beginning of the JSP file? That URI comes from the web.xml entry that we create. Here's what the file looks like:

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN" "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">

<web-app>

       <servlet>

              <servlet-name>orderlist</servlet-name>

              <jsp-file>orderlist.jsp</jsp-file>

       </servlet>

       <servlet-mapping>

              <servlet-name>orderlist</servlet-name>

              <url-pattern>/orderlist.jsp</url-pattern>

       </servlet-mapping>

       <servlet-mapping>

              <servlet-name>servicejsp</servlet-name>

              <url-pattern>/servicejsp</url-pattern>

       </servlet-mapping>

       <taglib>

              <taglib-uri>/composer</taglib-uri>

              <taglib-location>/WEB-INF/composer-taglib.tld</taglib-location>

       </taglib>

</web-app>

 

Along with the typical servlet definitions for the JSP file itself and its mapping, there is a <taglib> entry. This defines a URI and an associated tag library location. The location points to the TLD file that we're including in the WAR. The URI specified needs to be the same one that is used in the <%@ taglib %> tag in the JSP. That should be all that's needed for this simple WAR example.

conclusion

This has been a brief introduction to the possibilities that the Composer JSP tag library creates for creating HTML pages that utilize eXtend Composer web services. As with XSL transformations, it is a powerful mechanism to present the service's XML output in a user-readable way.