Tag Handler Life Cycle
If the container encounters a custom tags during the display of a JSP page, many events take place, beginning with the instantiation of the tag handler as shown in Figure 18.2.
Figure 18.2. Tag handler life cycle.
Execution of the methods implemented within tag handler classes is triggered by these events along the tag handler life cycle. The sequence of method invocation within the tag handler life cycle is as follows:
Once a JSP tag is encountered, the methods setPageContext() and setParent() are invoked to set up an environment context for the tag handler. These methods don't have to be implemented if you're using the tag support abstract classes (TagSupport and BodyTagSupport) for development (as opposed to the tag interfaces).
Next, the setter methods for tag attributes are invoked. Tag handlers must define setters and getters for all attributes.
Next, the doStartTag() method is invoked. This method is commonly used to initialize any resources for execution of your tag logic. This method should return one of three different values depending on the nature of your tag body, assuming that a tag body is implemented:
Tag.SKIP_BODY should be returned if you're implementing a simple (empty body) tag. On return of this value, the doEndTag() method is invoked.
Returning Tag.EVAL_BODY_INCLUDE causes evaluation and inclusion of tag body contents. Only classes implementing the Tag interface or extending the TagSupport class may return this value. On return of this value, the doEndTag() method is invoked.
Tag.EVAL_BODY_TAG causes evaluation of the tag body, followed by invocation of the doInitBody() method. Only classes implementing the BodyTag Interface or extending the BodyTagSupport class may return this value.
If EVAL_BODY_TAG is returned, the setBodyContent()method is invoked. This method creates a reference to the BodyContent (a JspWriter) buffer, which may be used by the doAfterBody() method for processing later in the life cycle. The BodyContent buffer contains all output from the tag, including any body content, if any. (At this point, the client does not have access to any output derived from the tag). If the tag is writing output to the JSP page, that output must be written to the parent-scoped JspWriter (via the getEnclosingWriter() method) before the end of the doEndTag() method. You don't have to implement the setBodyContent() method if you're implementing the BodyTagSupport class. This class has the convenience of the getBodyContent() method, which provides a reference to BodyContent.
If EVAL_BODY_TAG is returned, the doInitBody() method is invoked. This method is invoked immediately prior to the body tag being evaluated for the first time. This method is commonly used to prepare scripting variables or place content into the BodyContent JspWriter. As discussed earlier, content placed into the BodyContent is buffered and isn't available to the JSP page at this point.
If EVAL_BODY_TAG is returned, the doAfterBody method is invoked. This method is invoked immediately after the tag body is evaluated and added to the BodyContent. This method is commonly used to process work based on the results of the body tag evaluation. To access the evaluated body, use the getBodyContent() method if you extended the BodyTagSupport class, or use the setBodyContent() method if you implemented the BodyTag interface (you should have stored a BodyContent instance).
The JSP 1.2 spec provides a javax.servlet.jsp.tagext.IterationTag interface, which enables you to reprocess the tag body if desired. This reprocessing would most likely be driven by a preset condition, much like iteration or loop logic.
The doAfterBody() method returns one of two different values depending on the nature of your tag body:
Tag.SKIP_BODY should be returned if no further processing of the tag body is required. Upon return of this value, the doEndTag() method is invoked.
Tag.EVAL_BODY_TAG (IterationTag.EVAL_BODY_AGAIN) causes evaluation of the tag body again. The result of the tag body evaluation is appended to the BodyContent. The doAfterBody() method is invoked again.
To write to the surrounding scope, you can obtain a writer using method BodyTagSupport.getPreviousOut() or method BodyContent.getEnclosingWriter() as discussed earlier. Both methods return the same JspWriter. Because the BodyContent is appended on each iteration through the tag body, you should write to this surrounding scope only when you've decided to return Tag.SKIP_BODY.
At this point in the life cycle, the writer in the pageContext() is returned to the parent JspWriter.
Next, the doEndTag() method is invoked. This method is commonly used to perform post–body tag processing, close server-side resources, or to write output to the surrounding scope using the pageContext.getOut() method.
The doEndTag() method returns one of two different values depending on the nature of your page:
To conclude the tag handler life cycle, the release() method is invoked just before the tag handler instance is made available for garbage collection.
Tag Body Exceptions
The JSP 1.2 spec provides a javax.servlet.jsp.tagext.TryCatchFinally interface. This interface enables you to handle exceptions (manage expected programming error conditions) within the tag body using the doCatch() and doFinally() methods.