Oracle9iAS Containers for J2EE Support for JavaServer Pages Developer's Guide Release 2 (9.0.3) Part Number A97679-01 |
|
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 is organized as follows:
The chapter offers a detailed overview of standard tag library functionality. For complete information, refer to the Sun Microsystems JavaServer Pages Specification, Version 1.2 (or higher). For information about the tag libraries provided with OC4J, see the Oracle9iAS 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 new tag library features 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:
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.
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.
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.
mytag
does), and the names of those attributes.
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 1.2 specification.
An attribute of a user-defined type must be set using a request-time expression that returns an instance of the type.
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>
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="..." />
web.xml
file. See "Tag Library Event Listeners".
The remainder of this chapter provides details about these topics.
The JSP 1.2 specification adds features for improved tag library support in the following areas:
New 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.
According to the JSP 1.1 specification, you cannot have multiple TLD files packaged in a single JAR file. The JSP 1.2 specification adds support for this, however. See "Tag Handlers".
New 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".
This feature is new in JSP 1.2. See "Validation and Tag-Library-Validator Classes".
This feature is also new in JSP 1.2. See "Tag Library Event Listeners".
Object
JSP 1.2 adds 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 Oracle9iAS release 2 (9.0.3), 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 until Oracle9iAS release 2 (9.0.3). "Tag Library Descriptor Files" includes information about these features.
<validator>
element and its subelements, allowing you to declare a tag-library-validator class for the tag library
<listener>
element and its subelement, allowing you to declare event listeners for the tag library
<variable>
subelement, and its own subelements, under the <tag>
element, allowing you to declare scripting variables directly through the TLD
<type>
subelement under the <attribute>
subelement of the <tag>
element, for noting the datatype of the attribute
<display-name>
, <large-icon>
, and <small-icon>
elements, and also subelements of the same name under the <tag>
element, for use by authoring tools
<info>
element, and the subelement of the same name under the <tag>
element, were renamed to <description>
.
<tlibversion>
element was changed to <tlib-version>
.
<jspversion>
element was changed to <jsp-version>
.
<shortname>
element was changed to <short-name>
.
<tagclass>
, <teiclass>
, and <bodycontent>
subelements under the <tag>
element were changed to <tag-class>
, <tei-class>
, and <body-content>
.
Notes:
web.xml
file. Validation of TLD files is enabled by default; validation of web.xml
is disabled by default. (See "JSP Configuration Parameters" for information about the no_tld_xml_validate
and xml_validate
parameters.) In Oracle9iAS release 2 (9.0.2) and prior, TLD files and web.xml
were all validated through the xml_validate
parameter, which was disabled by default.
oraxsl
, to convert a JSP 1.1-compliant TLD file into one that is JSP 1.2-compliant. This template is located in the misc
directory under the OC4J demos. See ojspdemos/misc/index.html
for instructions.
The JSP 1.1 specification has two interfaces that can be implemented by tag handlers--Tag
, for tags without bodies, and BodyTag
, for tags with bodies. The JSP 1.2 specification adds 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 in JSP 1.2, 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 adds 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 until 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 contains information about a tag library and individual tags of the library. 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".)
This section provides an overview and general information about TLD file syntax and usage, referring ahead to other sections as appropriate for more information about related topics. This section covers the following topics:
For complete information, refer to the Sun Microsystems JavaServer Pages Specification, Version 1.2.
See "Example: Using the IterationTag Interface and a Tag-Extra-Info Class" for a sample TLD file.
Note:
By default, the OC4J JSP container performs XML validation of TLD files. To disable this, set the |
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, as of Oracle9iAS release 2 (9.0.3), 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 pre-translation, if the ojspc -noTldXmlValidation
flag is not used.)
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.
<tlib-version>
element specifies the version number of the tag library (whatever version number you want to give it).
<jsp-version>
element specifies the JSP version upon which this tag library depends (such as 1.2).
<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".
<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.
<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.
<description>
element can provide a description of the tag library.
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:
<name>
subelement specifies the name of the tag.
<tag-class>
subelement specifies the name of the corresponding tag handler class. See "Tag Handlers" for information about tag handler classes.
<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".
<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.
<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.
<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.
<display-name>
, <large-icon>
, and <small-icon>
subelements for use by authoring tools.
<description>
subelement can provide a description of the tag.
<example>
subelement can provide an example of how to use the tag.
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:
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.
JSP
(the default) indicates that the tag body should be processed as JSP source code and translated.
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, comparing the following traditional syntax:
<foosql:query ... > select ... where salary > 1000 </foosql:query>
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 are new 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.
This section discusses the packaging, placement, and access of tag libraries and their TLD files. It covers the following topics:
This section summarizes the use of taglib
directives, discussing original functionality under the JSP 1.1 specification and new functionality under the JSP 1.2 specification.
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>
Under the JSP 1.1 specification, the uri
setting can indicate a file location as in either of the following scenarios, either directly or through a "shortcut" URI:
See "Specifying a Tag Library by Physical Location" for more information.
Under 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:
<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 JSP 1.1, 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 TLD file must be located and named as follows in the JAR file:
META-INF/taglib.tld
You must place the JAR file 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 that is newly supported by the JSP 1.2 specification.
Note:
In either scenario discussed in this section, the |
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.
In addition to these scenarios, the JSP 1.2 specification allows 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.
While a single TLD file in a JAR file is packaged as /META-INF/taglib.tld
(although this is no longer s strict requirement under JSP 1.2), a JAR file with multiple TLD files must use unique names or subdirectories. 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:
<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.
<uri>
value must 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 the OC4J "well-known" URI location described in "Oracle Extension for Tag Library Sharing". 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".
As an extension of standard JSP "well-known URI" functionality described in the JSP 1.2 specification, the OC4J JSP container supports the use of a shared tag library directory where you can place tag library JAR files to be shared across multiple Web applications.
The directory location is according to the setting of the OC4J JSP well_known_taglib_loc
configuration parameter, with the specified location being under [Oracle_Home]
if [Oracle_Home]
is defined, or under the current directory (from which the OC4J process was started) if [Oracle_Home]
is not defined. The default value of well_known_taglib_loc
is as follows:
j2ee/home/jsp/lib/taglib/
Also see "JSP Configuration Parameters" for a description of the well_known_taglib_loc
parameter.
The shared directory must be added to the server-wide classpath by specifying it as a library path element. The default location is set in the application.xml
file in the OC4J configuration files directory (j2ee/home/config
by default in OC4J standalone); you can alter the setting there as desired. See the Oracle9iAS Containers for J2EE User's Guide for information about application.xml
.
TLD files to be shared across a set of applications must be placed in a JAR file. There can be multiple JAR files in the well-known location. Each tag library will be uniquely identified through the <uri>
element in its TLD file. Also see "Packaging and Accessing Multiple Tag Libraries in a JAR File".
Versions 2.2 and higher of the Sun Microsystems Java Servlet Specification describe 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:
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, Version 2.3, and the Sun Microsystems JavaServer Pages Specification, Version 1.2, for more information about the web.xml
deployment descriptor.
Important:
Using the |
This example presents key aspects of tag library packaging for some of the Oracle JSP demo applications. 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, which 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 taglib
directives from the JSP pages of the demos, 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" %>
This section describes tag handlers, which define the semantics of actions that result from the use of custom tags. It includes the following topics:
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 Sun Microsystems JavaServer Pages Specification, Version 1.2 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:
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".
rtattr="<%=expression%>"
For request-time attributes, there is no conversion--a request-time expression can be assigned to the attribute, and to its corresponding tag handler property, for any property type. This would apply to a tag attribute whose type is user-defined, for example.
Custom tags, as with standard JSP tags, may or may not have a body. In the case of a custom tag, even when there is a body, its content may not have to be accessed by the tag handler.
There are four scenarios:
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
.
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.
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.
Again, there is a start-tag and an end-tag with a body of statements in between; however, the tag handler must access the body content.
<oracust:mybodytag attr1="...", attr2="..." > ...body accessed and processed by tag handler... </oracust:mybodytag>
In this case, the tag handler should implement the BodyTag
interface.
The <body-content>
setting for this tag in the TLD file should be JSP
(the default) or tagdependent
, depending on whether the body content should be translated or treated as template data, respectively.
Notes:
|
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:
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:
pageContext
property).
parent
property).
doStartTag()
method. (See immediately following.)
doEndTag()
method. (See immediately following.)
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:
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:
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:
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.
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:
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:
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:
This class implements appropriate methods from the Tag
, IterationTag
, and BodyTag
interfaces.
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:
BodyContent
instance.
setBodyContent()
method of the tag handler, to pass the BodyContent
instance to the tag handler.
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:
java.io.Reader
object (getReader()
method).
java.io.Writer
object (writeOut()
method).
String
object (getString()
method).
clearBody()
method).
Typical uses for a BodyContent
object include the following:
String
instance and then use the string as a value for an operation.
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 adds 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 may 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 may 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:
this
object that is the class handler instance from which findAncestorWithClass()
was called (a Bar2Tag
instance in the example)
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:
In Oracle9iAS release 2, 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 release 2 (9.0.3), there are two models for this:
application
scope.
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:
tags_reuse_default
setting is runtime
, for use of 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 re-translate the JSP pages.
tags_reuse_default
setting is none
, for no tag handler reuse.
The runtime model can be enabled in either of two ways:
tags_reuse_default
value of runtime
. (For backward compatibility, a setting of true
is also supported and is equivalent to runtime
.)
or:
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:
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:
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));
You can switch to the compile-time model for tag-handler reuse in one of two ways:
or:
A compiletime_with_release
setting results in the tag handler release()
method being called between usages of the same tag handler within the same page. This method releases state information, with details according to the tag handler implementation. For example, if the tag handler is coded so as to assume a release of state information between tag usages, then compiletime_with_release
would be appropriate. If 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.
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:
<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".
<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
).
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
In the JSP 1.1 specification, 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". With the JSP 1.2 specification, however, there is 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:
or:
<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:
<variable-class>
element specifies the class of the variable. The default is java.lang.String
.
<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.
<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 key 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.
The key methods of the TagExtraInfo
class are as follows:
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.
The tag-extra-info class constructs each VariableInfo
instance with the following information regarding the scripting variable:
See "Sample Tag-Extra-Info Class: ExampleLoopTagTEI.java" for sample code of a tag-extra-info class.
The JSP 1.2 specification adds 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.
This section discusses tag library validation and TLV classes, covering the following topics:
To specify a TLV class for a tag library, use a <validator>
element in the TLD file. The <validator>
element has the following subelements:
<validator-class>
subelement specifies the TLV class name.
<description>
subelement can be used to provide documentation about the TLV class.
<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. In addition to the tag library with which the TLV class is associated (the use of which is allowed implicitly), 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.
<init-param>
subelements of the <validator>
element.
validate()
method of the TLV instance is called to validate the JSP page. (See the next section, "Validation Mechanisms".) If this method encounters any errors, it returns an array of ValidationMessage
instances. If there are no errors, the method can return null
or an empty ValidationMessage[]
array.
Note:
The OC4J JSP container implements an optional JSP 1.2 feature for improved reporting of validation errors--the |
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 may 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 Sun Microsystems Java Servlet Specification, Version 2.3 describes the use of the following types of event listeners:
javax.servlet.ServletContextListener
javax.servlet.ServletContextAttributeListener
javax.servlet.http.HttpSessionListener
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.
The JSP 1.2 specification, for convenience in packaging and deploying tag libraries, adds 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. This section describes the JSP 1.2 features, covering the following topics:
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:
<listener>
elements.
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.
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 the OC4J shared tag library directory ("well-known" URI location).
In addition, for any TLD file 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.
This section provides complete examples of custom tag usage, including sample JSP pages, tag handler classes, and tag library descriptor files. It includes the following samples:
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://otn.oracle.com/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> OJSP 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.
Included in the example are the following:
Note:
Sample code here uses extended datatypes in the |
Following is a sample JSP page, exampletag.jsp
, that uses the loop
tag, specifying that the outer loop 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:
TagSupport
class to implement the IterationTag
interface.
doStartTag()
method returns the integer constant EVAL_BODY_INCLUDE
so that the tag body (essentially, the loop) is processed.
doAfterBody()
method increments the counter. It returns EVAL_BODY_AGAIN
if there are more iterations left, and SKIP_BODY
after the last iteration.
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:
index
attribute.
oracle.jsp.jml.JmlNumber
, which you must specify as a fully qualified class name.
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 the one tag, loop
.
This TLD file follows JSP 1.2 syntax, specifying the following for the loop
tag:
examples.ExampleLoopTag
.
examples.ExampleLoopTagTEI
.
body-content
specification is JSP
. This means that the JSP translator should process and translate the body code.
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 Sun Microsystems JavaServer Pages Specification, Version 1.2, use a runtime support mechanism. They are typically portable, not requiring any particular JSP container.
It is also possible 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 may be scenarios where tags using a compile-time mechanism are appropriate, as this section discusses.
The JSP 1.2 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:
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 may 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 Oracle9iAS Containers for J2EE JSP Tag Libraries and Utilities Reference describes both the runtime version and the compile-time version of the JML library.
|
![]() Copyright © 2000, 2002 Oracle Corporation. All Rights Reserved. |
|