Skip Headers
Oracle® Containers for J2EE Support for JavaServer Pages Developer's Guide
10g Release 3 (10.1.3)
Part No. B14430-01
  Go To Documentation Library
Home
Go To Product List
Solution Area
Go To Table Of Contents
Contents
Go To Index
Index

Previous
Previous
Next
Next
 

7 Working with Custom Tags

This chapter discusses custom tags and 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 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 Containers for J2EE JSP Tag Libraries and Utilities Reference.

A multitude of resources are available for learning how to write and implement custom tags. For information beyond what is provided here, refer to the following resources:

http://java.sun.com/j2ee/1.4/docs/api/javax/servlet/jsp/tagext /package-summary.html

7.1 What Are Custom Tags?

Custom tags, also known as tag extensions, are JSP elements that allow custom logic and output provided by other Java components to be inserted into JSP pages. The logic provided through a custom tag is implemented by a Java object known as a tag handler. When OC4J encounters a custom tag in a JSP during translation, it generates code to obtain and interact with the tag handler. Custom tags are included in a JSP page using XML syntax. Tags may or may not contain a body. Tags can also contain XML attributes that match properties in the corresponding tag handler.

With the advent of JSP 2.0, you now have two options for creating custom tags:

Related tag handlers or tag files can be packaged together in a tag library. Libraries developed as tag handlers must include an XML document known as a tag library descriptor (TLD) that describes the syntax of each tag and maps the tag to its corresponding handler class. Tag file libraries do not technically require a TLD, although descriptors are required if the library will be packaged as an archive for deployment.

The types of custom tags you create will depend on your needs. Tags that use either a classic or a simple tag handler are ideal when the flexibility of the Java language is required. Tag files are useful when creating tags that are presentation-centric or that take advantage of existing tag libraries, such as the JSTL.

7.1.1 Available Tag Libraries

Oracle provides extensive tag libraries with OC4J and other components. See the Oracle Containers for J2EE JSP Tag Libraries and Utilities Reference for details on available Oracle tag libraries.

Additional tag libraries are available from vendors and organizations. For example, the Jakarta Taglibs includes a wide selection of libraries available for download from http://jakarta.apache.org/taglibs/.


Note:

The JSTL distribution is no longer installed in the ORACLE_HOME/j2ee/home/jsp/lib/taglib directory within OC4J.

See "Sharing Tag Libraries Across Web Applications" for instructions on sharing tag libraries across deployed Web applications.


7.1.2 When Should You Consider Creating/Using Custom Tag Libraries?

Custom tags offer a number of benefits, including cleaner JSP code and code reusability. Some situations make creating and/or using custom tags almost mandatory. In particular, consider the following situations:

  • JSP pages would otherwise have to include a significant amount of Java logic regarding presentation and format of output.

  • Convenient JSP programming access to functionality that would otherwise require the use of a Java API is needed.

  • Special manipulation or redirection of JSP output is required.

7.1.2.1 Eliminating Extensive Java Logic

Because JSP developers might not be experienced in Java programming, they might not be ideal candidates for coding Java logic in the page—logic that dictates presentation and format of the JSP output, for example.

This is a situation where JSP tag libraries might be helpful. If many of your JSP pages will require such logic in generating their output, a tag library to replace Java logic would be a great convenience for JSP developers.

7.1.2.2 Providing Convenient JSP Programming Access to API Features

Instead of having Web application programmers rely on Java APIs for using product functionality or extensions from servlets or JSP scriptlets, you can provide a tag library. A tag library can make the programmer's task much more convenient, with appropriate API calls being handled automatically by the tag handlers.

For example, tags as well as JavaBeans are provided with OC4J for e-mail and file access functionality. There is also a tag library as well as a Java API provided with the OC4J Web Object Cache. Similarly, while Oracle Application Server Personalization provides a Java API, OC4J also provides a tag library that you can use instead if you want to program a personalization application.

7.1.2.3 Manipulating or Redirecting JSP Output

Another common situation for custom tags is if special runtime processing of the response output is required. Perhaps the desired functionality requires an extra processing step, or redirection of the output to somewhere other than the browser.

For example, you can create a custom tag - <cust:log> - that will redirect the tag text into a log file instead of to a browser:

<cust:log>
   Text to log.
   More text to log.
   Yet more text to log.
</cust:log>

7.2 Working with Tag Handlers

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

7.2.1 What Are Classic Tag Handlers?

A classic tag handler is an instance of a Java class that directly or indirectly implements the standard javax.servlet.jsp.tagext.Tag interface. Although often regarded as somewhat complicated to write, classic tag handlers are your only option if Java scriplets or expressions must be used in the tag body or attribute values.

7.2.1.1 Classic Tag Handler Interfaces

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 classic 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.

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.


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 Tag Handler Features" for information about the Oracle implementation.

7.2.1.2 Custom Tag Processing, with or without Tag Bodies

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

There are four scenarios:

  1. There is no body.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    <oracust:mybodytag attr="...", 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.

7.2.1.3 Tag Handlers That Access Body Content

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

  • javax.servlet.jsp.tagext.BodyTag

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

  • javax.servlet.jsp.tagext.BodyTagSupport

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


Note:

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

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.

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.

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.

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.

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.

7.2.2 What Are Simple Tag Handlers?

A new feature of JSP 2.0, simple tag handlers provide as much power as classic tag handlers, but are much easier to implement due to a much simpler Java interface and a more straightforward lifecycle.

Unlike classic tag handlers, simple tag handler objects are never cached and reused by the OC4J JSP container. Instead, an object is instantiated, executed and then discarded. There are no complicated caching semantics when using this interface since nothing is cached or reused. This simplified lifecycle helps make writing tag handlers easier and less prone to error.

Note that while this discussion focuses on implementing simple tag handlers as Java classes, simple tags can also be implemented completely in JSP syntax using tag files. See "Working with Tag Files" for details. However, this option is only viable if the flexibility of Java is not required.

7.2.2.1 The SimpleTag Interface

Simple tag handler classes implement a single interface, javax.servlet.jsp.tagext.SimpleTag. The interface includes only one lifecycle method, doTag(). All iteration, body evaluation and other tag processing is performed within this method.

Ideally, your simple tag handler classes should extend the javax.servlet.jsp.tagext.SimpleTagSupport utility class, which implements the SimpleTag interface and provides a default implementation for the interface's methods. For example, this class provides getJspBody(), which returns the tag body passed to the handler.

Evaluation of the tag body is performed by the setJspBody() method, which is invoked by the OC4J JSP container with a JspFragment object encapsulating the body of the tag invocation. (See "Using JSP Fragments" for a discussion on JSP fragments.) The tag handler can call the invoke() method on the JspFragment to evaluate the body as many times as needed. This ability to be invoked and evaluated multiple times is a key feature of fragments.

Unlike classic tags, simple tag extensions do not rely on the PageContext of the calling JSP page's underlying servlet, but instead rely on JspContext, which PageContext now extends. JspContext provides generic services such as storing the JspWriter and keeping track of scoped attributes, while PageContext has functionality specific to serving JSPs in the context of servlets. Through these objects, a simple tag handler can retrieve the other implicit objects (request, session and application) available from a JSP page.

7.2.2.2 Using Attributes

As with classic tags, the behavior of simple tags can be controlled through attributes that correspond to properties of the tag handler class.

There are three types of attributes: simple, fragment and dynamic.

Simple attributes are first evaluated by the OC4J JSP container when the tag is invoked, before being passed to the simple tag handler. Attributes are defined within the start tag using the syntax attr="value". You can set the value as a String constant or an EL expression.

You can also define an attribute value within the body of a custom tag using the <jsp:attribute> element, a new element introduced in JSP 2.0. The following example uses <jsp:attribute> to use the output of the <my:helloWorld> custom tag to set the value of the bar property in a bean object:

<jsp:setProperty name="foo" property="bar">   <jsp:attribute name="value">      <my:helloWorld/>   </jsp:attribute></jsp:setProperty>

Fragment attributes are used to create named fragments. See "Using JSP Fragments" for an overview on JSP fragments.

As its name implies, a dynamic attribute is an attribute not specified in the tag definition. The ability of a tag to dynamically specify attributes is a new feature of JSP 2.0 that is applicable to both simple and classic tag handlers. Dynamic attributes are especially useful in tags that have a number of attributes that are all processed in a similar manner.

Tag handlers that support dynamic attributes must declare that they do so in the tag element of the TLD. For example:

<tag>
  <description>
   Tag that echoes all its attributes and body content
  </description>
  <name>echoAttributes</name>
  <tag-class>jsp2.examples.simpletag.EchoAttributesTag</tag-class>
  <body-content>empty</body-content>
  <dynamic-attributes>true</dynamic-attributes>
</tag>

7.2.3 Attribute Handling and Conversions from String Values in Tag Handlers

A tag handler class has an underlying property for each attribute of the custom tag. These properties are analogous to 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 Web 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%>"
    
    

    or:

    rtattr="${ELexpression}"
    
    

    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.

7.2.4 Using Scripting Variables in Tags

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" attr="..." attr2="..." />

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

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

The Web 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.

7.2.4.1 Scripting Variable Scopes

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

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

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

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

7.2.4.2 Variable Declaration Through TLD variable Elements

The JSP 1.1 specification mandated that use of a scripting variable for a custom tag requires the creation of a tag-extra-info (TEI) class. See "Variable Declaration Through Tag-Extra-Info Classes". The JSP1.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 hard-coded 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.

7.2.4.3 Variable Declaration Through Tag-Extra-Info Classes

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

The Web 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/1.4/docs/api/javax/servlet/jsp/tagext/package-summary.html


Note:

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

The following methods of the TagExtraInfo class are related:

  • boolean isValid(TagData data)

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

  • VariableInfo[] getVariableInfo(TagData data)

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

  • void setTagInfo(TagInfo info)

    Calling this method sets a TagInfo instance as an attribute of the tag-extra-info class. This method is typically called by the Web 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:

  • Variable name

  • 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

  • Variable scope


Important:

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

7.2.5 Access to Outer Tag Handler Instances

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

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

Consider the following JSP code example:

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

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

Tag bartag = TagSupport.findAncestorWithClass(this, BarTag.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 bar tag handler class (presumed to be BarTag in the example), as a java.lang.Class instance

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

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

7.2.6 Implementing a Tag Handler

Creating either a classic or simple tag handler implemented in Java consists of the following key steps:

  • Write and compile the tag handler class

  • Package the tag handler in a tag library

  • Define the tag in the tag library descriptor (TLD)

Several examples of simple tag handler implementations are provided with the sample applications that you can download from the Oracle Technology Network (OTN) Web site. After downloading and deploying the sample applications on OC4J, open the tag handler Java source files to see how each is implemented.

7.2.6.1 Creating the Tag Handler Class

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.

Note that a tag handler class must have a public no-arguments constructor.

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 Web 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.

7.2.6.2 Defining the Tag in the TLD

Each tag that your tag handler implements must be defined in the tag library descriptor file packaged with the tag library containing the handler class. The tag definition in the TLD fulfills two roles:

  • Defines the syntax of the tag

  • Provides the mapping between the tag and its corresponding tag handler class

The following snippet is based on the definition for the <my:shuffle> tag from shuffle.tld, the descriptor for the library containing the ShuffleSimpleTag handler class. This handler is included with the "Random Tic-Tac-Toe" sample application, which illustrates simple tag handler features. You can download this application from the Oracle Technology Network Web site.

The format for the TLD is shown in the following example. All TLD files are required to begin with a root <taglib> element that specifies the XML schema used to describe the TLD and the JSP version:

<taglib xmlns="http://java.sun.com/xml/ns/j2ee"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee web-jsptaglibrary_2_0.xsd"    version="2.0">  <tlib-version>1.0</tlib-version>  <short-name>SimpleTagLibrary</short-name>  <uri>/SimpleTagLibrary</uri>  <tag>
   ...
  </tag>
</taglib>

Next is the definition for the <my:shuffle> tag, contained within a <tag> element:

<tag>  <name>shuffle</name>   <tag-class>oracle.otnsamples.jsp20.simpletag.ShuffleSimpleTag</tag-class>   <body-content>empty</body-content>   <attribute>     <name>fragment1</name>     <required>true</required>     <fragment>true</fragment>   </attribute>
   <attribute>     <name>fragment2</name>     <required>true</required>     <fragment>true</fragment>   </attribute>   <attribute>     <name>fragment3</name>     <required>true</required>     <fragment>true</fragment>   </attribute>
</tag>

The subelements of a <tag> element define the 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 "Working with Tag Handlers" for information about tag handler classes.

  • The <body-content> subelement indicates how the tag body (if any) should be processed.

  • Each <variable> subelement (if any), with its further subelements, defines a scripting variable. See "Using Scripting Variables in Tags" 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 a parameter that you can pass in when you use the custom tag - in this example, a named fragment. 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 (9.0.4), the OC4J JSP container ignores the <type> element. It is for informational use only, for anyone examining the TLD file. Additionally, note the following:
  • For literal attribute values, where <rtexprvalue> specifies false, the <type> value (if any) should always be java.lang.String.

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


7.2.6.3 Declaring the Tag in a JSP Page

The tag library containing the tag handler is referenced in the file using a <taglib> directive. Note the prefix <my:...> which indicates that any tag including this prefix is defined in the corresponding TLD.

<%@ taglib uri="/WEB-INF/shuffle.tld" prefix="my" %>

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 Multiple Tag Libraries and TLD Files in a JAR File" which describes a scenario for packaging tag libraries to be shared by multiple Web applications.

7.2.6.4 Using the Tag in a JSP

The <my:shuffle> tag is used in the TictactoeManual.jsp page, which draws a "tic-tac-toe" table of three rows and three columns. Each column has a tile of a particular color, achieved by calling the <my:tile> tag with three different colored tiles, or images. The <my:shuffle> tag is used to wrap these calls. The tag handler randomly executes the three tile fragments, causing the colored tiles within each row to be shuffled each time the page is loaded.

<my:shuffle>   <jsp:attribute name="fragment1">
     <tr>
       <my:shuffle>
         <jsp:attribute name="fragment1">
           <my:tile imageVal="../images/blue_plain.gif" />
          </jsp:attribute>
          <jsp:attribute name="fragment2">
            <my:tile imageVal="../images/yellow_plain.gif" />
       </jsp:attribute>
       <jsp:attribute name="fragment3">
         <my:tile imageVal="../images/pink_plain.gif" />
       </jsp:attribute>
         </my:shuffle>
      </tr>
    </jsp:attribute>
      ...
</my:shuffle>

7.3 OC4J Tag Handler Features

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

7.3.1 Disabling or Enabling Tag Handler Reuse (Tag Pooling)

To improve performance, you can specify that tag instances be reused within each JSP page. This functionality is often referred to as tag pooling.

As of Oracle Containers for J2EE Release 3 (10.1.3), a compile-time tag pooling model is supported. 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).

Tag pooling in the OC4J JSP container is configured using the tags_reuse_default parameter. See "Summary of JSP Configuration Parameters" for further information on setting this parameter.


Note:

The runtime tag pooling model - previously the default mechanism used - is deprecated in Oracle Containers for J2EE Release 3 (10.1.3).

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

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

  • Set the tags_reuse_default configuration parameter to compiletime.

Or:

  • Set the tags_reuse_default configuration parameter to compiletime_with_release.

A compiletime_with_release setting results in the tag handler release() method being called between uses of the same tag handler within the same page. This method releases state information, with details according to the tag handler implementation.

If the tag handler is coded in such a way as to assume a release of state information between tag usages, for example, then a compiletime_with_release setting would be appropriate. If you are unsure about the implementation of the tag handler and about which compile-time setting to use, you might consider experimentation.


Notes:

  • Remember to retranslate your JSP pages when switching between the compiletime, compiletime_with_release or runtime models for tag handler reuse.

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


7.3.1.2 When Can the Compile-Time Tag Pooling Model Be Used?

In conformance with the JSP 2.0 specification, a tag instance can only be reused when the set of attributes defined for the tag is identical from usage to usage. This restriction is applicable to both the compiletime and compiletime-with-release tag pooling models.

The following example uses the tags from the JSTL core library to illustrate tag instance reuse.

<%@ taglib uri='http://java.sun.com/jstl/core' prefix='c' %>

// New instance of c:forEach tag is created.
// Note the inclusion of the "var" attribute.
<c:forEach var='item' begin='2' end='10'>

// New instance of c:out tag is created.
<c:out value="foo"/>

</c:forEach>

<%out.println("****");%>

// The first c:forEach tag instance cannot be reused, since the "var"
// attribute does not exist. A new tag instance is therefore created.
<c:forEach begin='1' end='10'>

// The existing c:out tag instance is reused, as
// the set of attributes is identical in both usages.
<c:out value="bar"/>

7.3.1.3 Code Pattern for the compiletime Tag Pooling Model

The following illustrates the code pattern for the default compiletime model for tag pooling.

      try {
        tag01.doStartTag();
        ...
        tag01.doEndTag();
        // reuse tag01 without calling release()
        tag01.doStartTag();
        ...
        tag01.doEndTag();
      }
      catch (Throwable e) {
        tag01.release();
      }

7.3.1.4 Code Pattern for the compiletime-with-release Tag Pooling Model

The following illustrates the code pattern for the compiletime-with-release option, which calls the release() method on the tag handler object between uses of the same tag handler within the same JSP.

      try {
        tag01.setPageContext(pageContext);
        tag01.doStartTag();
        ...
        tag01.doEndTag();
        tag01.release();
        // reuse tag01 with calling release()
        tag01.doStartTag();
        ...        tag01.doEndTag();
        tag01.release();
      }
      catch (Throwable e) {
        tag01.release();
      }

7.3.2 Tag Handler Code Generation

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

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

7.4 Working with Tag Files

The following sections provide an overview and understanding of tag files:

7.4.1 What Are Tag Files?

Introduced with JSP 2.0, tag files allow JSP authors to create custom tag libraries completely using JSP syntax, without requiring any knowledge of Java. In fact, writing a tag file is just like writing a JSP, with a few differences. Because of their ease of implementation, tag files offer an attractive alternative to traditional custom tag handlers.

The source for a tag file is simply a text file containing a reusable fragment of JSP code. Valid content that can be used in a tag file include:

  • Standard JSP actions (such as <jsp:useBean>)

  • Custom tags

  • JSTL tags

  • EL expressions or functions

  • Template text

Unlike traditional custom tags, tag files do not require a corresponding tag handler class; instead each file is translated and compiled into a simple tag handler by the OC4J JSP container. Tag files effectively remove the need for Java programming, opening tag library creation to JSP authors who do not possess a strong working knowledge of Java.

Standard JSP directives are used in a tag file to provide processing instructions, just as in a JSP page. The one exception is the page directive, which cannot be used. Instead, tag files use the tag directive, which includes attributes specific to tag file processing.

Additional directives, such as attribute and variable, can only be used in tag files. "Using Attributes in Tag Files" and "Exposing Data through Variables in Tag Files" for details.

7.4.2 Tag Body Processing

How the body of a custom tag is processed is defined in the body-content attribute of the corresponding tag file's tag directive. The default value is scriptless, indicating that any of the JSP or static text elements listed above can be used in the tag body - although as the value infers, Java scripting elements are not allowed. Tags that do not accept a tag body should be declared as empty, as shown below:

<%@ tag body-content="empty" %>

The tag's body is evaluated by the <jsp:doBody> standard action, which can only be used within tag files. Any dynamic JSP elements in the tag body are called, and the output they produce is mixed with template text in the body in the evaluation result.

The result is saved in a variable, which can be named using either the var or varReader attributes of the <jsp:doBody> tag. The var attribute captures the result as a String and should be sufficient for most usage scenarios.

The varReader attribute is used to capture the result as a java.io.Reader object, which may be more efficient when combined with a standard or custom tag, or with an EL function that reads its input from a Reader. If no variable is specified, the output is sent to the implicit JspWriter object.

As noted in the discussion of the SimpleTag interface, the body of the tag invocation is translated to a JspFragment object, which is then passed to the tag handler for processing. In this case, the value of text is displayed in bold and italic fonts in a Web browser. Fragments are very useful in the context of tag files, as discussed in "Using Attributes in Tag Files" below.

7.4.3 Using Attributes in Tag Files

Attributes are declared directly within tag files using attribute directives. In the example below, the required attribute is set to true, meaning that the page author must specify a value for this attribute when a tag element body passed in, or an error will be returned. The default value is false.

<%@ attribute name="category" required="true" %>

As with classic and simple tag handlers, it is also possible to use undeclared dynamic attributes in a tag file. This is done by setting the dynamic-attributes attribute of the tag directive to the name of a Map containing the names and values of the dynamic attributes passed during tag invocation. The Map must contain each dynamic attribute name and value as a key/value pair.

<%@ tag body-content="scriptless" dynamic-attributes="dynattrs" %> 

7.4.4 Exposing Data through Variables in Tag Files

Variables are also declared directly within the tag file using the variable directive, which is analogous to the <variable> element used to declare variables used by a tag handler in a TLD. The name-given attribute specifies the variable's name and the variable-class attribute defines its type.

<%@ variable name-given="current" variable-class="java.lang.Object" scope="NESTED" %>

As with tag handlers, the variable directive's scope attribute accepts one of three values, which control where the calling JSP sees the variable: AT_BEGIN, AT_END, or NESTED.

Tag files have access to a local page scope, which is distinct from the page scope of the calling JSP. The use of different scopes prevents confusion between the calling page and the tag file if they use the same names for page scope variables. In many cases, you may want to allow variable names to be specified by the calling JSP using an attribute supplied in a tag body, rather than hard-coding names in the tag file.

<%@ variable name-from-attribute="var" alias="current" variable-class="java.lang.Object" scope="NESTED" %>

Here, the name-from-attribute and alias attributes are used instead of the name-given attribute used in the previous example. The name-from-attribute value is the name of the tag attribute providing the variable name.

The alias attribute value declares the name of the tag file's local page scope variable, which the OC4J JSP container copies to the calling JSP's page scope. This attribute is needed because the page author can assign any name for the variable in a custom tag, but a fixed name - the alias - must be used when developing the tag file.

7.4.5 Using JSP Fragments

A JSP fragment can be thought of as a template used to produce customized content. Introduced with JSP 2.0, JSP fragments are a new option for use with simple tag extensions, and as such are relevant for both tag files simple tag handlers. However, creating a fragment is typically done within the context of a tag file.

Like a tag file, a fragment is an encapsulation of dynamic JSP elements - such as standard JSP action tags, custom tags or EL expressions - and optionally static template text that is passed to a simple tag handler through a tag invocation.

A fragment can be invoked and evaluated by the tag handler zero or more times, as needed. Because the JSP elements within the fragment have access to the current values of all scoped variables, the result will typically be different from invocation to invocation. These qualities make fragments ideal for:

  • Displaying conditional data or template text

  • Displaying a set of data in an iteration

7.4.5.1 Creating a JSP Fragment

Creating a named fragment for use in a tag file can be thought of as a two step process: You must declare the fragment within the tag file, then define its body within a <jsp:attribute> standard action tag inside the body of a custom tag.

You declare the fragment in the tag file using an attribute directive. Setting the directive's fragment attribute to true will cause the fragment to be evaluated by the tag handler. The default setting of false forces the attribute to be evaluated by the OC4J JSP container before being passed to the tag handler; hence the fragment's ability to be evaluated "zero or more times".

<%@ attribute name="frag1" fragment="true" %><%@ attribute name="frag2" fragment="true" %>

You then define the associated logic within the tag file using JSP syntax. The following snippet from a tag file illustrates conditional logic implemented using JSTL tags. If the test evaluates true, frag1 is invoked:

<c:when test="${empRow[2] >= 10000}">   <c:set var="name" value="${empRow[0]}"/>   <c:set var="phone" value="${empRow[1]}"/>   <c:set var="salary" value="${empRow[2]}"/>   <jsp:invoke fragment="frag1"/></c:when> 

The fragment is invoked by name using the <jsp:invoke> standard action tag within the tag file. Like <jsp:doBody>, this action can only be used within tag files. The scoped variables within the tag body - in this case EL constructs - are set by the tag file, allowing the tag file code to customize the fragment each time it is invoked.

The fragment content, which as noted previously can consist of JSP elements and static HTML, is defined within the body of a <jsp:attribute> standard action tag within the body of a custom tag.

<tags:EmpDetails deptNum="80">
 <jsp:attribute name="fragment1"> 
   <tr bgcolor="#FFFF99" align="center"> 
    <td><font color="#CC0033">${name}</font></td>
    <td><font color="#CC0033">${phone}</font></td>
    <td><font color="#CC0033">${salary}</font></td>
   </tr>
  </jsp:attribute> 
</tags:EmpDetails>

7.4.5.2 A Tag File Example

The following is a simple example illustrating the use of the var attribute to store the result of a tag body evaluation.

The sample doBodyVarTest.tag file defines a variable named text that will store the result of evaluating the body of the <tags:doBodyVarTest> tag in Example.jsp. It also defines two fragment attributes—frag1 and frag2—that will store the result of an EL variable evaluation.

When a tag file is executed, the Web container passes it two types of fragments: fragment attributes and the tag body. Within the tag file, the <jsp:invoke> element is used to evaluate a fragment attribute, while the <jsp:doBody> element is used to evaluate a tag file body. The result of evaluating either type of fragment is sent to the response or is stored in an EL variable for later manipulation.

<%@ attribute name="frag1" required="true" fragment="true" %>
<%@ attribute name="frag2" required="true" fragment="true" %>
<%@ variable name-given="text" scope="NESTED" %>
 <jsp:doBody var="text" />
  <TABLE border="0">
   <TR>
    <TD>
     <b><jsp:invoke fragment="frag1"/></b>
    </TD>
   </TR>
   <TR>
    <TD>
     <i><jsp:invoke fragment="frag2"/></i>
    </TD>
   </TR>
  </TABLE>

The Example.jsp code creates an instance of the doBodyVarTest tag. Note the <jsp:body> tag, which contains a string that will be set by the tag handler into the text variable. The <jsp:body> tag is used to explicitly specify the body of a simple tag, and is the only option for specifying a tag body when one or more <jsp:attribute> elements appear in the body of a tag invocation.

<%@ taglib tagdir="/WEB-INF/tags" prefix="tags" %>

<html>
 <body>
  <tags:doBodyVarTest>
   <jsp:attribute name="frag1">
    ${text}
   </jsp:attribute>
   <jsp:attribute name="frag2">
    ${text}
   </jsp:attribute>
   <jsp:body>
    Have a great day!
   </jsp:body>
  </tags:doBodyVarTest>
 </body>
</html>

7.4.6 Implementing a Tag File

The process for implementing a tag library as tag files is straightforward: You need only to write the tag files as outlined in this chapter.

7.4.6.1 Creating the Tag File

As noted earlier in this chapter, writing a tag file is very similar to writing a JSP. See "What Are Tag Files?" for a summary of elements that can be included in a tag file.

Be aware that tag files in your JAR file remain as uncompiled tag files, meaning that your code can be viewed by anyone with a text editor.

7.4.6.2 Packaging Tag Files

Tag files can be deployed in one of two ways:

  • Drop the tags directly into a /WEB-INF/tags directory within an application's directory structure

    When deployed in this manner, tag files do not require a tag library descriptor. However, the tags will only be accessible to the single application, unless you copy the tags to the /WEB-INF/tags directory for each application.

  • They can be packaged in a JAR file

    Packaging tag files in this manner requires a TLD. Any tag files within the JAR that are not defined in the TLD are ignored by the OC4J JSP container.

When packaged in a JAR, tag files are added under the /META-INF/tags within the JAR. The JAR will then be installed in the /WEB-INF/lib/ directory of a Web application.

Each tag file in the JAR is defined in the TLD within a <tag-file> element, as opposed to the <tag> element used to define classic or simple tag handlers. Each <tag-file> element takes two sub-elements:

  • The <name> element defines the tag name and must be unique

  • The <path> element specifies the full path of the tag file and must therefore begin with /META-INF/tags

The example below shows a TLD defining two tag files packaged in a JAR for distribution:

<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee web-jsptaglibrary_2_0.xsd"
   version="2.0">
  <tlib-version>1.0</tlib-version>
  <short-name>MyTagFiles</short-name
  <uri>/MyTagFiles</uri>
  <description>JSP 2.0 tag files</description> 
  <tlib-version>1.0</tlib-version> 
  <short-name>My Tag Files</short-name> 
  <tag-file> 
    <name>EmpDetails</name> 
    <path>/META-INF/tags/mytags/EmpDetails.tag</path> 
  </tag-file> 
  <tag-file>
    <name>ProductDetails</name>
    <path>/META-INF/tags/mytags/ProductDetails.tag</path>
  </tag-file>
</taglib

7.4.6.3 Declaring the Tag File in a JSP

A JSP page imports a tag library implemented with tag files using the taglib directive. The tag library prefix is specified using the prefix attribute. However, the other attributes included vary depending on how the tag files are deployed.

If the tag files are not packaged in a JAR, the value of the tagdir attribute must be set to the context-relative path to the directory that contains the tag files.

<%@ taglib tagdir="/WEB-INF/tags/mytags" prefix="mytags" %>

If the tag files are packaged in a JAR, the uri attribute is used, and is set to the content of the <uri> element in the TLD.

<%@ taglib uri="/MyTagFiles" prefix="mytags" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

7.5 Sharing Tag Libraries Across Web Applications

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

7.5.1 Packaging Multiple Tag Libraries and TLD Files in a JAR File

The JSP specification allows the packaging of multiple tag libraries, and the TLD files that define them, in a single JAR file.

This section presents an example of multiple tag libraries packaged in a single JAR file. The JAR file includes tag handler classes, tag-library-validator (TLV) classes, and TLD files for multiple libraries.

The following lists the contents and structure of the JAR file. Note that in a JAR file with multiple TLD files, the TLD files must be located under the /META-INF directory or a subdirectory.

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

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 "Specifying Well-Known Tag Library Locations". 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.

7.5.1.1 Key TLD File Entries

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; however, it must follow the XML namespace convention.I t 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.

The basic.tld file includes the following:

<taglib>

  <tlib-version>1.0</tlib-version>
  <jsp-version>2.0</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>

  <tlib-version>1.0</tlib-version>
  <jsp-version>2.0</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

7.5.1.2 Key web.xml Deployment Descriptor Entries

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.

The <taglib> element can include two subelements:

  • <taglib-uri>

    Contains the shortcut URI that will be used as the value of the uri attribute in the taglib directive in JSP pages that use the tag.

  • <taglib-location>

    Contains the unique identifier for the 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.

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 Well-Known Tag Library Locations" 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 Multiple Tag Libraries and TLD Files in a JAR File" for related information.

<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>

7.5.1.3 JSP Page taglib Directives for Multiple-Library Example

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

The page basic1.jsp includes the following directive:

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

The page exampletag.jsp includes the following directive:

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

The page xmlview.jsp includes the following directive:

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

7.5.2 Specifying Well-Known Tag Library Locations

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

The default well-known tag library location is the ORACLE_HOME/j2ee/home/jsp/lib/taglib/ directory. A tag library installed in this location will be available by default to all Web applications deployed to the OC4J instance.

You can also define additional shared tag library locations, and install tag library JAR files to be shared across applications in these directories. Defining a well-known tag library location is a two-step process:

  1. Define each directory in the jsp-taglib-locations attribute of the of the <orion-web-app> element in the ORACLE_HOME/j2ee/home/config/global-web-application.xml file. Separate each location with a semicolon.

  2. Add a <library> element for each directory to ORACLE_HOME/j2ee/home/config/application.xml, the configuration file for the default application. Set the path attribute to the directory containing the tag library JAR file.


Important:

The ability to specify and utilize multiple shared tag library locations is determined by the value of the jsp-cache-tlds attribute of the <orion-web-app> element. See Table 7-1, "TLD Caching Parameters" for details.

7.5.3 Enabling the TLD Caching Feature

As part of its support for sharing tag libraries, OC4J provides a persistent caching feature for TLD files. This includes 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 turn it off, however, if either of the following circumstances are true:

  • Your application does not use tag libraries.

  • You have pre-translated the JSP pages and none of the TLD files use <listener> elements for tag library event listeners.

TLD caching is enabled or disabled through the jsp-cache-tlds attribute of the <orion-web-app> element.

  • At the global level, TLD caching is set through this attribute in the global-web-application.xml file, the Web configuration file for the global Web application. The value set in this file is the default inherited by all other Web applications deployed to the OC4J instance.

  • At the application level, caching is set in the application-specific orion-web.xml file. The setting in this file overrides the default setting in global-web-application.xml.

The following table summarizes the values for the jsp-cache-tlds attribute.

Table 7-1 TLD Caching Parameters

Value of jsp-cache- tlds Value set in global-web-application.xml

standard

TLD caching is enabled. This is the default setting at the global and application level.

Add tag library JARs to the default well-known tag library location, which is ORACLE_HOME/j2ee/home/jsp/lib/taglib. The tag libraries will be available to all Web applications.

Note that TLD (*.tld) files must be placed in the /WEB-INF directory. Do NOT put TLD files in the /classes or /lib subdirectories.

on

TLD caching is enabled.

Add JAR files containing tag libraries to one of the following:

  • The default well-known tag library location, which is ORACLE_HOME/j2ee/home/jsp/lib/taglib.

  • An additional location specified in the jsp-taglib-locations attribute of the <orion-web-app> element in global-web-application.xml.

    See "Specifying Well-Known Tag Library Locations" for details on specifying additional locations.

off

TLD caching is disabled.

Add tag library JARs to the default well-known tag library location only, which is ORACLE_HOME/j2ee/home/jsp/lib/taglib.

A different location can be specified as the value of the well_known_taglib_loc initialization parameter in ORACLE_HOME/j2ee/home/config/global-web-application.xml.

Initialization parameters are specified within <init-param> subelements of <servlet>jsp</servlet> notation in this file. See "Setting JSP Parameters in the XML Configuration Files" for details.



Important:

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

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


7.5.3.1 Understanding the TLD Cache Features and Files

For any application that uses TLD caching, whether it is enabled at the global or 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. If the jsp-cache-tlds attribute of the <orion-web-app> element is set to standard, TLDs must NOT be placed in either /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.

  • 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:

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

  • 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. 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.

    If the jsp-cache-tlds attribute of the <orion-web-app> element is set to standard, TLDs must NOT be placed in either /WEB-INF/lib or /WEB-INF/classes.

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


    Notes:

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

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

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