Oracle® Application Server Containers for J2EE Support for JavaServer Pages Developer's Guide
10g Release 2 (10.1.2) B14014-02 |
|
Previous |
Next |
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/
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:
Sun Microsystems JavaServer Pages Specification
Sun Microsystems Javadoc for the javax.servlet.jsp.tagext
package, at the following Web site:
http://java.sun.com/j2ee/sdk_1.3/techdocs/api/javax/servlet/jsp/tagext/package-summary.html
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.
The JSP 1.2 specification introduced features for improved tag library support in the following areas:
Tag library descriptor features
Features are outlined in the next section, "Summary of TLD File Changes Between the JSP 1.1 and 1.2 Specifications". "Tag Library Descriptor Files" describes TLD features in detail.
Support for multiple tag libraries and their TLD files in a single JAR file
According to the JSP 1.1 specification, you could not have multiple TLD files packaged in a single JAR file. The JSP 1.2 specification supports this, however. See "Tag Handlers".
Tag handler features
Features are summarized in "Summary of Tag Handler Changes Between the JSP 1.1 and 1.2 Specifications". Tag handler features are described in detail in "Tag Handlers".
Tag library validators
This feature was introduced in the JSP 1.2 specification. See "Validation and Tag-Library-Validator Classes".
Tag library event listeners
This feature was also introduced in the JSP 1.2 specification. See "Tag Library Event Listeners".
Support for tag attributes of type Object
The JSP 1.2 specification introduced support for tag attributes of type java.lang.Object
. The OC4J JSP container supports this feature, as described in the previous section, "Overview of a Custom Tag Library Implementation".
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". |
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 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.
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 theno_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".
|
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 externalDOCTYPE 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.
|
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.
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:
|
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:
|
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 ">
;" 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.
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.
The following sections discuss the packaging, placement, and access of tag libraries and their TLD files:
Overview: Specifying a Tag Library with the taglib Directive
Packaging and Accessing Multiple Tag Libraries in a JAR File
Oracle Extensions for Tag Library Sharing and Persistent TLD Caching
Notes:
|
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".
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, thetaglib 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".
|
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:
|
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".
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".
|
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 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 thejsp-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 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:
|
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
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>
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> ...
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" %>
The following sections describe tag handlers, which define the semantics of actions that result from the use of custom tags:
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. |
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.
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:
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
.
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.
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.
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.
|
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.
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.
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 theTagSupport 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:
|
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 theBodyTag 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.
|
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:
It creates a BodyContent
instance.
It calls the setBodyContent()
method of the tag handler, to pass the BodyContent
instance to the tag handler.
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.
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.
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. */ }
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.
This section describes OC4J JSP extended features for tag handler pooling and code generation size reduction. It covers the following topics:
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.
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.
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:
|
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:
|
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.
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:
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:
Provide a <variable>
element for the variable in the TLD file, to specify the name and type of the variable along with additional information. See "Variable Declaration Through TLD variable Elements".
Create a tag-extra-info class, to specify the name and type of the variable along with additional information and related logic. Specify the tag-extra-info class name in a <tei-class>
element in the TLD file. See "Variable Declaration Through Tag-Extra-Info Classes".
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.
|
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
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.
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 useTagInfo 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 thegetVariableInfo() 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.
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:
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.
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>
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>
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.
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.
The TLV class is instantiated, with initialization parameter settings according to any <init-param>
subelements of the <validator>
element.
The XML view of the JSP page is exposed to the TLV instance. (See "Details of the JSP XML View".)
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—thejsp:id attribute. See "The jsp:id Attribute for Error Reporting During Validation" for information.
|
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.
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.
The servlet specification describes the use of the following types of event listeners:
Servlet context listener, implementing interface javax.servlet.ServletContextListener
Servlet context attribute listener, implementing interface javax.servlet.ServletContextAttributeListener
HTTP session listener, implementing interface javax.servlet.http.HttpSessionListener
HTTP session attribute listener, implementing interface javax.servlet.http.HttpSessionAttributeListener
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:
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>
When an application starts, the servlet container will make a call to the JSP container to perform the following:
Find and access TLD files.
Read TLD files to find their <listener>
elements.
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:
|
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").
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. |
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.)
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>
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; } } }
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>
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 theoracle.jsp.jml package. For information, refer to the Oracle Application Server Containers for J2EE JSP Tag Libraries and Utilities Reference.
|
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>
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; } }
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; } }
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>
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.
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.
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.