Appendix C. Tag Library

CONTENTS

IN THIS APPENDIX

  •  Tag Library Overview
  •  What Is a Tag Library?
  •  The Six Steps to Building Tag Libraries
  •  Tag Library Concepts
  •  Building a Tag Library
  •  General Notes
  •  Summary

Tag libraries are a central feature of JSP. Concisely stated, tag libraries permit the JSP programmer to build reusable code that has a simple interface and is easy to package across many JSP projects. More than any other feature of JSP, tag libraries make JSP stand out from any other Web application solution. This appendix will give you a quick overview of what a tag library is and will walk you through the details of how to build them. However, only a brief taste of tag libraries can be given in an appendix of this size. After you get started here, we recommend that you review the JSP specification (http://java.sun.com/products/jsp/download.html), which has a complete and in-depth explanation of how tag libraries work.

In case you are wondering why there is a tag library reference in a JSP XML book, the answer is simple. Tag libraries give us a way to place code in our JSP pages using an XML-compliant interface. We made use of this feature in Chapter 15, "Advanced Application Design."

Tag Library Overview

Tag libraries exist for one reason: to enable the separation of business and presentation logic within a JSP page. All business logic should be placed in JavaBeans, and all presentation logic should be placed in tag libraries.

By using a tag library, the programmer can offer a simple XML-based interface through which anybody may access the tag library.

One way to maintain the separation of the business logic and presentation logic is by using tag libraries to access JavaBeans. Once a tag library is packaged in a JSP project, the XML tags are easy enough to use that non-programmers can use them to access more complicated programming logic.

What Is a Tag Library?

A tag library is a set of custom actions that can be invoked on a JSP page using a custom tag. A custom action is a reusable module of code used to perform repeating tasks.

Prior to the widespread use of tag libraries, JavaBean components were used in conjunction with scriptlets for performing what is now tag library processing. The disadvantage, which was stressed previously, is that the lack of separation of business logic and presentation logic made JSP pages difficult to maintain due to their complexity.

According to the JSP 1.2 specification, "A tag library abstracts functionality used by a JSP page by defining a specialized sub language that enables the more natural use of that functionality within JSP pages."[1]

[1] JavaServer Pages specification, p. 105. You can download this document from http://java.sun.com/products/jsp/download.html.

Each tag library is a collection of custom actions. All custom actions compose that "specialized sub language" described in the preceding quotation. Each custom action uses an XML tag to invoke the processing code of the custom action and is composed of two parts:

  • Tag handler This Java class performs the processing required to implement the custom action.

  • Tag library descriptor (TLD) This descriptor primarily defines the XML interface to be used within the JSP pages and matches that XML interface to a tag handler.

In order to use these custom actions or tag libraries in a JSP page, you must declare the tag library directive. This is similar to the Java import statements.

Advantages

Advantages of tag libraries include the following:

  1. Tag libraries facilitate faster development. They offer an easy way to modularize and reuse JSP code. All projects can use existing tag libraries, and thus existing code, directly in JSP pages. The XML interface is easy to use, and speeds up the process of building a JSP page by using "plug-and-play" programming.

  2. Tag libraries make it easy to move code across projects. They are very portable between JSP applications. A tag library can be packaged as a JAR file and dropped into a project for use. The ability to reuse code from project to project is a major bonus to any JSP developer.

  3. Tag libraries permit the expansion of JSP. It's possible to replicate any action of the JSP specification through a tag library. This means that it's possible to expand JSP to do almost anything a project needs. If a better JSP include action is required, you can program your own.

  4. Tag libraries help reduce maintenance. In a well-written JSP application, all logic resides in the centralized tag handler and JavaBeans. To update code, only the central files of the tag library need to be altered.

  5. Expanding functionality is simple. The layering of logic makes it easy to add features to an existing tag library and have no impact on any of the existing pages using the tag. You can add attributes that introduce new behaviors to a tag while retaining old attributes and behaviors.

    For example, say you have a tag that colors all text blue:

    <BlueText> My Text </BlueText >

    Later in the project, you need to choose the shade of blue. Keeping the basic tag as is, we add an attribute called shade:

    <BlueText shade="teal"> My Text </BlueText>

    All of the old tags will still work as expected, but now we can use the new functionality to choose the shade.

Disadvantages

Tag libraries only have a single disadvantage worth mentioning: They create extra layers of processing. To completely separate presentation logic and business logic through the use of tags, extra layers are added to the process.

The Six Steps to Building Tag Libraries

The actual building of a tag library is a six-step process:

  1. Place your business logic into a Java class file. Typically, this means using JavaBeans.

  2. Create a tag handler. This Java class file contains the code that implements each tag's functionality.

  3. Create a TLD (tag library descriptor) file. This file describes the tag library for the JSP system.

  4. Create a distribution file. Tag libraries are portable and generally a programmer will package a tag library for distribution. This is optional.

  5. Register the tag library. This step tells the JSP container where to find the TLD file. This can be as easy as dropping a JAR file into the JSP application.

  6. Place the tag library on a JSP page.

Let's go through each of these steps, explaining them in greater detail.

Tag Library Concepts

The toughest part of building a tag library is understanding that it's a multiple-step process. Once you understand the overall process, it's easy to concentrate on each of the individual parts needed to build a tag library.

Isolating the Business Logic

To take advantage of the object-oriented nature of Java, reusable code should be placed outside the tag library in independent class containers. These classes are not part of the tag library. Rather, they are the code implemented by the tag library to perform part of the assigned task.

That is not to say that there isn't code within a tag library that executes. There is. It's called a tag handler, and it's a Java class file. But it's specifically written in such a way that only a JSP container can execute this class. For this reason, it is inaccessible to outside applications such as servlets, applets, and client-side Java applications.

Tag libraries are JSP specific. This means that any code within a tag library cannot be accessed by other Java applications. Moving the business logic out of the tag and into a JavaBean facilitates reuse of the code by other applications.

The Tag Handler

This is the core of a tag library. This class contains some of the logic needed to perform the tasks required when the tag library is used. This class will reference any outside material it needs, such as JavaBeans, and has access to all the information from your JSP page (through the pageContext object). It is this class (tag handler), which is only available through JSP pages, that will bring everything together to perform the tag library's assigned task.

One reason tag libraries are so powerful is that they have access to all the information needed to directly access the JSP page. The tag handler is the object within the tag library that gets access to the JSP page. This means that the tag handler has access to all the implicit objects tied to the JSP page. Any attributes declared within the tag on the JSP page are automatically passed down to the tag handler. Finally, the tag handler has direct access to any text data stored within the element that calls the tag handler.

Another powerful feature of the tag handler is the event framework that ties it back to the JSP page. This means that the tag handler and the JSP page communicate with each other during the processing of the tag element on the JSP page.

Because a tag handler is tied so strongly into JSP, any tag handler class must implement the javax.servlet.jsp.tagext.Tag interface. JSP takes the Tag interface and extends it to provide extra methods in the IterationTag and BodyTag interfaces. These three interfaces define the methods within a tag handler that a JSP page will call. In practice, most tag handlers are extended from two helper classes that JSP pages provide: the TagSupport class and the BodyTagSupport class.

Figure C.1 shows the event framework of a tag handler.

Figure C.1. The anatomy of a tag handler.

graphics/cfig01.gif

Here are the logical steps of a full-scale tag handler, based on the BodyTag interface:

  1. The JSP container maintains a pool of existing tag handlers to reuse. If a tag handler doesn't exist yet, the JSP container instatiates a new tag handler object.

  2. Any attribute defined in the tag on the JSP page is set. The tag handler is initialized with the JSP page's pageContext object.

  3. The doStartTag() method is invoked when the start of the tag is encountered within the JSP page.

  4. The JSP page creates the initial buffer to hold the BodyContent object. Note that the body of the tag is not evaluated in this step.

  5. The doInitBody() method provides an opportunity to process the BodyContent buffer before the first evaluation of the tag body is placed into the buffer.

  6. The JSP container evaluates the body of the tag and then places the data into the BodyContent object. If the tag doesn't implement the BodyTag interface, the BodyContent object is unavailable.

  7. The doAfterBody() method is called after the JSP page evaluates the body of the tag element. This method permits the programmer to instruct the JSP container to reevaluate the body of the element. This allows tag libraries to perform looping logic. If doAfterBody() returns EVAL_BODY_AGAIN, the body will be reevaluated. If doAfterBody() returns SKIP_BODY, the body is skipped and doEndTag() will next be called by the system.

  8. The method doEndTag() is invoked when the closing tag on the page is encountered.

A couple of additional notes are important at this juncture:

  • Most programmers will only place code within the doStartTag(), doAfterBody(), and doEndTag() methods. (Some programmers only put code in the doStartTag() method.)

  • Typically, the doStartTag() method is used for initialization purposes or when dealing with empty tags. The doAfterBody() method is useful for building iterating tags. The doEndTag() method is where you should place clean-up code or final processes.

The example presented in Figure C.1 shows the processing steps of a fully functional tag handler based on the BodyTag interface or inherited from the BodyTagSupport class. Simpler tags built on the TagSupport class will have neither the setBodyContent() method nor the doInitBody() method.

It should be noted that the label "tag library" is misleading as it refers to a collection of tag handlers. A custom tag is a single tag handler, while a tag library is a collection of custom tags. However, the term "tag library" has come to mean either a custom tag or a collection of custom tags.

The Tag Library Descriptor (TLD)

A TLD is an XML file that describes a tag library. The data found in this file defines the following:

  • The name of the tag library

  • Each custom action within that tag library, including its attributes

  • Which custom action matches each tag handler

  • Documentation

It is through this information that the JSP container uses the TLD file to interpret how to handle each custom action declared on a JSP page.

A TLD file must end with a .tld extension. Usually the TLD file is stored within the WEB-INF directory of the JSP Web application.

In a strange sense, the TLD is what creates the "library" part of the tag library because it's here that the index pulls together separate tag handlers, resulting in a library. Later, when this appendix builds a TLD, the index nature of the TLD will become clearer. The TLD file is where all the custom tags are first referenced under a tag library collection name. This is the only place where the actual tag library is defined.

The DTD used to validate and define the TLD file can be found in the JSP specifications (http://java.sun.com/products/jsp/download.html).

Creating a Distribution File

Distribution files are not a requirement in building a tag library. However, it is easy to create such files, and it's recommended that you do so if the tag library is going to be packaged for any other Web applications to use.

The steps for creating a distribution files are as follows:

  1. Create a JAR file. This is a zip file with a .jar extension.

  2. Add the class files necessary for the tag library into the newly created JAR file.

  3. Create and add a META-INF directory into the JAR file.

  4. Within the META-INF directory, place the TLD file that describes this tag library.

Once the tag library is packaged, it is ready to be distributed into other Web applications. To distribute the packaged tag library, place the JAR file into the destination site's WEB-INF/lib directory. Tomcat requires a stop and restart in order to register the JAR file.

Registering the Tag Library

Once the tag library has been developed, the next step is to register it with the JSP container. This is automatically done when using a distribution JAR file, whose creation was described earlier. The registration instructions that follow will describe registering a tag library by hand, then through the use of a JAR distribution file.

The usual method of registering a tag library is to modify a JSP site's web.xml file found in the WEB-INF directory. Add a <taglib> element such as

<taglib>   <taglib-uri>Your Unique Tag ID</taglib-uri>   <taglib-location>The relative location of the TLD file</taglib-location> </taglib>

At a minimum, a URI needs to be declared within a <taglib-uri> statement. The URI is a unique identifier that the JSP container will use to match with a tag library through its TLD file. Typically, the URI is a short unique identifier that makes sense for a tag. Sometimes programmers use URLs there, because they are unique.

The other piece of information is the physical location of the tag library TLD file. This information is stored in the <taglib-location> element, and is a relative path from the web.xml file.

After modifying the web.xml file, it's a good idea to restart your JSP container. This permits the JSP container to reinitialize itself with the new information.

The other common method of registering a tag library is through the use of a distribution JAR file. This file is placed in the destination Web site's WEB-INF/lib directory. Once it's installed, restart the JSP container and let the container automatically register the tag library.

While two other methods of registering a tag library exist, the methods mentioned here are the ones used throughout this book.

Using the Tag Library Declaration on a JSP Page

This is as simple as using a taglib directive to declare the existence of the tags. After the tag library has been declared on a JSP page, it can be used freely within that page. The taglib directive looks like the following:

<%@ taglib uri="registered URI" prefix="mytag" %>

The URI attribute is used to match with the registered URI name of the tag library. The prefix attribute is used to give a convenient tag handle to use within the page. For the previous taglib statement, any tag starting with the namespace mytag will call the "registered URI" tag library.

For instance, the following line of code calls the "hello" tag handler registered in the tag library referenced by the URI associated with the mytag prefix.

<mytag:hello>

In essence we are creating a variable that can be used throughout the JSP page in which it's declared. When this variable is declared, it's associated with a URI through which a tag library is referenced.

Building a Tag Library

Now, let's work through an example, building a tag library for database access. The tag library will take the results from a SQL statement and apply an XSL stylesheet to create formatted output.

Isolating the Business Logic

Chapter 7, "Successfully Using JSP and XML in an Application," produced several JavaBeans used to take a JDBC ResultSet and produce an XML output. The JavaBeans used are DatabaseParameter.java, XMLFromResult.java, and ProcessDom4J.java. This section will use these JavaBeans to illustrate how convenient it is to reuse code. Answers to any questions you might have regarding how to use or install these beans can be found in Chapter 7.

Building a Tag Handler

We need to build a new tag handler to access the previously created business logic components. Save the file shown in Listing C.1 as webapps/xmlbook/WEB-INF/classes/xmlbook/tagappendix/DatabaseResultTag.java.

Listing C.1 A Tag Handler to Access and Return Results from a Database
package xmlbook.tagappendix; import javax.servlet.jsp.tagext.*; import javax.servlet.jsp.*; import xmlbook.chapter7.*; import org.dom4j.Document; public class DatabaseResultTag extends TagSupport {     private DatabaseParameter database = null;         public void setDatabase(DatabaseParameter data)  { database = data; }         public DatabaseParameter getDatabase()        { return(database ); }     private String SQL  = null;         public void setSQL(String as_sql)             { SQL = as_sql; }         public String getSQL()                        { return(SQL); }     private String rootName = "Root";         public void setRootName(String as_data)       { rootName = as_data; }         public String getRootName()                   { return(rootName); }     private String rowName = "Row";         public void setRowName(String as_data)        { rowName = as_data; }         public String getRowName()                    { return(rowName); }     private String xsl = "";         public void setXsl(String as_data)            { xsl = as_data; }         public String getXsl()                        { return(xsl); }     private boolean clearBuffer = false;         public void setClearBuffer(boolean ab_data)   { clearBuffer = ab_data; }         public boolean getClearBuffer()               { return(clearBuffer); }     public int doStartTag() throws JspException     {         XMLFromResult result= new XMLFromResult(getRootName(),getRowName());         JspWriter out = pageContext.getOut();         try         {  if (getClearBuffer()) out.clearBuffer();            String ls_sql = getSQL();            Document xmldata = result.createXML (getDatabase(), ls_sql);            ProcessDom4J dealwithxml = new ProcessDom4J();            if (xsl.length() == 0 || xsl == null)            {dealwithxml.produceXML(out,xmldata);            }            else            {String  ls_xsl  = pageContext.getServletContext().getRealPath(xsl) ;             dealwithxml.applyXSL (out,xmldata,ls_xsl);            }         }         catch (Exception e)         {   try             {out.print (" <p align=\"center\">" + e.toString() + "</p>");}             catch (Exception tag_error)             {throw new JspException(tag_error.toString());}         }         return SKIP_BODY;     } }

If upon compiling this file you run into errors about org.xml.j4dom being irresolvable, you need to install dom4j. To do so, download the dom4j files and place the dom4j.jar file into the lib directory found at the root of your Tomcat installation. (More specific instructions can be found in Chapter 7.)

Let's review the code in the tag handler. The first thing we see is the name DatabaseResultTag. It's a common practice to append the word Tag to the end of any tag handler class.

This particular tag doesn't need to handle data placed between the opening and closing tags that compose the custom action. The logic can get all the information it needs from the attributes of the custom action element.

The next block of code to review will be the properties. For example:

private DatabaseParameter database = null;         public void setDatabase(DatabaseParameter data)   { database = data; }         public DatabaseParameter getDatabase()            { return(database ); }

Properties are managed automatically by the JSP container. The JSP container manages these properties using the JavaBeans introspection tools to determine and set all properties. This means that all properties exposed for the tag handler must have getter and setter methods using the JavaBean standards. It should be noted that your own code should not use the setter methods, since it is the JSP container's job to maintain these properties. The properties can be of any type, including objects.

If a property is of a type other than String, two other steps will have to occur after the tag handler class is built. First, within the TLD file, any attribute that differs from type String needs an element of <type> in the web.xml file to fully define the expected type of that attribute. Second, when a property will be an object as this first example is of type DatabaseParameter the object needs to be passed in with a JSP expression statement (<%= %>). We will illustrate this as we move on in the example.

Remember, in this example we're not worried about the body text of the tag element. This leaves us with a choice to place the code within either the doStartTag() method or the doEndTag() method. In this case there isn't much difference.

If the doEndTag() is chosen, it is possible to halt execution of the JSP page, if necessary. We won't get into that here, but needed to mention that it's possible. However, it's generally bad practice to have the tag halt the processing of a page and is rarely done. Halting a JSP page should generally occur at the JSP page level, where all processes on the page can be stopped cleanly by the governing JSP page. If a tag halts a JSP page, it could cause conflicts with other processes occurring within the parent JSP, which the tag knows nothing about. As a component, a tag library shouldn't know about other processes and should only concentrate on its own process.

In this case, the doStartTag() is chosen because we can tell the tag handler to skip any body processing:

return SKIP_BODY;

In theory, this cuts down on unneeded processing within the tag handler. In a tag where processing of the body occurs, this choice becomes more critical relative to the timing of what's happening in your logic.

The next idea we will cover is the use of the pageContext object:

JspWriter out = pageContext.getOut();

The pageContext object can be used to give the tag handler access to all the implicit objects that the calling JSP page has access to at the time of the tag call. In the preceding line of code, we are getting a handle to the out implicit object.

Next, the tag handler checks to see whether the user wants the buffer cleared before sending out the XML output:

if (getClearBuffer()) out.clearBuffer();

Many times when dealing with XML output, whitespace from the JSP page will be introduced before the XML output. Since this tag is built to send XML/XSLT output, it makes sense to clear the output buffer of this whitespace.

The tag handler then takes the attributes sent in from the JSP page and calls the three classes discussed in Chapter 7 to create and output a processed XML document from a database SQL call. The only item of real interest is some work in the catch block:

catch (Exception e) {   try     {out.print (" <p align=\"center\">" + e.toString() + "</p>");}     catch (Exception tag_error)     {throw new JspException(tag_error.toString());} }

The code has a try-catch block around the print statement. The out.print logic needs to catch the IO exception if it occurs. On the JSP page the servlet would do this for us. Also notice that the code repackages any exception as a JspException to send problems back to the JSP page. We repackage it as a JspException because the doStartTag already throws the JspException class. It's easier just to pass the JspException back up the exception food chain.

Overall, the logic here isn't much more difficult to deal with than that of a JavaBean. We have a little more work in the sense that the properties need to be created and the pageContext object queried for data. However, the code here is the intersection between the JSP page and other JavaBeans. As such, the slight amount of extra work is worth the increased functionality that the tag handler permits.

The Tag Library Descriptor

Now that we've created a tag handler, it is time to build a TLD file to define the tag handler for the tag library. The file in Listing C.2 should be saved as webapps/xmlbook/WEB-INF/xmldatabase.tld.

Listing C.2 A TLD File to Define the XMLDatabase Tag Library
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"                         "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> <taglib>     <tlib-version>1.0</tlib-version>     <jsp-version>1.2</jsp-version>     <short-name>xmldatabase</short-name>     <uri>xmlbook.xmldatabase</uri>     <tag>         <name>xmlresult</name>         <tag-class>xmlbook.tagappendix.DatabaseResultTag</tag-class>         <body-content>empty</body-content>         <description>Database xml functionality</description>         <attribute>             <name>database</name>             <required>true</required>             <rtexprvalue>true</rtexprvalue>             <type>xmlbook.chapter7.DatabaseParameter</type>             <description>Pass in a Database property object </description>          </attribute>         <attribute>             <name>SQL</name>             <required>true</required>             <rtexprvalue>true</rtexprvalue>             <description>Pass in a Database SQL Statement </description>         </attribute>         <attribute>             <name>rootName</name>             <required>false</required>             <rtexprvalue>true</rtexprvalue>             <description>Define the root element name </description>         </attribute>         <attribute>             <name>rowName</name>             <required>false</required>             <rtexprvalue>true</rtexprvalue>             <description>Define element name for each row </description>         </attribute>         <attribute>             <name>xsl</name>             <required>false</required>             <rtexprvalue>true</rtexprvalue>             <description>The XSL style sheet to use </description>         </attribute>            <attribute>             <name>clearBuffer</name>             <required>false</required>             <rtexprvalue>false</rtexprvalue>             <type>boolean</type>             <description>True to clear buffer before output</description>         </attribute>     </tag> </taglib>

The first step is to create the actual tag library:

<taglib>     <tlib-version>1.0</tlib-version>     <jsp-version>1.2</jsp-version>     <short-name>xmldatabase</short-name>     <uri>xmlbook.xmldatabase</uri>

The tag library is assigned a unique URI and then we add each tag handler the system needs in this tag library:

<tag>         <name>xmlresult</name>         <tag-class>xmlbook.tagappendix.DatabaseResultTag</tag-class>         <body-content>empty</body-content>         <description>Database xml functionality</description>

The name element contains the name of the custom action. For a tag handler to work, we must define what class is driving the logic in the tag-class element. In this case, we also state that the element body must be empty. This helps the container run the tag more efficiently.

Next, the file defines the attributes that the tag handler needs:

<attribute>     <name>database</name>     <required>true</required>     <rtexprvalue>true</rtexprvalue>     <type>xmlbook.chapter7.DatabaseParameter</type>     <description>Pass in a Database property object </description> </attribute>

The name of the attribute is logically placed in a name element. The required tag indicates whether the attribute is required when used on the JSP page. In this case we must make sure that a JSP expression (<%= %>) is permitted to send the data into the attribute through the use of the rtexprvalue tag. Correctly defining this specification is very important as we are passing a non-String object through this attribute. The only way to pass in a Java object is to use a JSP expression.

By default, JSP will send attribute data as a String. However, at times it will be more useful to pass in an object. To do so, the attribute value must indicate the object it expects. For our example the attribute type is defined as follows:

<type>xmlbook.chapter7.DatabaseParameter</type>

We define the attribute as requiring a DatabaseParameter object. Once this attribute is defined, the tag handler will continue by listing the other attributes using the same XML structure.

Registering the Tag Library

Registering the tag library only requires a quick modification to the webapps/xmlbook/WEB-INF/web.xml file. Between the web.xml's root element <web-app> tags add the following:

<taglib>   <taglib-uri>xmlbook.xmldatabase</taglib-uri>   <taglib-location>/WEB-INF/xmldatabase.tld</taglib-location> </taglib>

The taglib elements are placed after the final servlet-mapping tag within the web.xml file.

Stop and restart Tomcat and use the tag library we just built.

Using the Tag Library on a JSP Page

Listing C.3 shows a sample page using the tag library. Save this file as webapps/xmlbook/tagappendix/TestTag.jsp.

Listing C.3 Creating a JSP Page to Use a Tag Library
<%@page contentType="text/html"         import="xmlbook.chapter7.*,                 org.dom4j.Document"%> <%@taglib uri="xmlbook.xmldatabase" prefix="xmldata" %> <jsp:useBean class="xmlbook.chapter7.DatabaseParameter"              id   ="DBconn"    scope="page" >         <jsp:setProperty name="DBconn" property="databaseName"                          value="xmlbook"/>         <jsp:setProperty name="DBconn" property="driver"                          value="org.gjt.mm.mysql.Driver"/>         <jsp:setProperty name="DBconn" property="url"                          value="jdbc:mysql://localhost/xmlbook"/> </jsp:useBean> <xmldata:xmlresult  database    ="<%= DBconn %>"  SQL ="select name as NAME,link as LINK,linktext as LINKTEXT from BannerAds"  rootName    ="BANNERS"  rowName     ="BANNERAD"  xsl         ="chapter4/BannerAds.xsl"  clearBuffer ="true"/>

This page requires that the MySQL database server be successfully installed and that the xmlbook database, with table BannerAds, be created.

The resulting data page, shown in Figure C.2, is similar to the one produced in Listing 4.2 in Chapter 4, "A Quick Start to JSP and XML Together," with the exception that here it has been created from a database query rather than from an XML file.

Figure C.2. Results of the tag library call.

graphics/cfig02.gif

This output is basically the same as the earlier example, except that this one uses a tag that we created.

Let's look at the first line of the JSP page found in Listing C.4:

<%@taglib uri="xmlbook.xmldatabase" prefix="xmldata" %>

This line indicates that we have created a special namespace or tag prefix of xmldata to represent the tag library. In addition, the mapping xmlbook.xmldatabase is the URI the JSP container will use to find the tag library being used in this example.

To make our database connectivity object XML compliant, we created it as a JavaBean:

<jsp:useBean class="xmlbook.chapter7.DatabaseParameter"              id   ="DBconn"    scope="page" >         <jsp:setProperty name="DBconn" property="databaseName"                          value="xmlbook"/>         <jsp:setProperty name="DBconn" property="driver"                          value="org.gjt.mm.mysql.Driver"/>         <jsp:setProperty name="DBconn" property="url"                          value="jdbc:mysql://localhost/xmlbook"/> </jsp:useBean>

Referencing the object created by this useBean tag is a simple matter of using the ID "Dbconn." Many projects would store a database connectivity object within the application data space. It would then be simple to recall it and pass it directly to the tag.

The final step is to use the tag library itself:

<xmldata:xmlresult  database    ="<%= DBconn %>"  SQL ="select name as NAME,link as LINK,linktext as LINKTEXT from BannerAds"  rootName    ="BANNERS"  rowName     ="BANNERAD"  xsl         ="chapter4/BannerAds.xsl"  clearBuffer ="true"/>

Notice that a JSP expression (="<%= DBconn %>") was used to deliver the actual object to the tag handler. Also note that XML is case sensitive, so we had to make sure the SQL statement produced columns that matched the names of the XML elements (otherwise the XSL stylesheet wouldn't produce any results). Likewise, we had to tell the process the name of the row element and what names to expect for the root element. Again, we must match the XML file layout for our stylesheet to work.

General Notes

Before concluding this appendix, let's cover a few additional topics in greater detail.

Body Data

In order to access the body of the tag we need to implement the BodyTag interface. When the body is available, the JSP container will build the BodyContent object. This object will be created after the JSP container evaluates the body of the tag. This object will be passed to the tag handler when the doInitBody() method is invoked. Once created, BodyContent is available elsewhere in the tag handler until the doEndBody() method is finished processing.

The contents of BodyContent are the results after the JSP page has finished the evaluation. This means that the object will not contain any code or actions, just the results of the final invocation.

There is no limit to the amount of data a BodyContent object can contain other than the physical memory limitations of your server. Some care should be taken not to overload the object, since there is no way to automatically flush the buffer of the BodyContent.

Getting a handle of the BodyContent object requires a simple call to the getBodyContent() method.

In the typical tag library the BodyContent object and the data within it are converted to a String to be processed by the tag handler. The data is used either to perform an operation or as the base of some new output to be placed into the JSP output stream.

Design Notes

Tag libraries are flexible. A general rule is to avoid making a single tag handler do too much. It's a good idea to break logic into smaller reusable packages. As an example, we could have written several tags to perform the work of our single tag. It might be practical to take an approach similar to the DBTags database tags we examined in Chapter 1, "Integrating JSP and Data." The code is reproduced here:

<%@ taglib uri="http://jakarta.apache.org/taglibs/dbtags" prefix="sql" %> <sql:connection id="connect">   <sql:url>jdbc:mysql://localhost/xmlbook</sql:url>   <sql:driver>org.gjt.mm.mysql.Driver</sql:driver> </sql:connection>

Creating several custom tags could make our sample XML document tag library more flexible. In fact, it's also possible to make DBTags work alongside these tags. Because DBTags are an open source project, we could review their tag handlers' code and then merge the two to work together.

Empty Tags

Any tag library that is empty (such as <action />) will not invoke any methods that relate to tag body manipulation. This speeds up execution of the tags. As result, if a tag will always be empty, it's a good idea to build the tag from the TagSupport class. Also, indicate the fact that the tag will always be empty within the tag's description in the tag library descriptor file. The element would be set as follows:

<body-content>empty</body-content>

Threading

A tag handler instance will only permit one thread to execute at a time. The JSP container enforces this rule, and a programmer does not have to worry about thread safety of a tag handler. However, while a tag handler is thread safe, an instance of a tag handler can be reused many times. JSP containers will maintain a pool of tag handlers to speed execution of a tag library. The result is that while a tag library is thread safe, it is possible for threads to step on each other in dealing with shared data or objects at higher scopes. For example, we stated earlier that programmers shouldn't use the setter methods of any tag library property within the tag handler. The reason boils down to the fact that it's the JSP container's responsibility to do so. If the JSP container determines that a particular property is static across implementations, it may not reset the property after the initial setting of a pooled tag handler. This means that if one thread does modify the property, it may not be set to the proper value for the next thread. Note that this example depends on the way a JSP container is implemented and can vary from implementation to implementation.

Summary

This appendix has exposed you to the basics of tag libraries. If you choose to devote further study to tag libraries, you will discover how truly useful they are. As an example, it's possible to tie listener events within the TLD file for a tag library. Other features of tag libraries include the doCatch and doFinally methods, which permit a programmer to catch uncaught exceptions from the tag handler. Yet another feature is the TagLibraryValidation class that validates the use of tags on a JSP page. This appendix just scratches the surface of what is possible using a tag library. Throughout the book, you have encountered a few more advanced uses of tag libraries. As a JSP programmer, it's worth your time to learn how to use tag libraries to fill various everyday programming needs.

CONTENTS


JSP and XML[c] Integrating XML and Web Services in Your JSP Application
JSP and XML[c] Integrating XML and Web Services in Your JSP Application
ISBN: 672323540
EAN: N/A
Year: 2005
Pages: 26

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net