SimpleTAG



Classes and interfaces for the definition of JavaServer Pages Tag Libraries.

The SimpleTaginterface provides a simple doTagmethod, which is called once and only once for any given tag invocation. All tag logic, iteration, body evaluations, etc. Are to be performed in this single method. Thus, simple tag handlers. SimpleTAG-Tools is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with SimpleTAG-Tools.

Custom actions can be used by JSP authors and authoring tools tosimplify writing JSP pages. A custom action can be either an emptyor a non-empty action.

An empty tag has no body. There are two equivalent syntaxes, onewith separate start and end tags, and one where the start andend tags are combined. The two following examples are identical:

A non-empty tag has a start tag, a body, and an end tag. Aprototypical example is of the form:

The JavaServer Pages(tm) (JSP) specification provides a portablemechanism for the description of tag libraries.

A JSP tag library contains

  • A Tag Library Descriptor
  • A number of Tag Files or Tag handler classes defining request-time behavior
  • Additional classes and resources used at runtime
  • Possibly some additional classes to provide extra translation information

This API is described in the following sections:

1. Classic Tag Handlers

This section introduces the notion of a tag handler and describes theclassic types of tag handler.

JSP 2.0 introduces a new type of Tag Handler called a Simple Tag Handler, which is described in a later section. The protocol for Simple Tag handlers is much more straightforward.

Simpletag gps

Tag Handler

A tag handler is a run-time, container-managed object thatevaluates custom actions during the execution of a JSP page. A taghandler supports a protocol that allows the JSP container to providegood integration of the server-side actions within a JSP page.

A tag handler is created initially using a zero argumentconstructor on its corresponding class; the methodjava.beans.Beans.instantiate() is not used.

A tag handler has some properties that are exposed to the page asattributes on an action; these properties are managed by the JSPcontainer (via generated code). The setter methods used to setthe properties are discovered using the JavaBeans introspectormachinery.

The protocol supported by a tag handler provides for passing ofparameters, the evaluation and reevaluation of the body of the action,and for getting access to objects and other tag handlers in theJSP page.

A tag handler instance is responsible for processing one requestat a time. It is the responsability of the JSP container to enforcethis.

Additional translation time information associated with the actionindicates the name of any scripting variables it may introduce, theirtypes and their scope. At specific moments, the JSP container willautomatically synchronize the PageContext information with variablesin the scripting language so they can be made available directlythrough the scripting elements.

Properties

A tag handler has some properties. All tag handlers have apageContext property for the JSP page where the tag islocated, and a parent property for the tag handler to theclosest enclosing action. Specific tag handler classes may haveadditional properties.

All attributes of a custom action must be JavaBeans componentproperties, although some properties may not be exposed as attributes.The attributes that are visible to the JSP translator are exactlythose listed in the Tag Library Descriptor (TLD).

All properties of a tag handler instance exposed as attributeswill be initialized by the container using the appropriate settermethods before the instance can be used to perform the action methods.It is the responsibility of the JSP container to invoke theappropriate setter methods to initialize these properties. It is theresponsability of user code, be it scriptlets, JavaBeans code, or codeinside custom tags, to not invoke these setter methods, as doingotherwise would interfere with the container knowledge.

The setter methods that should be used when assigning a value toan attribute of a custom action are determined by using the JavaBeansintrospector on the tag handler class, then use the setter methodassociated with the property that has the same name as the attributein question. An implication (unclear in the JavaBeans specification)is that there is only one setter per property.

Unspecified attributes/properties should not be set (using asetter method).

SimpleTAG

Once properly set, all properties are expected to be persistent,so that if the JSP container ascertains that a property has alreadybeen set on a given tag handler instance, it must not set itagain.

The JSP container may reuse classic tag handler instances for multipleoccurrences of the corresponding custom action, in the same page or indifferent pages, but only if the same set of attributes are used for alloccurrences. If a tag handler is used for more than one occurence, thecontainer must reset all attributes where the values differ between thecustom action occurrences. Attributes with the same value in alloccurrences must not be reset. If an attribute value is set as arequest-time attribute value (using a scripting or an EL expression),the container must reset the attribute between all reuses of the taghandler instance. To prevent confusion, a tag handler with an empty bodymust not reuse any previous tag handler with a non-empty body.

User code can access property information and access and modifytag handler internal state starting with the first action method (doStartTag)up until the last action method (doEndTag or doFinally for tag handlersimplementing TryCatchFinally).

Tag Handler as a Container-Managed Object

Since a tag handler is a container managed object, the containerneeds to maintain its references; specifically, user code should notkeep references to a tag handler except between the start of the firstaction method (doStartTag()) and the end of the last action method(doEndTag() or doFinally() for those tags that implement TryCatchFinally).

The restrictions on references to tag handler objects andon modifying attribute properties gives the JSP container substantialfreedom in effectively managing tag handler objects to achieve differentgoals. For example, a container may implementing different pooling strategiesto minimize creation cost, or may hoist setting of properties to reducecost when a tag handler is inside another iterative tag.

Conversions

A tag handler implements an action; the JSP container must followthe type conversions described in Section 2.13.2 when assigning valuesto the attributes of an action.

Empty and Non-Empty Actions

An empty action has no body; it may use one of two syntaxes: either<foo/> or <foo></foo>. Since empty actions have nobody the methods related to body manipulation are not invoked.There is a mechanism in the Tag Library Descriptor to indicatethat a tag can only be used to write empty actions; when used,non-empty actions using that tag will produce a translation error.

A non-empty action has a body.

The Tag Interface

A Tag handler that does not want to process its body can implementjust the Tag interface. A tag handler may not want to process itsbody because it is an empty tag or because the body is just tobe 'passed through'.

The Tag interface includes methods to provide page contextinformation to the Tag Handler instance, methods to handle thelife-cycle of tag handlers, and two main methods for performingactions on a tag: doStartTag() anddoEndTag(). The method doStartTag() isinvoked when encountering the start tag and its return value indicateswhether the body (if there is any) should be skipped, or evaluated andpassed through to the current response stream. The methoddoEndTag() is invoked when encountering the end tag; itsreturn value indicates whether the rest of the page should continue tobe evaluated or not.

If an exception is encountered during the evaluation of thebody of a tag, its doEndTag method will not be evaluated. See theTryCatchFinally tag for methods that are guaranteed to be evaluated.

The IterationTag Interface

Simple tag games

The IterationTag interface is used to repeatedly reevaluatethe body of a custom action. The interface has one method:doAfterBody() which is invoked after each evaluationof the body to determine whether to reevaluate or not.

Reevaluation is requested with the value 2, which in JSP 1.1 isdefined to be BodyTag.EVAL_BODY_TAG. That constant value is stillkept in JSP 1.2 (for full backwards compatibility) but, to improveclarity, a new name is also available: IterationTag.EVAL_BODY_AGAIN.To stop iterating, the returned value should be 0, which isTag.SKIP_BODY.

The JspIdConsumer Interface

Simple tagalog wordsThis interface indicates to the container that a tag handler wishes to be provided with a compiler generated ID that is uniquewithin the page.

The TagSupport Base Class

The TagSupport class is a base class that can be used whenimplementing the Tag or IterationTag interfaces.

2. Tag Handlers that want Access to their Body Content

The evaluation of a body is delivered into a BodyContentobject. This is then made available to tag handlers that implementthe BodyTag interface. The BodyTagSupportclass provides a useful base class to simplify writing these handlers.

If a Tag handler wants to have access to the content of its bodythen it must implement the BodyTag interface.This interface extends IterationTag, provides two additional methodssetBodyContent(BodyContent) anddoInitBody()and refers to an object of type BodyContent.

A BodyContent is a subclass of JspWriter that has afew additional methods to convert its contents into a String, insertthe contents into another JspWriter, to get a Reader into itscontents, and to clear the contents. Its semantics also assure thatbuffer size will never be exceeded.

The JSP page implementation will create a BodyContent if thedoStartTag() method returns a EVAL_BODY_BUFFERED. This object will bepassed to doInitBody(); then the body of the tag will be evaluated,and during that evaluation out will be bound to theBodyContent just passed to the BodyTag handler. ThendoAfterBody() will be evaluated. If that method returns SKIP_BODY, nomore evaluations of the body will be done; if the method returnsEVAL_BODY_AGAIN, then the body will be evaluated, and doAfterBody() willbe invoked again.

The content of a BodyContent instance remains available until afterthe invocation of its associated doEndTag() method.

A common use of the BodyContent is to extract its contents into aString and then use the String as a value for some operation. Anothercommon use is to take its contents and push it into the out Streamthat was valid when the start tag was encountered (that is availablefrom the PageContext object passed to the handler in setPageContext).

3. Dynamic Attributes

Any tag handler can optionally extend the DynamicAttributesinterface to indicate that it supports dynamic attributes. In addition to implementing the DynamicAttributes interface, tag handlers that support dynamic attributes must declare that they do so in the Tag Library Descriptor.

The TLD is what ultimately determines whether a tag handler accepts dynamic attributes or not. If a tag handler declares that it supports dynamic attributes in the TLD but it does not implement the DynamicAttributes interface, the tag handler must be considered invalid by the container.

If the dynamic-attributes element for a tag being invoked contains the value 'true', the following requirements apply:

  • For each attribute specified in the tag invocation that does not have a corresponding attribute element in the TLD for this tag, a call must be made to setDynamicAttribute(), passing in the namespace of the attribute (or null if the attribute does not have a namespace or prefix), the name of the attribute without the namespace prefix, and the final value of the attribute.
  • Dynamic attributes must be considered to accept request-time expression values as well as deferred expressions.
  • Dynamic attributes must be treated as though they were of type java.lang.Object. If a ValueExpression is passed as a dynamic attribute, the default value for the expected return type is assumed to be java.lang.Object. If a MethodExpression is passed as a dynamic attribute, the default method signature is assumed to be void method().
  • Note that passing a String literal as a dynamic attribute will never be considered as a deferred expression.
  • The JSP container must recognize dynamic attributes that are passed to the tag handler using the <jsp:attribute> standard action.
  • If the setDynamicAttribute() method throws JspException, the doStartTag() or doTag() method is not invoked for this tag, and the exception must be treated in the same manner as if it came from a regular attribute setter method.
  • For a JSP document in either standard or XML syntax, If a dynamic attribute has a prefix that doesn't map to a namespace, a translation error must occur. In standard syntax, only namespaces defined using taglib directives are recognized.

In the following example, assume attributes a and b are declared using the attribute element in the TLD, attributes d1 and d2 are not declared, and the dynamic-attributes element is set to 'true'. The attributes are set using the calls:

  • setA( '1' ),
  • setDynamicAttribute( null, 'd1', '2' ),
  • setDynamicAttribute( 'http://www.foo.com/jsp/taglib/mytag.tld', 'd2', '3' ),
  • setB( '4' ),
  • setDynamicAttribute( null, 'd3', '5' ), and
  • setDynamicAttribute( 'http://www.foo.com/jsp/taglib/mytag.tld', 'd4', '6' ).

4. Annotated Tag Handler Management Example

Below is a somewhat complete example of the way one JSP containercould choose to do some tag handler management. There are manyother strategies that could be followed, with different pay offs.

In this example, we are assuming thatx:iterate is an iterative tag, while x:doit and x:foobar are simpletag. We will also assume that x:iterate and x:foobar implement theTryCatchFinally interface, while x:doit does not.

The particular code shown below assumes there is some pool of taghandlers that are managed (details not described, although poolmanaging is simpler when there are no optional attributes), andattemps to reuse tag handlers if possible. The code also 'hoists' setting of properties to reduce the cost when appropriate, e.g. insidean iteration.

5. Cooperating Actions

Actions can cooperate with other actions and with scripting codein a number of ways.

PageContext

Often two actions in a JSP page will want to cooperate,perhaps by one action creating some server-side object thatneeds to be accessed by another.One mechanism for doing this is by giving the object a namewithin the JSP page; the first action will create the objectand associate the name to it while the second actionwill use the name to retrieve the object.

For example, in the following JSP segment the fooaction might create a server-side object and give it thename 'myObject'. Then the baraction might access that server-side object and take some action.

In a JSP implementation, the mapping 'name'->value is kept by theimplicit objectpageContext.This object is passed around through the Tag handler instancesso it can be used to communicate information: all it is neededis to know the name under which the information is stored intothe pageContext.

SimpleTAG

The Runtime Stack

An alternative to explicit communication of information througha named object is implicit coordination based on syntactic scoping.

For example, in the following JSP segment the fooaction might create a server-side object;later the nested bar action might access that server-side object.The object is not named within the pageContext:it is found because the specific foo element is theclosest enclosing instance of a known element type.

This functionality is supported through theTagSupport.findAncestorWithClass(Tag, Class),which uses a reference to parent tag kept by each Tag instance,which effectively provides a run-time execution stack.

6. Simple Tag Handlers

This section presents the API to implement Simple Tag Handlers. Simple Tag Handlers present a much simpler invocation protocol than do Classic Tag Handlers.

The Tag Library Descriptor maps tag library declarations to their physical underlying implementations. A Simple Tag Handler is represented in Java by a class which implements the SimpleTag interface.

Unlike classic tag handlers, the SimpleTag interface does not extend Tag. Instead of supporting doStartTag() and doEndTag(), the SimpleTag interface provides a simple doTag() method, which is called once and only once for any given tag invocation. All tag logic, iteration, body evaluations, etc. are to be performed in this single method. Thus, simple tag handlers have the equivalent power of BodyTag, but with a much simpler lifecycle and interface.

To support body content, the setJspBody() method is provided. The container invokes the setJspBody() method with a JspFragment object encapsulating the body of the tag. The tag handler implementation can call invoke() on that fragment to evaluate the body. TheSimpleTagSupport convenience class provides getJspBody() and other useful methods to make this even easier.

Lifecycle of Simple Tag Handlers

This section describes the lifecycle of simple tag handlers, from creation to invocation. For all semantics left unspecified by this section, the semantics default to that of a classic tag handler.

When a simple tag handler is invoked, the following steps occur (in order):

  1. Simple tag handlers are created initially using a zero argument constructor on the corresponding implementation class. Unlike classic tag handlers, this instance must never be pooled by the container. A new instance must be created for each tag invocation.
  2. The setJspContext() and setParent() methods are invoked on the tag handler. The setParent() method need not be called if the value being passed in is null. In the case of tag files, a JspContext wrapper is created so that the tag file can appear to have its own page scope. Calling getJspContext() must return the wrapped JspContext.
  3. The attributes specified as XML element attributes (if any) are evaluated next, in the order in which they are declared, according to the following rules (referred to as 'evaluating an XML element attribute' below). The appropriate bean property setter is invoked for each. If no setter is defined for the specified attribute but the tag accepts dynamic attributes, the setDynamicAttribute() method is invoked as the setter.
    • If the attribute is a scripting expression (e.g. '<%= 1+1 %>' in JSP syntax, or '%= 1+1 %' in XML syntax), the expression is evaluated, and the result is converted as per the rules in 'Type Conversions', and passed to the setter.
    • Otherwise, if the attribute contains any Expression Language expressions (e.g. 'Hello ${name}'), the expression is evaluated, and the result is converted and passed to the setter.
    • Otherwise, the attribute value is taken verbatim, converted, and passed to the setter.
  4. The value for each <jsp:attribute> element is evaluated, and the corresponding bean property setter methods are invoked for each, in the order in which they appear in the body of the tag. If no setter is defined for the specified attribute but the tag accepts dynamic attributes, the setDynamicAttribute() method is invoked as the setter.
    • Otherwise, if the attribute is not of type JspFragment, the container evaluates the body of the <jsp:attribute> element. This evaluation can be done in a container-specific manner. Container implementors should note that in the process of evaluating this body, other custom actions may be invoked.
    • Otherwise, if the attribute is of type JspFragment, an instance of a JspFragment object is created and passed in.
  5. The value for the body of the tag is determined, and if a body exists the setJspBody() method is called on the tag handler.
    • If the tag is declared to have a body-content of 'empty' or no body or an empty body is passed for this invocation, then setJspBody() is not called.
    • Otherwise, the body of the tag is either the body of the <jsp:body> element, or the body of the custom action invocation if no <jsp:body> or <jsp:attribute> elements are present. In this case, an instance of a JspFragment object is created as per the lifecycle described in the JSP Fragments section and it is passed to the setter. If the tag is declared to have a body-content of 'tagdependent' the JspFragment must echo the body's contents verbatim. Otherwise, if the tag is declared to have a body-content of type 'scriptless', the JspFragment must evaluate the body's contents as a JSP scriptless body.
  6. The doTag() method is invoked.
  7. The implementation of doTag() performs its function, potentially calling other tag handlers (if the tag handler is implemented as a tag file) and invoking fragments.
  8. The doTag() method returns, and the tag handler instance is discarded. If SkipPageException is thrown, the rest of the page is not evaluated and the request is completed. If this request was forwarded or included from another page (or Servlet), only the current page evaluation stops.
  9. For each tag scripting variable declared with scopes AT_BEGIN or AT_END, the appropriate scripting variables and scoped attributes are declared, as with classic tag handlers.

7. JSP Fragments

JSP Fragments are represented in Java by an instance of the javax.servlet.jsp.tagext.JspFragment abstract class.Pieces of JSP code are translated into JSP fragments in the context of a tag invocation. JSP Fragments are created when providing the body of a <jsp:attribute> standard action for an attribute that is definedas a fragment or of type JspFragment, or when providing the body of a tag invocation handled by a Simple Tag Handler.

Before being passed to a tag handler, the JspFragment instance is associated with the JspContext of the surrounding page in an implementation-dependent manner. In addition, it is associated with the parent Tag or SimpleTag instance for collaboration purposes, so that when a custom action is invoked from within the fragment, setParent() can be called with the appropriate value. The fragment implementation must keep these associations for the duration of the tag invocation in which it is used.

The invoke() method executes the body and directs all output to either the passed in java.io.Writer or the JspWriter returned by the getOut() method of the JspContext associated with the fragment.

Simple Tag Games

The implementation of each method can optionally throw a JspException, which must be handled by the invoker. Note that tag library developers and page authors should not generateJspFragment implementations manually.

The following sections specify the creation and invocation lifecycles of a JSP Fragment in detail, from the JSP Container's perspective.

Creation of a JSP Fragment

Simple Tag Django

When a JSP fragment is created, the following steps occur (in order):

  1. An instance of a class implementing the JspFragment abstract class is obtained (may either be created or can optionally be cached) each time the tag is invoked. This instance must be configured to produce the contents of the body of the fragment when invoked. If the fragment is defining the body of a <jsp:attribute>, the fragment must evaluate the body each time it is invoked. Otherwise, if the fragment is defining the body of a simple tag, the behavior of the fragment when invoked varies depending on the body-content declared for the tag:
    • If the body-content is 'tagdependent', then the fragment must echo the contents of the body verbatim when invoked.
    • If the body-content is 'scriptless', then the fragment must evaluate the body each time it is invoked.
  2. The JspFragment instance is passed a reference to the current JspContext. Whenever the fragment invokes a tag handler, it must use this value when calling setJspContext().
  3. The JspFragment instance is associated with an instance of the tag handler of the nearest enclosing tag invocation, or with null if there is no enclosing tag. Whenever the fragment invokes a tag handler, the fragment must use this value when calling setParent().

Invocation of a JSP Fragment

After a JSP fragment is created, it is passed to a tag handler for later invocation. JSP fragments can be invoked either programmatically from a tag handler written in Java, or from a tag file using the <jsp:invoke> or <jsp:doBody> standard action.

JSP fragments are passed to tag handlers using a bean property of type JspFragment. These fragments can be invoked by calling the invoke() method in the JspFragment abstract class. Note that it is legal (and possible) for a fragment to recursively invoke itself, indirectly.

The following steps are followed when invoking a JSP fragment:

  1. The tag handler invoking the fragment is responsible for setting the values of all declared AT_BEGIN and NESTED variables in the JspContext of the calling page/tag, before invoking the fragment. Note that this is not always the same as the JspContext of the fragment being invoked, as fragments can be passed from one tag to another. In the case of tag files, for each variable declared in scope AT_BEGIN or NESTED, if a page scoped attribute exists with the provided name in the tag file, the JSP container must generate code to create/update the page scoped attribute of the provided name in the calling page/tag. If a page scoped attribute with the provided name does not exist in the tag file, and a page scoped attribute of the provided name is present in the calling page, the scoped attribute is removed from the calling page's page scope. See the chapter on Tag Files for details.
  2. If <jsp:invoke> or <jsp:doBody> is being used to invoke a fragment, if the var attribute is specified, a custom java.io.Writer is created that can expose the result of the invocation as a java.lang.String object. If the varReader attribute is specified, a custom java.io.Writer object is created that can expose the resulting invocation as a java.io.Reader object.
  3. The invoke() method of the fragment is invoked, passing in an optional Writer.
  4. Before executing the body of the fragment, if a non-null value is provided for the writer parameter, then the value of JspContext.getOut() and the implicit 'out' object must be updated to send output to that writer. To accomplish this, the container must call pushBody( writer ) on the current JspContext, where writer is the instance of java.io.Writer passed to the fragment upon invocation.
  5. The body of the fragment is then evaluated by executing the generated code. The body of the fragment may execute other standard or custom actions. If a classic Custom Tag Handler is invoked and returns SKIP_PAGE, or if a Simple Tag Handler is invoked and throws SkipPageException, the JspFragment must throw SkipPageException to signal that the calling page is to be skipped.
  6. Once the fragment has completed its evaluation, even if an exception is thrown, the value of JspContext.getOut() must be restored via a call to popBody() on the current JspContext.
  7. The fragment returns from invoke()
  8. If <jsp:invoke> or <jsp:doBody> is being used to invoke a fragment, if the var or varReader attribute is specified, a scoped variable with a name equal to the value of the var or varReader attribute is created (or modified) in the page scope, and the value is set to a java.lang.String or java.io.Reader respectively that can produce the results of the fragment invocation.
  9. The invoke() method can be called again, zero or more times. When the tag invocation defining the fragment is complete, the tag must discard the fragment instance since it might be reused by the container.

8. Example Simple Tag Handler Scenario

The following non-normative example is intended to help solidify some of the concepts relating to Tag Files, JSP Fragments and SimpleTag Handlers. In the first section, two sample input files are presented, a JSP (my.jsp), and a simple tag handler implemented using a tag file (simpletag.tag). One possible output of the translation process is presented in the second section.

Although short, the example shows all concepts, including the variable directive. In practice most uses of tags will be much simpler, but probably longer.

The sample generated code is annotated with comments that point to lifecycle steps presented in various sections. The notation is as follows:

  • 'Step T.x' = Annotated step x from 'Lifecycle of Simple Tag Handlers' earlier in this Chapter.
  • 'Step C.x' = Annotated step x from 'Creation of a JSP Fragment' earlier in this Chapter.
  • 'Step F.x' = Annotated step x from 'Invocation of a JSP Fragment' earlier in this Chapter.

Sample Source Files

This section presents the sample source files in this scenario, from which the output files are generated.

Original JSP (my.jsp)

Original Tag File (/WEB-INF/tags/simpletag.tag)

Sample Generated Files

This section presents sample output files that might be generated by a JSP compiler, from the source files presented in the previous section.

Helper class for JspFragment (JspFragmentBase.java)

Relevant Portion of JSP Service Method

Generated Simple Tag Handler (MySimpleTag.java)

9. Translation-time Classes

The following classes are used at translation time.

Tag mapping, Tag name

A taglib directive introduces a tag library and associates aprefix to it. The TLD associated with the library associates Taghandler classes (plus other information) with tag names. Thisinformation is used to associate a Tag class, a prefix, and a namewith each custom action element appearing in a JSP page.

At execution time the implementation of a JSP page will use anavailable Tag instance with the appropriate property settings and thenfollow the protocol described by the interfaces Tag, IterationTag,BodyTag, SimpleTag, and TryCatchFinally. The implementation guaranteesthat all tag handler instances are initialized and all are released,but the implementation can assume that previous settings are preservedby a tag handler, to reduce run-time costs.

Scripting Variables

JSP supports scripting variables that can be declared within ascriptlet and can be used in another. JSP actions also can be used todefine scripting variables so they can used in scripting elements, orin other actions. This is very useful in some cases; for example, thejsp:useBean standard action may define an object whichcan later be used through a scripting variable.

In some cases the information on scripting variables can bedescribed directly into the TLD using elements. A special case is typicalinterpretation of the 'id' attribute.In other cases the logic that decides whether an action instancewill define a scripting variable may be quite complex and the name ofa TagExtraInfo class is instead given in the TLD. ThegetVariableInfo method of this class is used attranslation time to obtain information on each variable that will becreated at request time when this action is executed. The method ispassed a TagData instance that contains thetranslation-time attribute values.

Validation

The TLD file contains several pieces of information that is usedto do syntactic validation at translation-time. It also contains twoextensible validation mechanisms: a TagLibraryValidatorclass can be used to validate a complete JSP page, and aTagExtraInfo class can be used to validate a specificaction. In some cases, additional request-time validation will be donedynamically within the methods in the Tag instance. If an error isdiscovered, an instance of JspTagException can be thrown.If uncaught, this object will invoke the errorpage mechanism of JSP.

Simpletags

The TagLibraryValidator is an addition to the JSP 1.2specification and is very open ended, being strictly more powerfulthan the TagExtraInfo mechanism. A JSP page is presented via thePageData object, which abstracts the XML view of the JSPpage.

A PageData instance will provides an InputStream (read-only) on thepage. Later specifications may add other views on the page (DOM, SAX,JDOM are all candidates), for now these views can be generated fromthe InputStream and perhaps can be cached for improved performance(recall the view of the page is just read-only).

As of JSP 2.0, the JSP container must support a jsp:id attribute toprovide higher quality validation errors. Thecontainer will track the JSP pages as passed to the container, andwill assign to each element a unique 'id', which is passed as thevalue of the jsp:id attribute. Each XML element in the XML viewwill be extended with this attribute. TheTagLibraryValidator can use the attribute in one or moreValidationMessage objects. The container then, in turn, can use thesevalues to provide more precise information on the location of anerror.

The prefix for the id attribute need not be 'jsp'but it must map to the namespace http://java.sun.com/JSP/Page.In the case where the user has redefined the jsp prefix, an alternative prefix must be used by the container.

Simple Tagine Recipes

Validation Details

In detail, validation is done as follows:

Simple Tagalog Words

First, the JSP page is parsed using the information in the TLD.At this stage valid mandatory and optional attributes are checked.

Second, for each unique tag library in the page as determinedby the tag library URI, and in the lexical order in which they appear,their associated validator class (if any) is invoked. This involves several substeps.

Simple Tagalog

The first substep is to obtain an initialized validator instance byeither:

  • construct a new instance and invoke setInitParameters() on it, or
  • obtain an existing instance that is not being used, invoke release() on it, and then invoke setInitParameters() on it, or
  • locate an existing instance that is not being used on which the desired setInitParameters() has already been invoked

The class name is as indicated in the <validator-class> element,and the Map passed through setInitParameters() is as described in the<init-params> element.All TagLibraryValidator classes are supposed to keep their initParametersuntil new ones are set, or until release() is invoked on them.

The second substep is to perform the actual validation. This is doneby invoking the validate() method with a prefix, uri, and PageData thatcorrespond to the taglib directive instance being validated and thePageData representing the page. In the case where a single URI is mappedto more than one prefix, the prefix of the first URI must be used.

Simplytag V2

The last substep is to invoke the release() method on the validator tagwhen it is no longer needed. This method releases all resources.

Finally, after checking all the tag library validator classes, theTagExtraInfo classes for all tags will be consulted by invoking theirvalidate method. The order of invocation of this methodsis undefined.