Skip Headers
Oracle® Application Server Containers for J2EE Support for JavaServer Pages Developer's Guide
10g Release 2 (10.1.2)
B14014-02
  Go To Documentation Library
Home
Go To Product List
Solution Area
Go To Table Of Contents
Contents
Go To Index
Index

Previous
Previous
Next
Next
 

8 JSP Tag Libraries

This chapter discusses custom tag libraries, covering the basic framework that vendors can use to provide their own libraries. There is also discussion of Oracle extensions and a comparison of standard runtime tags versus vendor-specific compile-time tags. The chapter consists of the following sections:

The chapter offers a detailed overview of standard tag library functionality. For complete information, refer to the Sun Microsystems JavaServer Pages Specification. For information about the tag libraries provided with OC4J, see the Oracle Application Server Containers for J2EE JSP Tag Libraries and Utilities Reference.

Custom tag syntax largely follows XML conventions. For general information about XML, you can find the specification at the following Web site:

http://www.w3.org/XML/

Overview of the Tag Library Framework

JavaServer Pages technology allows vendors to create custom JSP tag libraries. A tag library defines a collection of custom actions. The tags can be used directly by developers in manually coding a JSP page, or automatically by Java development tools.

This section provides an overview of the JSP tag library framework as well as a summary of tag library features introduced in the JSP 1.2 specification.

For information beyond what is provided here regarding tag libraries and the standard JavaServer Pages tag library framework, refer to the following resources:

http://java.sun.com/j2ee/sdk_1.3/techdocs/api/javax/servlet/jsp/tagext/package-summary.html

Overview of a Custom Tag Library Implementation

A custom tag library is made accessible to a JSP page through a taglib directive of the following general form:

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

Note the following points about implementation and usage of a tag library:

  • The tags of a library are defined in a tag library descriptor (TLD) file, as "Tag Library Descriptor Files" describes.

  • The URI in the taglib directive is a pointer to the TLD file, as "Overview: Specifying a Tag Library with the taglib Directive" discusses. It is possible to use URI shortcuts, as "Use of web.xml for Tag Libraries" explains.

  • The prefix in the taglib directive is a string of your choosing that you use in your JSP page with any tag from the library.

    Assume that the taglib directive specifies a prefix oracust:

    <%@ taglib uri="URI" prefix="oracust" %>
    
    

    Further assume that there is a tag, mytag, in the library. You might use mytag as follows:

    <oracust:mytag attr1="...", attr2="..." />
    
    

    Using the oracust prefix informs the JSP translator that mytag is defined in the TLD file that can be found through the URI specified in the above taglib directive.

  • The entry for a tag in the TLD file provides specifications about use of the tag, including whether the tag uses attributes (as mytag does), and the names of those attributes.

  • The semantics of a tag—the actions that occur as the result of using the tag—are defined in a tag handler class, as "Tag Handlers" describes. Each tag has its own tag handler class, and the class name is specified in the TLD file.

  • A tag attribute can be of any standard Java type or an object type—either the generic java.lang.Object or a user-defined type.

    You typically set an attribute of a standard Java type as a string value. The appropriate conversion is handled automatically.

    You can also set an attribute of type Object with a string value. The string is converted to an Object instance and passed in to the corresponding setter method in the tag handler instance. This feature complies with the JSP specification.

    An attribute of a user-defined type must be set using a request-time expression that returns an instance of the type.

  • The TLD file indicates whether a tag uses a body.

    A tag without a body is used as in the following example:

    <oracust:mytag attr1="...", attr2="..." />
    
    

    By contrast, a tag with a body is used as in the following example:

    <oracust:mytag attr1="...", attr2="..." >
       ...body...
    </oracust:mytag>
    
    
  • A custom tag action can create one or more server-side objects that are available for use by the tag itself or by other JSP scripting elements, such as scriptlets. These objects are known as scripting variables.

    You can declare a scripting variable through a <variable> element in the TLD file or through a tag-extra-info class. See "Scripting Variables, Declarations, and Tag-Extra-Info Classes" for more information.

    A tag can create and use scripting variables with syntax such as in the following example, which creates the object myobj:

    <oracust:mytag id="myobj" attr1="...", attr2="..." />
    
    
  • The TLD file can optionally declare a tag-library-validator class for use with the tag library. This class would have logic to validate any JSP page that uses the tag library, according to specified constraints. See "Validation and Tag-Library-Validator Classes".

  • The TLD file can optionally declare one or more event listeners for use with the tag library. This functionality is offered as a convenient alternative to declaring listeners in the application web.xml file. See "Tag Library Event Listeners".

  • The tag handler of a nested tag can access the tag handler of an outer tag, in case this is required for any of the processing or state management of the nested tag. See "Access to Outer Tag Handler Instances".

The remainder of this chapter provides details about these topics.

Overview of Tag Library Changes Between the JSP 1.1 and 1.2 Specifications

The JSP 1.2 specification introduced features for improved tag library support in the following areas:


Important:

In Oracle Application Server 10g Release 2 (10.1.2), the OC4J JSP container by default expects JSP 1.1, not JSP 1.2, tag syntax and usage. To use JSP 1.2 features described in the following sections, specify the JSP 1.2 TLD DTD, as shown in "Overview of TLD File Validation and Features".

Summary of TLD File Changes Between the JSP 1.1 and 1.2 Specifications

The following list is a summary of features in TLD syntax and functionality that were introduced in the JSP 1.2 specification. These changes were not available prior to Oracle9iAS Release 2 (9.0.3). "Tag Library Descriptor Files" includes information about these features.

  • The <validator> element and its subelements, allowing you to declare a tag-library-validator class for the tag library

  • The <listener> element and its subelement, allowing you to declare event listeners for the tag library

  • The <variable> subelement, and its own subelements, under the <tag> element, allowing you to declare scripting variables directly through the TLD

  • The <type> subelement under the <attribute> subelement of the <tag> element, for noting the datatype of the attribute

  • The <display-name>, <large-icon>, and <small-icon> elements, and also subelements of the same name under the <tag> element, for use by authoring tools

  • Renamed elements since the JSP 1.1 specification, as follows:

    • The <info> element, and the subelement of the same name under the <tag> element, were renamed to <description>.

    • The <tlibversion> element was changed to <tlib-version>.

    • The <jspversion> element was changed to <jsp-version>.

    • The <shortname> element was changed to <short-name>.

    • The <tagclass>, <teiclass>, and <bodycontent> subelements under the <tag> element were changed to <tag-class>, <tei-class>, and <body-content>.


      Notes:

      • The OC4J JSP container enables XML validation of TLD files separately from validation of the web.xml file. Validation of TLD files is enabled by default; validation of web.xml is disabled by default. (See "JSP Configuration Parameter Descriptions" for information about the no_tld_xml_validate and xml_validate parameters.) In Oracle9iAS Release 2 (9.0.2) and prior, TLD files and web.xml were all validated through the xml_validate parameter, which was disabled by default.

      • OC4J provides a sample XSL template that you can use with a standard XSLT program, such as oraxsl, to convert a JSP 1.1-compliant TLD file into one that is JSP 1.2-compliant. This template is located in the misc directory in the OC4J demos directory structure. You can find the demos through the following location:

        http://www.oracle.com/technology/tech/java/oc4j/demos/
        

Summary of Tag Handler Changes Between the JSP 1.1 and 1.2 Specifications

The JSP 1.1 specification documented two interfaces to be implemented by tag handlers: Tag for tags without bodies, and BodyTag for tags with bodies. The JSP 1.2 specification introduced the IterationTag interface, for tags that call for iteration through a tag body, but do not require access to the tag body content through a body content object. IterationTag extends Tag and is extended by BodyTag.

Also as of the JSP 1.2 specification, the int constant EVAL_BODY_TAG, which indicates that there is a tag body to be processed, is deprecated and replaced by EVAL_BODY_AGAIN and EVAL_BODY_BUFFERED. EVAL_BODY_AGAIN is used with tags that iterate through a tag body, to specify that iteration should continue. EVAL_BODY_BUFFERED is used with tags that require access to body content, to direct that a BodyContent object be created.

The JSP 1.2 specification also introduced the TryCatchFinally interface, which any tag handler can implement for improved data integrity and resource management when exceptions occur.

The JSP 1.2 changes were not available prior to Oracle9iAS Release 2 (9.0.3). "Tag Handlers" includes information about these new features.

Tag Library Descriptor Files

A tag library descriptor (TLD) file is an XML-style document that defines a tag library and its individual tags. The name of a TLD file has the .tld extension.

A JSP container uses the TLD file in determining what action to take when it encounters a tag from the library. The taglib directive in a JSP page informs the JSP container where to find the TLD file. (See "Overview: Specifying a Tag Library with the taglib Directive".)

The following sections provide an overview and general information about TLD file syntax and usage, referring ahead to other sections as appropriate for more information about related topics:

For complete information, refer to the Sun Microsystems JavaServer Pages Specification.

See "Example: Using the IterationTag Interface and a Tag-Extra-Info Class" for a sample TLD file.


Note:

By default, the OC4J JSP container performs XML validation of TLD files. To disable this, set the no_tld_xml_validate JSP configuration parameter to true. See "JSP Configuration Parameter Descriptions" for more information. For pretranslation, use the ojspc -noTldXmlValidate option, described in "Option Descriptions for ojspc".

Overview of TLD File Validation and Features

The OC4J JSP container uses the DOCTYPE declaration of a TLD file to determine which TLD DTD version to validate against, unless TLD validation has been disabled. By default in Oracle Application Server 10g Release 2 (10.1.2), the JSP container assumes the JSP 1.1 TLD DTD. To use the JSP 1.2 TLD DTD, list the following as the system ID (DTD location):

http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd

Here is an example:

<!DOCTYPE taglib
        PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"
        "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">

When TLD validation is enabled, the XML parser must be able to reference the appropriate DTD, which it can do with the above DOCTYPE declaration for JSP 1.2. TLD validation is enabled if the JSP no_tld_xml_validate parameter has its default false setting, or, for pretranslation, if the ojspc -noTldXmlValidation flag is not used.


Note:

According to the JSP specification, use an absolute URL to specify the system ID. If a TLD file does not use a public external DOCTYPE declaration with an absolute URL, the default in Oracle Application Server 10g Release 2 (10.1.2) is to assume that the JSP 1.1 TLD DTD is intended.

A TLD file provides definitions for the tag library as a whole as well as for each individual tag. For each tag, it defines the tag name, its attributes (if any), its scripting variables (if any), and the name of the class that handles tag semantics. See "Use of the tag Element".

For the library as a whole, TLD definitions can include a tag-library-validator class and event listeners. See "Other Key Elements and Their Subelements: validator and listener".

A TLD file also provides additional definitions for the library as a whole, as follows.


Note:

The <tag>, <validator>, and <listener> elements and the elements listed below are top-level subelements under the <taglib> root element of the TLD file.

  • The required <tlib-version> element specifies the version number of the tag library (whatever version number you want to give it).

  • The required <jsp-version> element specifies the JSP version upon which this tag library depends (such as 1.2).

  • The <uri> element can specify a string value that uniquely identifies this tag library. In particular, this is useful in situations where multiple tag libraries and their TLD files are packaged in a single JAR file. See "Packaging and Accessing Multiple Tag Libraries in a JAR File".

  • The required <short-name> element specifies a convenient default name for the library, for possible use by authoring tools. You could also use the short name as a preferred tag prefix for the library, for use in the taglib directive.

  • There are also additional elements that you can use, typically for authoring tools: the <display-name> element for a display name of the tag library, and the <large-icon> and <small-icon> elements for the file names (.jpg or .gif) of a large icon, a small icon, or both. Icon file locations are relative to the TLD file.

  • The <description> element can provide a description of the tag library.


    Note:

    Several descriptive elements were added to the JSP 1.2 TLD DTD. In addition to the <description> element directly under the root <taglib> element, there are <description> subelements under the <tag>, <variable>, and <attribute> elements. There is also an <example> subelement under the <tag> element. These subelements can provide information for developers who wish to use the tag library. In particular, a TLD can be processed, such as through an XSLT style sheet, to provide developer documentation from the material in the descriptive elements. This information can be displayed in the help windows of tools such as Oracle JDeveloper, for example.

Use of the tag Element

Each tag of a tag library is specified in a <tag> element under the root <taglib> element of the TLD file. There must be at least one <tag> element in a TLD file. This section describes its usage and subelements.

Subelements of the tag Element

The subelements of a <tag> element define a tag, as follows:

  • The required <name> subelement specifies the name of the tag.

  • The required <tag-class> subelement specifies the name of the corresponding tag handler class. See "Tag Handlers" for information about tag handler classes.

  • The <body-content> subelement indicates how the tag body (if any) should be processed. See the example and accompanying discussion in "Sample tag Element and Use of Its body-content Subelement".

  • Each <variable> subelement (if any), with its further subelements, defines a scripting variable. See "Scripting Variables, Declarations, and Tag-Extra-Info Classes" for information about scripting variables. The <variable> element is for relatively uncomplicated situations, where the logic for the scripting variable does not require a tag-extra-info class. The variable name is specified through either the <name-given> subelement, to specify the name directly, or the <name-from-attribute> subelement, to specify the name of a tag attribute that specifies the variable name. There is also a <variable-class> subelement to specify the class of the variable, a <scope> subelement to specify the scope of the variable, and a <declare> subelement to specify whether the variable is to be newly defined. See "Variable Declaration Through TLD variable Elements" for more information. Another subelement under <variable> is an optional <description> element.

  • Each <tei-class> subelement (if any) specifies the name of a tag-extra-info class that defines a scripting variable. This is for situations where declaring the variable through a <variable> element is not sufficient. See "Variable Declaration Through Tag-Extra-Info Classes" for more information.

  • Each <attribute> subelement (if any), with its further subelements, provides information about an attribute of the tag—a parameter that you can specify when you use the custom tag. Subelements of <attribute> include the <name> element to specify the attribute name, the <type> element to optionally note the Java type of the attribute value, the <required> element to specify whether the attribute is required (default false), and the <rtexprvalue> element to specify whether the attribute can accept runtime expressions as values (default false). See the example and accompanying discussion below. Another subelement under <attribute> is an optional <description> element.


Notes:

As of Oracle Application Server 10g Release 2 (10.1.2), the OC4J JSP container ignores the <type> element. It is for informational use only, for anyone examining the TLD file. Additionally, note the following:
  • For literal attribute values, where <rtexprvalue> specifies false, the <type> value (if any) should always be java.lang.String.

  • When <rtexprvalue> specifies true, then the type of the tag handler property corresponding to this tag attribute determines what you should specify for the <type> value (if any).


  • As with the tag library as a whole, each tag can have its own <display-name>, <large-icon>, and <small-icon> subelements for use by authoring tools.

  • The <description> subelement can provide a description of the tag.

  • The <example> subelement can provide an example of how to use the tag.


Notes:

  • A custom tag name must qualify as an NMTOKEN according to the XML specification. For example, it cannot start with a numeric character.

  • Attribute names must follow naming conventions for XML attributes, and their setter methods in tag handler classes must follow the JavaBeans specification.


Sample tag Element and Use of Its body-content Subelement

Here is a sample TLD file entry for a tag myaction:

<tag>
  <name>myaction</name>
  <tag-class>examples.MyactionTag</tag-class>
  <tei-class>examples.MyactionTagExtraInfo</tei-class>
  <body-content>JSP</body-content>
  <attribute>
    <name>attr1</name>
    <required>true</required>
  </attribute>
  <attribute>
    <name>attr2</name>
    <required>false</required>
    <rtexprvalue>true</rtexprvalue>
  </attribute>
</tag>

According to this entry, the tag handler class is MyactionTag and the tag-extra-info class is MyactionTagExtraInfo. The attribute attr1 is required; the attribute attr2 is optional and can take a runtime expression as its value.

The <body-content> element indicates how the tag body (if any) should be processed. There are three choices:

  • A value of empty indicates that the tag uses no body. In this case, the OC4J JSP translator will return an exception if there is a tag body.

  • A value of JSP (the default) indicates that the tag body should be processed as JSP source code and translated.

  • A value of tagdependent indicates that the tag body should not be translated. Any text in the body is treated as template data.

Consider the following example:

<foo:bar>
   <%=blah%>
</foo:bar>

If the bar tag has a <body-content> value of JSP, then the body is processed by the JSP translator, and the expression is evaluated. With a <body-content> value of tagdependent, the JSP translator does not process the body. In this case, the characters "<", "%", "=", and ">" have no special meaning—they are treated as literal characters, along with the rest of the body, and are part of the JSP out object passed straight through to the tag handler.

There are additional considerations for JSP XML documents. In this case, because the document is parsed by the XML parser, it is not appropriate to implement support for a value of tagdependent. This value is essentially meaningless in a JSP XML document.

One reason for this is that in XML, there is already a convenient mechanism for escaping body content—using the CDATA token. But beyond that, there are many scenarios where it would actually be undesirable to pass content straight through as a tagdependent implementation would do. Consider an example using a tag for SQL queries, with traditional syntax:

<foosql:query ... >
   select ... where salary > 1000
</foosql:query>

Compare this to the following JSP XML syntax:

<foosql:query ... >
   <![CDATA[select ... where salary > 1000]]>
</foosql:query>

In the traditional syntax, a <body-content> value of tagdependent would result in the query statement being passed straight through to the JSP out object, presumably the desired result.

In the XML syntax, the CDATA token (or, alternatively, a "&gt;" escape character) is required, because otherwise the character ">" has special meaning to the XML parser.

In this example, if an implementation of tagdependent were used, the entire body would be passed through to the out object:

<![CDATA[select ... where salary > 1000]]>

But presumably, the information that should really be passed through is only the SQL query itself:

select ... where salary > 1000

This is what would happen by processing the body through a <body-content> value of JSP, and using the CDATA token for the XML parser. This is more appropriate behavior than what would happen with a tagdependent implementation.

See "Details of JSP XML Documents" for more information about JSP XML syntax.

Other Key Elements and Their Subelements: validator and listener

The TLD <validator> and <listener> elements were introduced in the JSP 1.2 specification.

A <validator> element and its subelements specify information about a tag-library-validator (TLV) class that can validate JSP pages that use this tag library. The <validator> element has three subelements: <validator-class>, <description>, and <init-param>. The <init-param> subelement has the same functionality as <init-param> subelements within <servlet> elements in the web.xml file. It has <param-name> and <param-value> subelements to specify each parameter. See "Validation and Tag-Library-Validator Classes" for more information.

A <listener> element and its <listener-class> subelement specify an event listener for use with the tag library, such as in creating and destroying resource pools used by the library. See "Tag Library Event Listeners" for more information.

Tag Library and TLD Setup and Access

The following sections discuss the packaging, placement, and access of tag libraries and their TLD files:


Notes:

  • It is highly recommended to place TLD files under the application /WEB-INF directory. In future releases this will be enforced.

  • If you use tag library JAR files at the application level that are intended to supersede JAR files in the well-known tag library location (global level), then you must specify that the application class loader search local classes first. In the application orion-web.xml file, in the <web-app-class-loader> element, set the search-local-classes-first attribute to a value of "true".

  • In OC4J standalone, if you add a tag library JAR file to the /WEB-INF/lib directory while OC4J is running, you must use a tags_reuse_default flag value of "none" or "compiletime" to avoid a ClassCastException. You must also force retranslation of relevant JSP pages (such as by touching the .jsp files or removing the corresponding .class files).


Overview: Specifying a Tag Library with the taglib Directive

This section summarizes the use of taglib directives, comparing functionality under the JSP 1.1 specification to functionality under the JSP 1.2 and later specifications.

Import a custom library into a JSP page by using a taglib directive of the following general form:

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

The prefix setting specifies a string of characters that stipulates when tags from this library are being used. For example, if mytag is in a library that has a specified prefix of oracust, use mytag as follows:

<oracust:mytag attr1="..." attr2="..." >
...
</oracust:mytag>


Note:

Prefixes must follow the naming conventions of the XML namespaces specification.

The JSP 1.1 specification stated that the uri setting can indicate a file location as in either of the following scenarios, either directly or through a "shortcut" URI:

  • It can indicate the physical location, within a WAR file structure, of the TLD file that defines the desired tag library.

  • It can indicate the physical location of the JAR file that contains the components and TLD file of the desired tag library. Under the JSP 1.1 specification, there can be only one tag library and only one TLD file in the JAR file.

See "Specifying a Tag Library by Physical Location" for more information.

Beginning with the JSP 1.2 specification, the uri setting can still indicate the physical location of a TLD file or the location of a JAR file containing one tag library and its TLD file, but it can also be used as follows:

  • It can specify one of multiple tag libraries packaged in a single JAR file, by specifying a value that matches the <uri> element value in one of the TLD files in the JAR file. In this case, the uri setting is intended to be a unique key, not a pointer to a physical location.

As under JSP 1.1, you can also use a shortcut URI.

See "Packaging and Accessing Multiple Tag Libraries in a JAR File" for more information. For information about shortcut URIs, see "Use of web.xml for Tag Libraries".

Specifying a Tag Library by Physical Location

As first defined in the JSP 1.1 specification, the taglib directive of a JSP page can fully specify the name and physical location, within a WAR file structure, of the TLD file that defines a particular tag library, as in the following example:

<%@ taglib uri="/WEB-INF/oracustomtags/tlds/mytld.tld" prefix="oracust" %>

Specify the location as application-relative by starting with "/" as in this example. See "Requesting a JSP Page" for discussion of application-relative syntax.

Be aware that the TLD file should be in the /WEB-INF directory or a subdirectory.

Alternatively, as also defined since the JSP 1.1 specification, the taglib directive can specify the name and application-relative physical location of a JAR file instead of a TLD file, where the JAR file contains a single tag library and the TLD file that defines it. In this scenario, the JSP 1.1 specification mandated that the TLD file must be located and named as follows in the JAR file:

META-INF/taglib.tld

The JSP 1.1 specification also mandated that the JAR file must be located in the /WEB-INF/lib directory.

Here is an example of a taglib directive that specifies a tag library JAR file:

<%@ taglib uri="/WEB-INF/lib/mytaglib.jar" prefix="oracust" %>

Also see "Packaging and Accessing Multiple Tag Libraries in a JAR File", following, which describes a scenario introduced in the JSP 1.2 specification.


Note:

In either scenario discussed in this section, the taglib directive can specify a "shortcut" URI that corresponds to the complete URI value according to settings in the web.xml file. See "Use of web.xml for Tag Libraries".

Packaging and Accessing Multiple Tag Libraries in a JAR File

The preceding section, "Specifying a Tag Library by Physical Location", discusses the JSP 1.1 scenarios of using a taglib directive to specify a TLD file by physical location, or to specify a JAR file that contains a single tag library and its TLD file.

Adding to these scenarios, the JSP 1.2 specification introduced the packaging of multiple tag libraries, and the TLD files that define them, in a single JAR file. Inside the JAR file, these TLD files must be located under the /META-INF directory or a subdirectory.

A single TLD file in a JAR file can be packaged as /META-INF/taglib.tld, or you can use another name as desired. (In JSP 1.1, the taglib.tld naming convention was a requirement.)

In a JAR file with multiple TLD files, the TLD files must be uniquely named or be in different subdirectories under META-INF.

Here are a couple of possibilities, for example, for packaging three TLD files in a JAR file:

META-INF/abctags.tld
META-INF/deftags.tld
META-INF/ghitags.tld

or:

META-INF/abc/taglib.tld
META-INF/def/taglib.tld
META-INF/ghi/taglib.tld

In each TLD file, there is a <uri> element under the root <taglib> element. Use this feature as follows:

  • The <uri> element must specify a value that is to be matched by the uri setting of a taglib directive in any JSP page that wants to use the corresponding tag library.

  • To avoid unintended results, each <uri> value should be unique across all <uri> values in all TLD files on the server.

The value of the <uri> element can be arbitrary. It is simply used as a key and does not indicate a physical location. By convention, however, its value is of the form of a physical location, such as in the following example:

<uri>http://www.mycompany.com/j2ee/jsp/tld/myproduct/mytags.tld</uri>

A <uri> value must follow the XML namespace convention.

A JAR file with multiple TLD files must be placed in the /WEB-INF/lib directory or in an OC4J "well-known" tag library location as described in "Oracle Extensions for Tag Library Sharing and Persistent TLD Caching". During translation, the JSP container searches these two locations for JAR files, searches each JAR file for TLD files, and accesses each TLD file to find its <uri> element.


Notes:

  • A <uri> element and the corresponding taglib directive can specify a "shortcut" URI setting. This corresponds to settings in the web.xml file, as "Use of web.xml for Tag Libraries" explains.

  • A JSP 1.2-compliant container, such as the OC4J JSP container, supports the multiple TLD file packaging mechanism for JSP 1.1 TLD files as well as JSP 1.2 TLD files.


Example: URI Settings for Multiple Tag Libraries in a JAR File

Consider a JAR file, myapptags.jar, that includes the following TLD files:

META-INF/mytaglib1.tld
META-INF/mytaglib2.tld

Assume that mytaglib1.tld specifies the following:

<taglib> 
   <tlib-version>1.0</tlib-version> 
   <jsp-version>1.2</jsp-version> 
   <short-name>shorty</short-name>
   <uri>http://www.foo.com/jsp/mytaglib1</uri>
   <description>example TLD</description>
   <tag>
      <name>mytag1</name>
      ...
   </tag>
   ...
</taglib>

To use mytag1 or any other tag defined in mytaglib1.tld, a JSP page could have the following taglib directive:

<%@ taglib uri="http://www.foo.com/jsp/mytaglib1" prefix="myprefix1" %>

URI values in this scenario (multiple tag libraries in a single JAR file) are used as keywords only. They can be arbitrary.

For a more complete example, see "Example: Multiple Tag Libraries and TLD Files in a JAR File".

Use of web.xml for Tag Libraries

The Sun Microsystems Java Servlet Specification describes a standard deployment descriptor for servlets: the web.xml file. JSP pages can use this file in specifying the location or URI identifier of a JSP TLD file.

For JSP tag libraries, the web.xml file can include <taglib> elements and two subelements:

  • <taglib-uri>

  • <taglib-location>

For the scenario of an individual TLD file, or the scenario of a JAR file that contains a single tag library and its TLD file, the <taglib-location> subelement indicates the application-relative physical location (by starting with "/") of the TLD file or tag library JAR file. See "Specifying a Tag Library by Physical Location" for related information.

For the scenario of a JAR file that contains multiple tag libraries and their TLD files, a <taglib-location> subelement indicates the unique identifier of a tag library. In this case, the <taglib-location> value actually indicates a key, not a location, and corresponds to the <uri> value in the TLD file of the desired tag library. See "Packaging and Accessing Multiple Tag Libraries in a JAR File" for related information.

The <taglib-uri> subelement indicates a shortcut URI to use in taglib directives in your JSP pages, with this URI being mapped to the physical location or URI identifier specified in the accompanying <taglib-location> subelement.

Following is a sample web.xml entry for a TLD file:

<taglib>
   <taglib-uri>/oracustomtags</taglib-uri>
   <taglib-location>/WEB-INF/oracustomtags/tlds/mytld.tld</taglib-location>
</taglib>

This entry makes /oracustomtags equivalent to /WEB-INF/oracustomtags/tlds/mytld.tld in taglib directives in your JSP pages.

Given this example, the following directive in your JSP page results in the JSP container finding the /oracustomtags URI in web.xml and, therefore, finding the accompanying name and location of the TLD file (mytld.tld):

<%@ taglib uri="/oracustomtags" prefix="oracust" %>

This statement enables you to use any of the tags of this custom tag library in a JSP page.

See the Sun Microsystems Java Servlet Specification and the Sun Microsystems JavaServer Pages Specification for more information about the web.xml deployment descriptor.


Important:

Generally speaking, the <taglib> element in web.xml is required in the case of a TLD file that is located in a JSP "well-known" tag library location and has <listener> elements. This is the only way that the TLD file can be found and accessed in order to activate its listeners. This is not the case, however, if you use persistent TLD caching. See "Oracle Extensions for Tag Library Sharing and Persistent TLD Caching" and "Tag Library Event Listeners".

Oracle Extensions for Tag Library Sharing and Persistent TLD Caching

As an extension of standard JSP "well-known URI" functionality described in the JSP specification, the OC4J JSP container supports the use of one or more directories, known as well-known tag library locations, where you can place tag library JAR files to be shared across multiple Web applications.

There is also a persistent caching feature for TLD files, with a global cache for TLD files in any well-known tag library locations, as well as an application-level cache for any application that uses TLD caching.

The use of TLD caching speeds performance at application startup and during JSP page translation. You might typically turn it off, however, under either of the following circumstances:

  • Your application does not use tag libraries.

or:

  • You have pretranslated the JSP pages and none of the TLD files use <listener> elements for tag library event listeners. (See "Tag Library Event Listeners".)

The following sections provide additional information:

TLD Caching and Well-Known Tag Library Locations

TLD caching is enabled or disabled through the jsp-cache-tlds attribute of the <orion-web-app> element, at a global level through this attribute in the global-web-application.xml file, or at an application level through this attribute in the application orion-web.xml file.

By default, TLD caching is enabled at a global level through the default setting jsp-cache-tlds="true" in global-web-application.xml. This is also the default setting in the orion-web.xml file of each application, but you can disable TLD caching for any particular application with a setting of jsp-cache-tlds="false" in orion-web.xml. This overrides the global setting.

Alternatively, you can disable TLD caching at a global level with a "false" setting in global-web-application.xml, then optionally enable TLD caching for any particular application with a "true" setting in orion-web.xml.

A setting of "standard" searches for TLD files only in /WEB-INF or subdirectories other than /WEB-INF/classes or /WEB-INF/lib. The "true" setting, by contrast, searches all application files for TLD files.


Note:

By default, orion-web.xml inherits its jsp-cache-tlds setting from global-web-application.xml.

If TLD caching is enabled, you can specify one or more well-known tag library locations using a semicolon-delimited list of directory paths in the jsp-taglib-locations attribute of the <orion-web-app> element in global-web-application.xml. See "OC4J Configuration Parameters for JSP" for additional information about this attribute.


Important:

Use the jsp-taglib-locations attribute only in global-web-application.xml, not in orion-web.xml.

If TLD caching is disabled, the well-known tag library location is limited to a single directory, using functionality that existed prior to the availability of TLD caching. In this case, the well-known location is determined by the well_known_taglib_loc JSP configuration parameter. See "JSP Configuration Parameters" for additional information about this parameter.

In an Oracle Application Server environment, the default well-known location is ORACLE_HOME/j2ee/home/jsp/lib/taglib (assuming ORACLE_HOME is defined).


Important:

  • For any application to pick up files in the well-known location or locations, the directory or directories that are specified in jsp-taglib-locations or the directory that is specified in well_known_taglib_loc must be added to the path attribute setting of the <library> element in the OC4J global application.xml file in the configuration files directory (j2ee/home/config by default in OC4J standalone). See the Oracle Application Server Containers for J2EE User's Guide for information about application.xml.

  • If a TLD file is present both in the well-known location and under the /WEB-INF directory of an application, the /WEB-INF copy takes precedence and is used.

  • If TLD files with the same URI value are present in or under the /WEB-INF directory and also in a JAR file in the /WEB-INF/lib directory, the decision of which one to use is indeterminate. Avoid this situation.


TLD Cache Features and Files

For any application that uses TLD caching, whether it is enabled at the global level or at the application level, there are two levels of caching, and two aspects of caching at each level.

Caching levels:

  • There is a global cache for TLD files that are in JAR files in any well-known tag library locations.

  • There is an application-level cache for TLD files under the application /WEB-INF directory.

    At the application level, tag library JAR files, which include TLD files, must be in the /WEB-INF/lib directory. Individual TLD files can be directly in /WEB-INF or in any subdirectory, but preferably not in /WEB-INF/lib or /WEB-INF/classes.

Caching aspects at each level:

  • There is a file containing resource information for the relevant location—the well-known location for the global cache, or /WEB-INF or /WEB-INF/lib for the application-level cache. Because of this feature, JAR files do not have to be scanned more than once. The file contains two types of entries:

    • There is a list of all resources (tag library JAR files) that includes a timestamp for each resource so that any change to any resource can be detected. There is also an indication ("true" or "false") of whether each resource includes a TLD file.

    • There is a list of TLD files, where each entry consists of a TLD name, TLD URI value if present, and tag library listeners if present. (See "Tag Library Event Listeners".)

  • There is a serialized DOM representation of each TLD file. Because of this feature, TLD files do not have to be parsed more than once.

The global cache is always located in a directory called tldcache, parallel to the configuration directory. The tldcache directory contains the following:

  • There is a file, _GlobalTldCache, that contains resource information, as described above, for any well-known locations.

  • There are DOM representations of the TLD files that are in well-known locations. For each TLD file that is in a JAR file in a well-known location, the DOM representation is in a subdirectory according to the name of the JAR file, with a file name according to the name of the TLD file. For example, if email.tld is found in ojsputil.jar in a well-known location, then its DOM representation would be in the following file (file name email in directory ojsputil_jar):

    ORACLE_HOME/j2ee/home/jsp/lib/taglib/persistence/ojsputil_jar/email
    
    

    This is for an Oracle Application Server environment, where ORACLE_HOME is defined. In OC4J standalone, the j2ee directory is relative to where OC4J is installed.

The application-level cache is in the directory indicated by the jsp-cache-directory setting in either global-web-application.xml or orion-web.xml. (See "OC4J Configuration Parameters for JSP" for information about jsp-cache-directory.) This directory contains the following:

  • There is a file, _TldCache, that contains resource information, as described above, for TLD files under the /WEB-INF directory—either in JAR files in /WEB-INF/lib, or individually in /WEB-INF or any subdirectory, but preferably not /WEB-INF/lib or /WEB-INF/classes.

  • There are DOM representations of the TLD files under /WEB-INF. For TLD files that are in JAR files in the /WEB-INF/lib directory, the DOM representations go into subdirectories under the directory indicated by jsp-cache-directory, in the same type of scheme as described for the global cache. For individual TLD files under /WEB-INF, the DOM representations go directly in the jsp-cache-directory location.


    Notes:

    • TLD changes at the global level are reflected only after OC4J is restarted.

    • TLD changes at the application level are reflected immediately in an OC4J standalone environment, but only after the application is restarted in an Oracle Application Server environment.

    • You can increase the OC4J verbosity level to see information regarding construction of TLD caches and regarding any TLD URIs that are duplicated. Level 4 provides some information; level 5 provides additional information. You can use Oracle Enterprise Manager 10g to set the verbosity level. The default level is 3.


Example: Multiple Tag Libraries and TLD Files in a JAR File

This section presents an example of tag library packaging. This is a situation where multiple tag libraries are packaged in a single JAR file. The JAR file includes tag handler classes, tag-library-validator classes, and TLD files for multiple libraries. The following shows the contents and structure of the JAR file:

examples/BasicTagParent.class
examples/ExampleLoopTag.class
examples/BasicTagChild.class
examples/BasicTagTLV.class
examples/TagElemFilter.class
examples/XMLViewTagTLV.class
examples/TagFilter.class
examples/XMLViewTag.class
META-INF/xmlview.tld
META-INF/exampletag.tld
META-INF/basic.tld
META-INF/MANIFEST.MF

Key TLD File Entries for Multiple-Library Example

This section illustrates the <uri> elements of the TLD files.

The basic.tld file includes the following:

<taglib>

  <tlib-version>1.0</tlib-version>
  <jsp-version>1.2</jsp-version>
  <short-name>basic</short-name>
  <uri>http://xmlns.oracle.com/j2ee/jsp/tld/demos/basic.tld</uri>

  ...

</taglib>

The exampletag.tld file includes the following:

<taglib xmlns="http://java.sun.com/JSP/TagLibraryDescriptor">

  <tlib-version>1.0</tlib-version>
  <jsp-version>1.2</jsp-version>
  <short-name>example</short-name>
  <uri>http://xmlns.oracle.com/j2ee/jsp/tld/demos/exampletag.tld</uri>

  ...

</taglib>

The xmlview.tld file includes the following:

<taglib>

  <tlib-version>1.0</tlib-version>
  <jsp-version>1.2</jsp-version>
  <short-name>demo</short-name>
  <uri>http://xmlns.oracle.com/j2ee/jsp/tld/demos/xmlview.tld</uri>

  ...

</taglib>

Key web.xml File Entries for Multiple-Library Example

This section shows the <taglib> elements of the web.xml deployment descriptor. These map the full URI values, as seen in the <uri> elements of the TLD files in the previous section, to shortcut URI values used in the JSP pages that access these libraries.

...
<taglib>
  <taglib-uri>/oraloop</taglib-uri> 
  <taglib-location>http://xmlns.oracle.com/j2ee/jsp/tld/demos/exampletag.tld
  </taglib-location> 
</taglib>
<taglib>
  <taglib-uri>/orabasic</taglib-uri> 
  <taglib-location>http://xmlns.oracle.com/j2ee/jsp/tld/demos/basic.tld
  </taglib-location> 
</taglib>
<taglib>
  <taglib-uri>/oraxmlview</taglib-uri> 
  <taglib-location>http://xmlns.oracle.com/j2ee/jsp/tld/demos/xmlview.tld
  </taglib-location> 
</taglib>
...

JSP Page taglib Directives for Multiple-Library Example

This section shows the appropriate taglib directives, which reference the shortcut URI values defined in the web.xml elements listed in the preceding section.

The page basic1.jsp includes the following directive:

<%@ taglib prefix="basic" uri="/orabasic" %>

The page exampletag.jsp includes the following directive:

<%@ taglib prefix="example" uri="/oraloop" %>

The page xmlview.jsp includes the following directive:

<%@ taglib prefix="demo" uri="/oraxmlview" %>

Tag Handlers

The following sections describe tag handlers, which define the semantics of actions that result from the use of custom tags:

Overview of Tag Handlers

A tag handler is an instance of a Java class that directly or indirectly implements the standard javax.servlet.jsp.tagext.Tag interface. Depending on whether there is a tag body and how that body is to be processed, the tag handler implements one of the following interfaces, in the javax.servlet.jsp.tagext package:

  • Tag: This interface defines the basic methods for all tag processing, but does not include tag body processing.

  • IterationTag: This interface extends Tag and is for iterating through a tag body.

  • BodyTag: This interface extends IterationTag and is for accessing the tag body content itself.

A tag handler class might implement one of these interfaces directly, or might extend a class (such as one of the support classes provided by Sun Microsystems) that implements one of them.

Each custom tag has its own handler class. By convention, the name of the tag handler class for a tag abc, for example, is AbcTag.

The TLD file of a tag library specifies the name of the tag handler class for each tag in the library. See "Tag Library Descriptor Files".

A tag handler instance is typically created by the JSP page implementation instance, by use of a zero-argument constructor, and is a server-side object used at request-time. The tag handler has properties that are set by the JSP container, including the page context object for the JSP page that uses the custom tag, and a parent tag handler object if the use of this tag is nested within an outer tag. A tag handler, as applicable, supports parameter-passing, evaluation of the tag body, and access to other objects in the JSP page, including other tag handlers.

"Example: Using the IterationTag Interface and a Tag-Extra-Info Class" includes code for a sample tag handler class.


Note:

The JSP specification does not mandate whether multiple uses of the same custom tag within a JSP page should use the same tag handler instance or different instances. This is left to the discretion of JSP vendors. See "OC4J JSP Tag Handler Features" for information about the Oracle implementation.

Attribute Handling, Conversions from String Values

A tag handler class has an underlying property for each attribute of the custom tag. These properties are somewhat like JavaBean properties, with at least a setter method.

Recall that there are two approaches in setting a tag attribute:

  • The first approach is where the attribute is a non-request-time attribute, set using a string literal value:

    nrtattr="string"
    
    

    For a non-request-time attribute, if the underlying tag handler property is not of type String, the JSP container will try to convert the string value to a value of the appropriate type.

    Because tag attributes correspond to bean-like properties, their processing, such as for these type conversions from string values, is similar to that of bean properties. See "Bean Property Conversions from String Values".

  • The second approach is where the attribute is a request-time attribute that is set using a request-time expression:

    rtattr="<%=expression%>"
    
    

    For request-time attributes, there is no conversion. A request-time expression can be assigned to the attribute, and to its corresponding tag handler property, for any property type. This would apply to a tag attribute whose type is user-defined, for example.

Custom Tag Processing, with or without Tag Bodies

A custom tag, as with a standard JSP tag, might or might not have a body. In the case of a custom tag, even when there is a body, its content might not have to be accessed by the tag handler.

There are four scenarios:

  1. There is no body.

    In this case you need only a single tag, not a start-tag and end-tag. Following is a general example:

    <oracust:mytag attr1="...", attr2="..." />
    
    

    This is equivalent to the following, which is also permissible:

    <oracust:mytag attr1="...", attr2="..." ></oracust:abcdef>
    
    

    In this case, the tag handler should implement the Tag interface.

    The <body-content> setting for this tag in the TLD file should be empty.

  2. There is a body; access of the body content by the tag handler is not required; the body is executed no more than once.

    In this case, there is a start-tag and an end-tag with a body of statements in between, but the tag handler does not process the body. Body statements are passed through for normal JSP processing only. Following is a general example of this scenario:

    <foo:if cond="<%= ... %>" >
    ...body executed if cond is true, but body content not accessed by tag handler...
    </foo:if>
    
    

    In this case, the tag handler should implement the Tag interface.

    The <body-content> setting for this tag in the TLD file should be JSP (the default) or tagdependent, depending on whether the body content should be translated or treated as template data, respectively.

  3. There is a body; access of the body content by the tag handler is not required; the body is executed multiple times (iterated).

    This is the same as the second scenario, except there is iterative processing of the tag body.

    <foo:myiteratetag ... >
    ...body executed multiple times, according to attribute or other settings,
    but body content not accessed by tag handler...
    </foo:myiteratetag>
    
    

    In this case, the tag handler should implement the IterationTag interface.

    The <body-content> setting for this tag in the TLD file should be JSP (the default) or tagdependent, depending on whether the body content should be translated or treated as template data, respectively.

  4. There is a body that must be processed by the tag handler.

    Again, there is a start-tag and an end-tag with a body of statements in between; however, the tag handler must access the body content.

    <oracust:mybodytag attr1="...", attr2="..." >
    ...body accessed and processed by tag handler...
    </oracust:mybodytag>
    
    

    In this case, the tag handler should implement the BodyTag interface.

    The <body-content> setting for this tag in the TLD file should be JSP (the default) or tagdependent, depending on whether the body content should be translated or treated as template data, respectively.


    Notes:

    • In the first scenario, where there is no body, the action is known as an empty action. In the second, third, and fourth scenarios, where there is a body, the action is known as a non-empty action.

    • In the first, second, and third scenarios, where no body content processing is required by the tag handler, the handler is known as a simple tag handler.

    • For additional information about the <body-content> element, see "Use of the tag Element".


Summary of Integer Constants for Body Processing

The tag handler interfaces that are described in the following sections specify methods that you must implement, as applicable, to return appropriate int constants, depending on the situation.

The possible return values from the doStartTag() method, which is defined in the Tag interface and inherited by the IterationTag and BodyTag interfaces, are as follows:

  • SKIP_BODY: Use this value if there is no body or if evaluation of the body should be skipped.

  • EVAL_BODY_INCLUDE: Use this value to evaluate the body and pass it through to the current JSP out object. There is no special processing of the body content; no body content object is created.

  • EVAL_BODY_BUFFERED (for BodyTag classes only): Use this value to create a BodyContent object for the content of the tag body, used for evaluation and processing of the content.

  • EVAL_BODY_TAG: This is deprecated (formerly used if there is a body that requires special processing by the tag handler). Use EVAL_BODY_AGAIN or EVAL_BODY_BUFFERED, which both have the same int value as EVAL_BODY_TAG.

The possible return values from the doAfterBody() method, defined in the IterationTag interface and inherited by the BodyTag interface, are as follows:

  • SKIP_BODY: Use this value to skip evaluation of the body or, when iterating through the body, to stop iterating.

  • EVAL_BODY_AGAIN: Use this value to continue iterating through the body.

The possible return values from the doEndTag() method, defined in the Tag interface and inherited by the IterationTag and BodyTag interfaces, are as follows:

  • SKIP_PAGE: Use this value to skip the rest of the page after the tag. This completes the request.

  • EVAL_PAGE: Use this value to evaluate the remainder of the page after the tag.

Simple Tag Handlers without Iteration

For a custom tag that does not have a body, or has a body whose content does not require access and special processing by the tag handler, the tag handler is referred to as a simple tag handler. The tag handler class can implement the following standard interface:

  • javax.servlet.jsp.tagext.Tag

However, if there is a tag body that is to be iterated, then the tag handler should implement the IterationTag interface instead. See "Simple Tag Handlers with Iteration".

The standard javax.servlet.jsp.tagext.TagSupport class implements the Tag interface, but also implements the IterationTag interface. Because of this, it is inefficient to use the TagSupport class for a tag that does not iterate through the tag body. This is especially important to consider when migrating code from a JSP 1.1 environment to a JSP 1.2 environment, in case you created tag handlers that extended TagSupport under JSP 1.1. For simple tag handlers not requiring body iteration, it is best to implement the Tag interface from scratch.

The Tag interface defines methods for the following key functions:

  • Set up the JSP page context object (pageContext property).

  • Set or get the parent tag handler—the handler for the closest enclosing tag, if applicable (parent property).

  • Set up the tag attributes.

  • Conditionally process the tag body, as appropriate, according to the return value of the doStartTag() method. (See immediately following.)

  • Conditionally process the remainder of the JSP page after the tag, as appropriate, according to the return value of the doEndTag() method. (See immediately following.)

  • Release state information.

For complete information, see the Sun Microsystems Tag interface Javadoc at:

http://java.sun.com/j2ee/sdk_1.3/techdocs/api/javax/servlet/jsp/tagext/Tag.html

In particular, the Tag interface specifies the following key methods:

  • doStartTag()

  • doEndTag()

The tag developer provides code for these methods in the tag handler class, as appropriate, to be executed as the start-tag and end-tag, respectively, are encountered. The JSP page implementation class generated by the JSP translator includes appropriate calls to these methods.

Implement action processing—whatever you want the action tag to accomplish—in the doStartTag() method. The doEndTag() method implements any appropriate post-processing. In the case of a tag without a body, essentially nothing happens between the execution of these two methods.

The Tag interface also specifies getter and setter methods for the pageContext and parent properties. The JSP page implementation instance invokes the setPageContext() and setParent() methods before invoking the doStartTag() and doEndTag() methods.

The doStartTag() method returns an int value. For a tag handler class implementing the Tag interface, this value is one of the following:

  • SKIP_BODY: Do not evaluate the body, if any. This is the only option if the TLD file specifies a <body-content> setting of empty for the tag associated with this handler.

  • EVAL_BODY_INCLUDE: Evaluate the body and pass it through to the current JSP out object.

The doEndTag() method also returns an int value, one of the following:

  • SKIP_PAGE: Skip the rest of the page after the tag. If the request was originally from another page, from which the current page was forwarded to or included, only the remainder of the current page evaluation is skipped.

  • EVAL_PAGE: Evaluate the remainder of the page after the tag.

Simple Tag Handlers with Iteration

For a custom tag that has a body that does not require access and special processing by the tag handler, but does require repeated reevaluation such as for iteration, the tag handler class can implement the following standard interface:

  • javax.servlet.jsp.tagext.IterationTag

The IterationTag interface extends the Tag interface. A class that implements the IterationTag interface is still known as a simple tag handler.

The following standard support class implements the IterationTag interface, as well as the java.io.Serializable interface, and can be used as a base class:

  • javax.servlet.jsp.tagext.TagSupport

In addition to implementing appropriate methods from the Tag and IterationTag interfaces, the TagSupport class includes a convenience method, findAncestorWithClass(), that calls the getParent() method defined in the Tag interface.


Note:

It is not advisable to extend the TagSupport class if your tag handler does not have to support body iteration. Because TagSupport implements the IterationTag interface, there is looping logic that would be unnecessary. In addition to being generally inefficient, this increases the likelihood of methods exceeding a Java 64K size limit.

The IterationTag interface inherits basic tag-handling functionality, including the doStartTag() and doEndTag() methods, from the Tag interface. See "Simple Tag Handlers without Iteration".

The IterationTag interface also defines the following additional key method:

  • doAfterBody()

This method is called after each evaluation of the tag body, to see if the body should be evaluated again. It returns one of the following int values:

  • SKIP_BODY: Stop iterating; do not reevaluate the tag body. Call doEndTag() instead. The SKIP_BODY setting is also used when the body is not to be evaluated in the first place, and is the only option if the TLD file specifies a <body-content> setting of empty for the tag associated with this handler.

  • EVAL_BODY_AGAIN: Continue iterating; reevaluate the tag body. After the body is evaluated, the doAfterBody() method is called again.


Notes:

  • In the JSP 1.1 specification, the doAfterBody() method was defined in the BodyTag interface. Moving this method definition to the IterationTag interface, beginning with the JSP 1.2 specification, allows a simple iteration tag handler to avoid the overhead of maintaining a BodyContent object.

  • For a complete example of IterationTag usage, see "Example: Using the IterationTag Interface".


Tag Handlers That Access Body Content

For a custom tag with body content that the tag handler must be able to access, the tag handler class can implement the following standard interface:

  • javax.servlet.jsp.tagext.BodyTag

The following standard support class implements the BodyTag interface, as well as the java.io.Serializable interface, and can be used as a base class:

  • javax.servlet.jsp.tagext.BodyTagSupport

This class implements appropriate methods from the Tag, IterationTag, and BodyTag interfaces.


Note:

Do not use the BodyTag interface (or BodyTagSupport class) if your tag handler does not actually require access to the body content. This would result in the needless overhead of creating and maintaining a BodyContent object. Depending on whether iteration through the body is required, use the Tag interface or the IterationTag interface (or TagSupport class) instead.

BodyTag Features

The BodyTag interface inherits basic tag-handling functionality from the Tag interface, including the doStartTag() and doEndTag() methods and their defined return values. It also inherits functionality from the IterationTag interface, including the doAfterBody() method and its defined return values. See "Simple Tag Handlers without Iteration" and "Simple Tag Handlers with Iteration".

Along with its inherited features, the BodyTag interface adds functionality to capture execution results from the tag body. Evaluation of a tag body is encapsulated in an instance of the javax.servlet.jsp.tagext.BodyContent class. The page implementation object creates this instance as appropriate. See "BodyContent Objects".

As with the Tag interface, the doStartTag() method specified in the BodyTag interface supports int return values of SKIP_BODY and EVAL_BODY_INCLUDE. For BodyTag, this method also supports an int return value of EVAL_BODY_BUFFERED. To summarize the meanings:

  • SKIP_BODY: Do not evaluate the body.

  • EVAL_BODY_INCLUDE: Evaluate the body and pass it through to the JSP out object without the body content being made available to the tag handler. This is essentially the same behavior as in an EVAL_BODY_INCLUDE scenario with a tag handler that implements the IterationTag interface.

  • EVAL_BODY_BUFFERED: Create a BodyContent object for processing of the tag body content.

The BodyTag interface also adds definitions for the following methods:

  • setBodyContent(): Set the bodyContent property (a BodyContent instance) of the tag handler.

  • doInitBody(): Prepare to evaluate the tag body.

If the doStartTag() method returns EVAL_BODY_BUFFERED, the JSP page implementation instance executes the following steps, in order:

  1. It creates a BodyContent instance.

  2. It calls the setBodyContent() method of the tag handler, to pass the BodyContent instance to the tag handler.

  3. It calls the doInitBody() method of the tag handler to perform initialization, if any, related to the BodyContent instance.

These steps occur before the tag body is evaluated. While the body is evaluated, the JSP out object will be bound to the BodyContent object.

After each evaluation of the body, as for tag handlers implementing the IterationTag interface, the page implementation instance calls the tag handler doAfterBody() method. This involves the following possible return values:

  • SKIP_BODY: Stop iterating; do not reevaluate the tag body. Call doEndTag() instead. The JSP out object is restored from the page context.

  • EVAL_BODY_AGAIN: Continue iterating; reevaluate the tag body. When the body is evaluated, it is passed through to the current JSP out object. After the body is evaluated, the doAfterBody() method is called again.

Once evaluation of the body is complete, for however many iterations are appropriate, the page implementation instance invokes the tag handler doEndTag() method.

BodyContent Objects

For tag handlers implementing the BodyTag interface, evaluation results from the tag body are made accessible to the tag handler through an instance of the javax.servlet.jsp.tagext.BodyContent class. This class extends the javax.servlet.jsp.JspWriter class.

A BodyContent instance is created through the pushBody() method of the JSP page context.

The BodyContent class, in addition to inheriting JspWriter features, adds methods to accomplish the following:

  • Return its contents as a java.io.Reader object (getReader() method).

  • Write its contents into a java.io.Writer object (writeOut() method).

  • Convert its contents into a String object (getString() method).

  • Clear its contents (clearBody() method).

Typical uses for a BodyContent object include the following:

  • Convert its contents into a String instance and then use the string as a value for an operation.

  • Write its contents into the JSP out object that was active as of when the start-tag was encountered.

TryCatchFinally Interface

For data integrity and resource management when exceptions occur during tag processing, the JSP 1.2 specification introduced the javax.servlet.jsp.tagext.TryCatchFinally interface. Implementing this interface in your tag handlers is particularly useful for tags that must handle errors and for ensuring the proper release of resources.

The TryCatchFinally interface specifies the following methods:

  • void doCatch(java.lang.Throwable throw)

    This method can be invoked on a tag handler when a Throwable error occurs during evaluation of a tag body or during a call to the doStartTag(), doEndTag(), doAfterBody(), or doInitBody() method. The Throwable object that was encountered is taken as input by the doCatch() method. This method would not be invoked if the Throwable error occurs during a call to a setter method.

    The doCatch() method can throw an exception (the original Throwable exception or a new exception) to be propagated through an error chain.

  • void doFinally()

    This method is invoked regardless of whether a Throwable error, as discussed for the doCatch() method, occurs. It would not be invoked, however, if a Throwable error occurs during a call to a setter method.

    The doFinally() method should not throw an exception.

Following is a typical TryCatchFinally invocation (from the Sun Microsystems JavaServer Pages Specification, Version 1.2):

 h = get a Tag();  // get a tag handler, perhaps from pool

 h.setPageContext(pc);  // initialize as desired
 h.setParent(null);
 h.setFoo("foo");
 
 // tag invocation protocol; see Tag.java
 try {
   h.doStartTag()...
   ....
   h.doEndTag()...
 } catch (Throwable t) {
   /* React to exceptional condition; invoked if exception occurs between
      doStartTag() and doEndTag(). */
   h.doCatch(t);
 } finally {
   // restore data invariants and release pre-invocation resources
   h.doFinally();
   /* doFinally() is almost always called, unless Throwable error occurs
      during setter method, or Java thread terminates. */
 }

Access to Outer Tag Handler Instances

Where nested custom tags are used, the tag handler instance of the nested tag has access to the tag handler instance of the outer tag, which might be useful in any processing and state management performed by the nested tag.

This functionality is supported through the static findAncestorWithClass() method of the javax.servlet.jsp.tagext.TagSupport class. Even though the outer tag handler instance is not named in the JSP page context, it is accessible because it is the closest enclosing instance of a given tag handler class.

Consider the following JSP code example:

<foo:bar1 attr="abc" >
   <foo:bar2 />
</foo:bar1>

Within the code of the bar2 tag handler class (class Bar2Tag, by convention), you can have a statement such as the following:

Tag bar1tag = TagSupport.findAncestorWithClass(this, Bar1Tag.class);

The findAncestorWithClass() method takes the following as input:

  • The this object that is the class handler instance from which findAncestorWithClass() was called (a Bar2Tag instance in the example)

  • The name of the bar1 tag handler class (presumed to be Bar1Tag in the example), as a java.lang.Class instance

The findAncestorWithClass() method returns an instance of the appropriate tag handler class, in this case Bar1Tag, as a javax.servlet.jsp.tagext.Tag instance.

It is useful for a Bar2Tag instance to have access to the outer Bar1Tag instance in case the Bar2Tag needs the value of a bar1 tag attribute or needs to call a method on the Bar1Tag instance.

OC4J JSP Tag Handler Features

This section describes OC4J JSP extended features for tag handler pooling and code generation size reduction. It covers the following topics:

Disabling or Enabling Runtime or Compile-Time Tag Handler Reuse

To improve performance, you can specify that tag handler instances be reused within each JSP page. This is sometimes referred to as tag handler instance pooling. As of Oracle Application Server 10g Release 2 (10.1.2), there are two models for this:

  • Runtime model: The logic and patterns of tag handler reuse is determined at runtime, during execution of the JSP pages. Tag handler reuse is within application scope.

  • Compile-time model: The logic and patterns of tag handler reuse is determined at compile-time, during translation of the JSP pages. This is an effective way to improve performance for an application with very large numbers of tags within the same page (hundreds of tags, for example).

The JSP tags_reuse_default configuration parameter is relevant in either case. See "JSP Configuration Parameters" for further information about this parameter and how to set it.

Key Points Regarding Tag Handler Reuse

Be aware of the following points about tag handler reuse:

  • In the current implementation, the default tags_reuse_default setting is runtime, for use of the runtime model.

  • If you switch from the runtime model (tags_reuse_default value of runtime) to the compile-time model (tags_reuse_default value of compiletime or compiletime_with_release), or from the compile-time model to the runtime model, you must retranslate the JSP pages.

  • The JSP container also supports tag handler reuse in a servlet 2.0 environment. In that environment, the default tags_reuse_default setting is none, for no tag handler reuse.

  • Any given tag handler instance processes only one request at a time.

Enabling or Disabling the Runtime Model for Tag Handler Reuse

The runtime model can be enabled in either of two ways:

  • Use the default tags_reuse_default value of runtime. (For backward compatibility, a setting of true is also supported and is equivalent to runtime.)

or:

  • If tags_reuse_default has a value of none, you can override this in any particular JSP page by setting the oracle.jsp.tags.reuse attribute in the JSP page context to true. For example:

    pageContext.setAttribute("oracle.jsp.tags.reuse", new Boolean(true));
    
    

You can also disable the runtime model in either of two ways:

  • Set tags_reuse_default to a value of none. This also disables the compile-time model. (For backward compatibility, a setting of false is also supported and is equivalent to none.)

or:

  • If tags_reuse_default has a value of runtime, you can override this in any particular JSP page by setting the oracle.jsp.tags.reuse attribute in the JSP page context to false. For example:

    pageContext.setAttribute("oracle.jsp.tags.reuse", new Boolean(false));
    
    

    Notes:

    • Remember to retranslate your JSP pages when switching from the compile-time model to the runtime model for tag handler reuse.

    • You can use separate oracle.jsp.tags.reuse settings in different pages, or even in different sections of the same page.

    • The oracle.jsp.tags.reuse attribute is ignored with a tags_reuse_default setting of compiletime or compiletime_with_release.


Enabling or Disabling the Compile-Time Model for Tag Handler Reuse

You can switch to the compile-time model for tag-handler reuse in one of two ways:

  • Set the tags_reuse_default configuration parameter to compiletime.

or:

  • Set the tags_reuse_default configuration parameter to compiletime_with_release.

A compiletime_with_release setting results in the tag handler release() method being called between uses of the same tag handler within the same page. This method releases state information, with details according to the tag handler implementation. If the tag handler is coded in such a way as to assume a release of state information between tag usages, for example, then a compiletime_with_release setting would be appropriate. If you are unsure about the implementation of the tag handler and about which compile-time setting to use, you might consider experimentation.

To disable the compile-time model, set tags_reuse_default to a value of none. This also disables the runtime model.


Notes:

  • Remember to retranslate your JSP pages when switching from the runtime model to the compile-time model for tag handler reuse.

  • The page context oracle.jsp.tags.reuse attribute is ignored with a tags_reuse_default setting of compiletime or compiletime_with_release.


Tag Handler Code Generation

The Oracle JSP implementation reduces the code generation size for custom tag usage. In addition, there is a JSP configuration flag, reduce_tag_code, that you can set to true for even further size reduction.

Be aware, however, that when this flag is enabled, the code generation pattern does not maximize tag handler reuse. Although you can still improve performance by setting tags_reuse_default to true as described in "Disabling or Enabling Runtime or Compile-Time Tag Handler Reuse", the effect is not maximized when reduce_tag_code is also true.

See "JSP Configuration Parameters" for further information about these parameters and how to set them.

Scripting Variables, Declarations, and Tag-Extra-Info Classes

A custom tag action can create one or more server-side objects, known as scripting variables, that are available for use by the tag itself or by other scripting elements, such as scriptlets and other tags. A scripting variable can be defined either through a <variable> element in the TLD file of the tag library, for elementary cases, or through a tag-extra-info class, for cases where the logic for the scripting variable is more complex.

This section covers the following topics:

Using Scripting Variables

Objects that are defined explicitly in a custom tag can be referenced in other actions through the JSP page context, using the object ID as a handle. Consider the following example:

<oracust:foo id="myobj" attr1="..." attr2="..." />

This statement results in the object myobj being available to scripting elements in the page, according to the declared scope of myobj. (See "Scripting Variable Scopes".) The id attribute is a translation-time attribute. You can specify a variable in one of two ways:

Generally, the more convenient <variable> mechanism will suffice.

The JSP container enters myobj into the page context, where it can later be obtained by other tags or scripting elements using syntax such as the following:

<oracust:bar ref="myobj" />

The myobj object is passed through the tag handler instances for the foo and bar tags. All that is required is knowledge of the name of the object (myobj).


Note:

In the example, id and ref are merely sample attribute names; there are no special predefined semantics for these attribute names. It is up to the tag handler to define attribute names and create and retrieve objects in the page context.

Scripting Variable Scopes

Specify the scope of a scripting variable in the <variable> element or tag-extra-info class of the tag that creates the variable. It can be one of the following int constants:

  • NESTED: Use this setting for the scripting variable to be available between the start-tag and end-tag of the action that defines it.

  • AT_BEGIN: Use this setting for the scripting variable to be available from the start-tag to the end of the page.

  • AT_END: Use this setting for the scripting variable to be available from the end-tag to the end of the page

Variable Declaration Through TLD variable Elements

The JSP 1.1 specification mandated that use of a scripting variable for a custom tag requires the creation of a tag-extra-info (TEI) class. See "Variable Declaration Through Tag-Extra-Info Classes". The JSP 1.2 specification, however, introduced a simpler mechanism—a <variable> element in the TLD file where the associated tag is defined. This is sufficient for most cases, where logic related to the variable is simple enough to not require use of a TEI class.

The <variable> element is a subelement under the <tag> element that defines the tag that uses the variable.

You can specify the name of the variable in one of two ways:

  • Use a <name-given> subelement under <variable> to specify the variable name directly.

or:

  • Use a <name-from-attribute> subelement under <variable> to specify a tag attribute whose value, at translation-time, will specify the variable name.

Along with <name-given> and <name-from-attribute>, the <variable> element has the following subelements:

  • The <variable-class> element specifies the class of the variable. The default is java.lang.String.

  • The <declare> element specifies whether the variable is to be a newly declared variable, in which case the JSP translator will declare it. The default is true. If false, then the variable is assumed to have been declared earlier in the JSP page through a standard mechanism such as a jsp:useBean action, a JSP scriptlet, a JSP declaration, or some custom action.

  • The <scope> element specifies the scope of the variable: NESTED, AT_BEGIN, or AT_END, as described in "Scripting Variable Scopes". The default is NESTED.

Here is an example that declares two scripting variables for a tag myaction. Note that details within the <tag> element that are not directly relevant to this discussion are omitted:

<tag>
   <name>myaction</name>
   ...
   <attribute>
     <name>attr2</name>
     <required>true</required>
   </attribute>
   <variable>
      <name-given>foo_given</name-given>
      <declare>false</declare>
      <scope>AT_BEGIN</scope>
   </variable>
   <variable>
      <name-from-attribute>attr2</name-from-attribute>
      <variable-class>java.lang.Integer</variable-class>
   </variable>
</tag>

The name of the first variable is hardcoded as foo_given. By default, it is of type String. It is not to be newly declared, so is assumed to exist already, and its scope is from the start-tag to the end of the page.

The name of the second variable is according to the setting of the required attr2 attribute. It is of type Integer. By default, it is to be newly declared and its scope is NESTED, between the myaction start-tag and end-tag.

See "Tag Library Descriptor Files" for more information about related TLD syntax.

Variable Declaration Through Tag-Extra-Info Classes

For a scripting variable with associated logic that is at least somewhat complicated, the use of a <variable> element in the TLD file to declare the variable might be insufficient. In this case, you can specify details regarding the scripting variable in a subclass of the javax.servlet.jsp.tagext.TagExtraInfo abstract class. This manual refers to such a subclass as a tag-extra-info class. Tag-extra-info classes support additional validation of tag attributes and provide additional information about scripting variables to the JSP runtime.

The JSP container uses tag-extra-info instances during translation. The TLD file specifies any tag-extra-info classes to use for scripting variables of a given tag. Use <tei-class> elements, as in the following example:

<tag>
  <name>loop</name>
  <tag-class>examples.ExampleLoopTag</tag-class>
  <tei-class>examples.ExampleLoopTagTEI</tei-class>
  <body-content>JSP</body-content>
  <description>for loop</description>
  <attribute>
     ...
  </attribute>
  ...
</tag>

The following are related classes, also in the javax.servlet.jsp.tagext package:

  • TagData: An instance of this class contains translation-time attribute value information for a tag instance.

  • VariableInfo: Each instance of this class contains information about a scripting variable that is declared, created, or modified by a tag at runtime.

  • TagInfo: An instance of this class contains information about the relevant tag. The class is instantiated from the TLD file and is available only at translation time. TagInfo has methods such as getTagName(), getTagClassName(), getBodyContent(), getDisplayName(), and getInfoString().

You can refer to the following location for further information:

http://java.sun.com/j2ee/sdk_1.3/techdocs/api/javax/servlet/jsp/tagext/package-summary.html


Note:

It is uncommon to use TagInfo instances in a tag-extra-info implementation, although it might be useful if you want to map a single tag-extra-info class to multiple tag libraries and TLD files, for example.

The following methods of the TagExtraInfo class are related:

  • boolean isValid(TagData data)

    The JSP translator calls this method for translation-time validation of the tag attributes, passing it a TagData instance.

  • VariableInfo[] getVariableInfo(TagData data)

    The JSP translator calls this method during translation, passing it a TagData instance. This method returns an array of VariableInfo instances, with one instance for each scripting variable the tag creates.

  • void setTagInfo(TagInfo info)

    Calling this method sets a TagInfo instance as an attribute of the tag-extra-info class. This method is typically called by the JSP container.

  • TagInfo getTagInfo()

    Use this method to retrieve the TagInfo attribute of the tag-extra-info class, assuming the TagInfo attribute was previously set.

The tag-extra-info class constructs each VariableInfo instance with the following information regarding the scripting variable:

  • Its name

  • Its Java type (not a primitive type)

  • A boolean value indicating whether the variable is to be newly declared, in which case the JSP translator will declare it

  • Its scope


Important:

As of the OC4J 10.1.2 implementation, you can have the getVariableInfo() method return either a fully qualified class name (FQCN) or a partially qualified class name (PQCN) for the Java type of the scripting variable. FQCNs were required in previous releases, and are still preferred to avoid confusion in case there are duplicate class names between packages. Primitive types are not supported.

See "Sample Tag-Extra-Info Class: ExampleLoopTagTEI.java" for sample code of a tag-extra-info class.

Validation and Tag-Library-Validator Classes

The JSP 1.2 specification introduced a feature to optionally associate a "validator" class with each tag library. These classes are referred to as tag-library-validator (TLV) classes. The purpose of a TLV class is to validate any JSP page that uses the tag library, verifying that the page adheres to any constraints that you wish to impose through your implementation of the TLV class. Although it is probably typical for a TLV class to check for constraints regarding use of the associated tag library only, there is no limitation. The TLV class can check any aspect of a JSP page.

A tag-library-validator class must be a subclass of the javax.servlet.jsp.tagext.TagLibraryValidator class.

The following sections discuss tag library validation and TLV classes:

TLD validator Element

To specify a TLV class for a tag library, use a <validator> element in the TLD file. The <validator> element has the following subelements:

  • The <validator-class> subelement specifies the TLV class name.

  • The <description> subelement can be used to provide documentation about the TLV class.

  • The <init-param> subelement and its own subelements—<param-name> and <param-value>—can be used to set initialization parameters for the TLV class. This is similar to how <init-param> subelements work within <servlet> elements in the application deployment descriptor (web.xml). There is also an optional <description> subelement under the <init-param> element.

The following <validator> element examples are from the Sun Microsystems JavaServer Pages Standard Tag Library, Version 1.0 specification.

Example 1

This is an example of a TLV class (ScriptFreeTLV) that can disallow JSP declarations, JSP scriptlets, JSP expressions, and runtime expressions according to the settings of its initialization parameters. In this case, JSP expressions and runtime expressions will be allowed, but not JSP declarations or JSP scriptlets.

<validator>
   <validator-class>
      javax.servlet.jsp.jstl.tlv.ScriptFreeTLV
   </validator-class>
   <init-param>
      <param-name>allowDeclarations</param-name>
      <param-value>false</param-value>
   </init-param>
   <init-param>
      <param-name>allowScriptlets</param-name>
      <param-value>false</param-value>
   </init-param>
   <init-param>
      <param-name>allowExpressions</param-name>
      <param-value>true</param-value>
   </init-param>
   <init-param>
      <param-name>allowRTExpressions</param-name>
      <param-value>true</param-value>
   </init-param>
</validator>

Example 2

This is an example of a TLV class (PermittedTagLibsTLV) that allows tag library usage only as specified in its initialization parameter. The use of the tag library with which the TLV class is associated is allowed implicitly. In addition, the TLV class allows the libraries specified in a list, with entries separated by white space, in its initialization parameter setting. In this case, it allows only the core, xml, fmt, and sql JSTL libraries.

<validator>
   <validator-class>
      javax.servlet.jsp.jstl.tlv.PermittedTaglibsTLV
   </validator-class>
   <init-param>
      <param-name>permittedTaglibs</param-name>
      <param-value>
         http://java.sun.com/jstl/core
         http://java.sun.com/jstl/xml
         http://java.sun.com/jstl/fmt
         http://java.sun.com/jstl/sql
      </param-value>
   </init-param>
</validator>

Key TLV-Related Classes and the validation() Method

As the introduction mentions, a TLV class is a subclass of the javax.servlet.jsp.tagext.TagLibraryValidator class.

The following related classes are also in the javax.servlet.jsp.tagext package:

  • PageData: An instance of this class is generated by the JSP translator and contains information corresponding to the XML view of the page being translated.

  • ValidationMessage: An instance of this class contains an error message from a TLV instance, being returned through the TLV validate() method.

Here is the key method of a TLV class:

  • ValidationMessage[] validate (String prefix, String uri, PageData page)

    The JSP container calls this method each time it encounters a taglib directive that points to a TLD file that has a <validator> element. The method takes as input the tag library prefix, the TLD URI, and the PageData object (XML view) of the page. If errors are encountered during validation, the validate() method returns an array of validation messages. Because the OC4J JSP container supports the optional jsp:id attribute, the jsp:id values are included in the validation messages.

    See the next section, "TLV Processing", for more information.

TLV Processing

As each taglib directive is encountered in a JSP page during translation, the JSP container searches the associated TLD file for a <validator> element that specifies a TLV class. If one is found, the container executes the following steps during the translation. See the preceding section, "Key TLV-Related Classes and the validation() Method", for background information about classes and methods discussed here.

  1. The TLV class is instantiated, with initialization parameter settings according to any <init-param> subelements of the <validator> element.

  2. The XML view of the JSP page is exposed to the TLV instance. (See "Details of the JSP XML View".)

  3. The validate() method of the TLV instance is called to validate the JSP page. (See the next section, "Validation Mechanisms".) If this method encounters any errors, it returns an array of ValidationMessage instances. If there are no errors, the method can return null or an empty ValidationMessage[] array.


    Note:

    The OC4J JSP container implements an optional JSP 1.2 feature for improved reporting of validation errors—the jsp:id attribute. See "The jsp:id Attribute for Error Reporting During Validation" for information.

  4. Each time a custom tag belonging to this library (the library associated with the TLV class) is encountered, it is checked for a tag-extra-info class. If one is specified, then it is instantiated by the JSP container and its isValid() method is called to validate the attributes of the tag. The isValid() method returns true if this validation is successful, or false if not.

Validation Mechanisms

The XML view of a JSP page cannot generally be validated against a DTD and does not include a DOCTYPE statement. There are various namespace-aware mechanisms that you can use for validation. One mechanism in particular is the W3C XML Schema language. Refer to the W3C Web site for information:

http://www.w3.org/XML/

More elementary mechanisms might be suitable as well, such as simply verifying that only a certain set of elements are used in a JSP page, or that a certain set of elements are not used in a page.

Tag Library Event Listeners

The servlet specification describes the use of the following types of event listeners:

In servlet 2.3 functionality, you can specify event listeners in the application web.xml file. As a result of this, they are registered with the servlet container and notified of relevant state changes. Servlet context listeners, for example, are notified of changes in the application ServletContext object, such as application startup or shutdown. See the Oracle Application Server Containers for J2EE Servlet Developer's Guide for additional information about the event listeners.

The JSP 1.2 specification, for convenience in packaging and deploying tag libraries, introduced support for <listener> elements in TLD files. You can use these elements to specify event listeners, as an alternative to specifying them in the web.xml file. The following sections describe these features:

TLD listener Element

In a TLD file, each <listener> element is at the top level underneath the root <taglib> element. The <listener> element has one subelement, the required <listener-class> element, which specifies the listener class to be instantiated. This would be a class that implements the ServletContextListener, ServletContextAttributeListener, HttpSessionListener, or HttpSessionAttributeListener interface.

Following is an example:

<taglib>
...
   <listener>
      <listener-class>mypkg.MyServletContextListener</listener-class>
   </listener>
...
</taglib>

Activation of Tag Library Event Listeners

When an application starts, the servlet container will make a call to the JSP container to perform the following:

  1. Find and access TLD files.

  2. Read TLD files to find their <listener> elements.

  3. Instantiate and register the listeners.

This is a convenient way to manage application-level and session-level resources that are associated with the usage of a particular tag library. The functionality is essentially the same as for servlet context listeners specified in the web.xml file.


Notes:

  • For event listeners specified in TLD files, the order in which the listeners are registered is undefined, but they are all registered prior to application startup and they are all registered after listeners that are specified in the web.xml file.

  • If a TLD file is present within the WAR file structure, it will be scanned for listeners, and any listeners will be registered, even if the associated tag library is not actually used in the application.


Access of TLD Files for Event Listener Information

You must take certain standard measures to ensure that the JSP container can access TLD files to find their <listener> elements. For general information about TLD file location, accessibility, and packaging, see "Tag Library and TLD Setup and Access". That section includes information about OC4J well-known tag library locations.

Also, generally speaking, for any TLD in the well-known tag library directory, you must specify the tag library in a <taglib> element in the application web.xml file if you want the application to activate any listeners specified in the TLD file. Without this step, TLD files in the shared directory are not accessed to search for their <listener> elements. This is to protect against needless performance impact for any application that does not use a tag library that happens to be in the shared directory. The <taglib> element in web.xml is not required, however, if you are using persistent TLD caching (described in "Oracle Extensions for Tag Library Sharing and Persistent TLD Caching").

End-to-End Custom Tag Examples

The following sections provide complete examples of custom tag usage, including sample JSP pages, tag handler classes, and tag library descriptor files:


Note:

These examples are for illustrative purposes only and do not necessarily reflect the most realistic or efficient approaches.

Example: Using the IterationTag Interface

This sample shows the use of a custom tag, myIterator, to make the current item in a collection available as a scripting variable. It defines a scripting variable through a <variable> element in the TLD file.

For complete information about this example, including unpacking and deploying it, refer to the following Oracle Technology Network Web site:

http://www.oracle.com/technology/tech/java/oc4j/htdocs/how-to-jsp-iterationtag.html

(You must register for membership, but registration is free of charge.)

Sample JSP Page: exampleiterator.jsp

The following JSP page uses the myIterator tag:

<%@ page contentType="text/html;charset=windows-1252"%> 
<HTML> 
<HEAD> 
<TITLE> 
JSP 1.2 IterationTag Sample 
</TITLE> 
</HEAD> 
<%@ taglib uri="/WEB-INF/exampleiterator.tld" prefix="it"%> 
<BODY> 

<% java.util.Vector vector = new java.util.Vector(); 
   vector.addElement("One"); 
   vector.addElement("Two"); 
   vector.addElement("Three"); 
   vector.addElement("Four"); 
   vector.addElement("Five"); 
%> 
  Collection to Iterate over is <%=vector%> ..... <p> 

 <B>Iterating ...</B><br> 
 <it:myIterator collection="<%= vector%>" > 
      Item  <B><%= item%></B><br> 
 </it:myIterator> 
</p> 
</BODY> 
</HTML> 

Sample Tag Handler Class: MyIteratorTag.java

In this sample tag handler class, MyIteratorTag, the doStartTag() method checks whether the collection is null. If not, it retrieves the collection object. If the iterator contains at least one element, then doStartTag() makes the first item in the collection available as a page-scope object and returns EVAL_BODY_INCLUDE. This alerts the JSP container to add the contents of the tag body to the response object and to call the doAfterBody() method.

This class extends the tag handler support class TagSupport, which implements the IterationTag interface.

package oracle.taglib; 

import java.util.*; 
import javax.servlet.jsp.*; 
import javax.servlet.jsp.tagext.*; 

/** 
 * MyIteratorTag extends TagSupport. The TagSupport class in JSP 1.2 implements the IterationTag 
 */ 

public class MyIteratorTag extends TagSupport 
{ 
  private Iterator iterator; 
  private Collection _collection; 

  public void setCollection(Collection collection) 
  { 
        this._collection = collection; 
  } 

  public int doStartTag() throws JspTagException 
  { 
    if (_collection == null) 
    { 
      throw new JspTagException("No collection with name " 
        + _collection 
        + " found"); 
    } 

    iterator = _collection.iterator(); 
    if (iterator.hasNext()) 
    { 
      pageContext.setAttribute("item", iterator.next()); 
      return EVAL_BODY_INCLUDE; 
    } 
    else 
    { 
       return SKIP_BODY; 
    } 
  } 

  public int doAfterBody() 
  { 

     if (iterator.hasNext()) 
     { 
      pageContext.setAttribute("item", iterator.next()); 
      return EVAL_BODY_AGAIN; 
     } 
     else 
     { 
      return SKIP_BODY; 
     } 
  } 

}

Sample Tag Library Descriptor File: exampleiterator.tld

Here is a sample TLD file to define the myIterator tag. This example takes advantage of the JSP 1.2 feature allowing definition of scripting variables directly in TLD files through <variable> elements. This TLD file defines the scripting variable item of type java.lang.Object. (In a JSP 1.1 environment, this would require use of a tag-extra-info class.) The variable is to be newly declared.

The myIterator tag has an attribute collection to specify the collection. This attribute is required and can be set as a runtime expression. The tag also has a <body-content> value of JSP, which means the JSP translator should process and translate the body code.

For JSP 1.2 syntax, be sure to specify the JSP 1.2 tag library DTD path.

<?xml version = '1.0' encoding = 'windows-1252'?> 
<!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>iterate</short-name> 
   <description>This tag lib implements new JSP 1.2 IterationTag
                interface</description> 
   <tag> 
      <name>myIterator</name> 
      <tag-class>oracle.taglib.MyIteratorTag</tag-class> 
      <body-content>JSP</body-content> 
      <attribute> 
          <name>collection</name> 
          <required>true</required> 
          <rtexprvalue>true</rtexprvalue> 
      </attribute> 
      <variable> 
        <name-given>item</name-given> 
        <variable-class>java.lang.Object</variable-class> 
        <declare>true</declare> 
        <!-- default scope: nested --> 
        <description>Scripting Variable item</description> 
      </variable> 
    </tag> 
</taglib>

Example: Using the IterationTag Interface and a Tag-Extra-Info Class

This section provides an end-to-end example of the definition and use of a custom tag, loop, that is used to iterate through the tag body a specified number of times. It defines a scripting variable through a tag-extra-info class.

This example includes the following:

  • JSP source code for a page that uses the tag

  • Source code for the tag handler class

  • Source code for the tag-extra-info class

  • TLD file


Note:

Sample code here uses extended datatypes in the oracle.jsp.jml package. For information, refer to the Oracle Application Server Containers for J2EE JSP Tag Libraries and Utilities Reference.

Sample JSP Page: exampletag.jsp

Following is a sample JSP page, exampletag.jsp, that uses the loop tag, specifying that the outer loop is to be executed five times and the inner loop three times:

<%@ taglib uri="/WEB-INF/exampletag.tld" prefix="foo" %>
<% int num=5; %>
<br>
<pre>
<foo:loop index="i" count="<%=num%>">
body1here: i expr: <%=i%> 
           i property: <jsp:getProperty name="i" property="value" /> 
  <foo:loop index="j" count="3">
  body2here: j expr: <%=j%> 
  i property: <jsp:getProperty name="i" property="value" />
  j property: <jsp:getProperty name="j" property="value" /> 
  </foo:loop>
</foo:loop>
</pre>

Sample Tag Handler Class: ExampleLoopTag.java

This section provides source code for the tag handler class, ExampleLoopTag. Note the following:

  • The tag handler class extends the standard TagSupport class to implement the IterationTag interface.

  • The doStartTag() method returns the integer constant EVAL_BODY_INCLUDE so that the tag body (essentially, the loop) is processed.

  • After each pass through the loop, the doAfterBody() method increments the counter. It returns EVAL_BODY_AGAIN if there are more iterations left, and SKIP_BODY after the last iteration.

  • This class does not define a doEndTag() method. The underlying implementation from TagSupport is used.

Here is the code:

package examples;

import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import java.util.Hashtable;
import java.io.Writer;
import java.io.IOException;
import oracle.jsp.jml.JmlNumber;

public class ExampleLoopTag 
    extends TagSupport
{
    
    String index;
    int count;
    int i;
    JmlNumber ib;

    public ExampleLoopTag() {
      resetAttr();
    }

    public void release() {
      resetAttr();
    }

    private void resetAttr() {
      index=null;
      count=0;
      i=0;
      ib=null;
    }

    public void setIndex(String index)
    {
      this.index=index;
    }
    public void setCount(String count)
    {
      this.count=Integer.parseInt(count);
    }

    public int doStartTag() throws JspException {
        ib=new JmlNumber();
        pageContext.setAttribute(index, ib);
        i++;
        ib.setValue(i);
        return EVAL_BODY_INCLUDE;
    }

    public int doAfterBody() throws JspException {
        if (i >= count) {
            return SKIP_BODY;
        } else
            pageContext.setAttribute(index, ib);
        i++;
        ib.setValue(i);
        return EVAL_BODY_AGAIN;
    }
}

Sample Tag-Extra-Info Class: ExampleLoopTagTEI.java

This section provides the source code for the tag-extra-info class that describes the scripting variable used by the loop tag.

A VariableInfo instance is constructed that specifies the following for the variable:

  • The variable name is according to the index attribute.

  • The variable is of the type oracle.jsp.jml.JmlNumber, which you must specify as a fully qualified class name.

  • The variable is to be newly declared (by the JSP translator).

  • The variable scope is NESTED.

In addition, the tag-extra-info class has an isValid() method that determines whether the count attribute is valid. It must be an integer.

package examples;

import javax.servlet.jsp.tagext.*;

public class ExampleLoopTagTEI extends TagExtraInfo {
    public VariableInfo[] getVariableInfo(TagData data) {
        return new VariableInfo[] 
            {
                new VariableInfo(data.getAttributeString("index"),
                                 "oracle.jsp.jml.JmlNumber",
                                 true,
                                 VariableInfo.NESTED)
            };
    }

    public boolean isValid(TagData data)
    {
      String countStr=data.getAttributeString("count");
      if (countStr!=null)   // for request-time case
      {
        try {
          int count=Integer.parseInt(countStr);
        }
        catch (NumberFormatException e)
        {
          return false;
        }
      }
      return true;
    }
}

Sample Tag Library Descriptor File: exampletag.tld

This section presents the TLD file for the tag library. In this example, the library consists of only one tag, loop.

This TLD file follows JSP 1.2 syntax, specifying the following for the loop tag:

  • The tag handler class is examples.ExampleLoopTag.

  • The tag-extra-info class is examples.ExampleLoopTagTEI.

  • The body-content specification is JSP. This means that the JSP translator should process and translate the body code.

  • There are attributes index and count, both required. The count attribute can be a request-time JSP expression.

Here is the TLD file:

<?xml version = '1.0' encoding = 'ISO-8859-1'?>
<!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>simple</short-name>
  <description>
       A simple tab library for the examples
  </description>
  <!-- example tag -->
  <!-- for loop -->
  <tag>
    <name>loop</name>
    <tag-class>examples.ExampleLoopTag</tag-class>
    <tei-class>examples.ExampleLoopTagTEI</tei-class>
    <body-content>JSP</body-content>
    <description>for loop</description>
    <attribute>
        <name>index</name>
        <required>true</required>
    </attribute>
    <attribute>
        <name>count</name>
        <required>true</required>
        <rtexprvalue>true</rtexprvalue>
    </attribute>
  </tag>
</taglib>

Compile-Time Tags

Standard tag libraries, as described in the JSP specification, use a runtime support mechanism. They are typically portable, not requiring any particular JSP container.

It is also possible, however, for vendors to support custom tags through vendor-specific functionality in their JSP translators. Such tags are not portable to other containers.

It is generally advisable to develop standard, portable tags that use the runtime mechanism, but there might be scenarios where tags using a compile-time mechanism are appropriate, as this section discusses.

General Compile-Time Versus Runtime Considerations

The JSP specification describes a runtime support mechanism for custom tag libraries. This mechanism, using an XML-style TLD file to specify the tags, is covered earlier in this chapter. Creating and using a tag library that adheres to this model generally assures that the library will be portable to any standard JSP environment.

There are, however, reasons to consider compile-time implementations:

  • A compile-time implementation can produce more efficient code.

  • A compile-time implementation allows the developer to catch errors during translation and compilation, instead of the user seeing them at runtime.

JSP Compile-Time Versus Runtime JML Library


Important:

The JML tag library is deprecated in the OC4J 10.1.2 implementation and will be desupported in future implementations.

OC4J provides a portable tag library called the JSP Markup Language (JML) library. This library uses the standard JSP 1.2 runtime mechanism.

However, the JML tags are also supported through a compile-time mechanism. This is because the tags were first introduced with JSP implementations that preceded the JSP 1.1 specification, which is when the runtime mechanism was introduced. The compile-time tags are still supported for backward compatibility.

The general advantages and disadvantages of compile-time implementations apply to the Oracle JML tag library as well. There might be situations where it is advantageous to use the compile-time JML implementation. There are also a few additional tags in that implementation, and some additional expression syntax that is supported.

The Oracle Application Server Containers for J2EE JSP Tag Libraries and Utilities Reference describes both the runtime version and the compile-time version of the JML library.