![]() |
![]() |
|
This section describes how to write Java classes that implement the functionality of an extended tag. The following topics are discussed:
The JSP 1.1 API defines a set of classes and interfaces that you use to write custom tag handlers. Documentation for the javax.servlet.jsp.tagext API is available at http://java.sun.com/j2ee/j2sdkee/techdocs/api/index.html.
Your tag handler must implement one of two interfaces:
The methods inherited from either the Tag or BodyTag interfaces and implemented by the tag handler class are invoked by the JSP engine at specific points during the processing of the JSP page. These methods signify points in the life cycle of a tag and are executed in the following sequence:
At the end of the doStartTag() method, you can determine if the tag body should be evaluated or not by returning one of the following value constants from your tag handler class:
If the tag is passing output to the JSP page (or the surrounding tag scope if it is nested), the tag must explicitly write its output to the parent-scoped JspWriter between this point in the tag life cycle and the end of the doEndTag() method. The tag handler can gain access to the enclosing output using the getEnclosingWriter() method.
You do not need to implement this method if you are using the BodyTagSupport convenience class, because the tag keeps a reference to the BodyContent and makes the reference available through the getBodyContent() method.
The significant difference between performing work in this method and performing work at the end of the doStartTag() method (once you know you are going to return EVAL_BODY_TAG) is that with this method, the scope of the tag's output is nested and does not go directly to the JSP page (or parent tag). All output is now buffered in a special type of JspWriter called BodyContent.
At the end of the doAfterBody() method, you can determine the life cycle of the tag again by returning one of the following value constants:
At this point, you may want your tag handler to write output to the surrounding scope. Obtain a writer to the enclosing scope using the BodyTagSupport.getPreviousOut() method or the BodyContent.getEnclosingWriter() method. Either method obtains the same enclosing writer.
Your tag handler can write the contents of the evaluated body to the surrounding scope, or can further process the evaluated body and write some other output. Because the BodyContent is appended to the existing BodyContent upon each iteration through the body, you should only write out the entire iterated body content once you decide you are going to return SKIP_BODY. Otherwise, you will see the content of each subsequent iteration repeated in the output.
Your tag handler writes output directly to the surrounding scope using the JspWriter obtained from pageContext.getOut() in the doEndTag() method. The previous step restored pageContext.out to the enclosing writer when popBody() was invoked on the pageContext.
You can control the flow for evaluation of the rest of the JSP page by returning one of the following values from the doEngTag() method:
Your custom tags can define any number of attributes that can be specified from the JSP page. You can use these attributes to pass information to the tag handler and customize its behavior.
You declare each attribute name in the TLD, in the <attribute> element. This declares the name of the attribute and other attribute properties.
Your tag handler must implement setter and getter methods based on the attribute name, similar to the JavaBean convention. For example, if you declare an attribute named foo, your tag handler must define the following public methods:
public void setFoo(String f);
public String getFoo();
Note that the first letter of the attribute name is capitalized after the set/get prefix.
The JSP engine invokes the setter methods for each attribute appropriately after the tag handler is initialized and before the doStartTag() method is called. Generally, you should implement the setter methods to store the attribute value in a member variable that is accessible to the other methods of the tag handler.
Defining New Scripting Variables
Your tag handler can introduce new scripting variables that can be referenced by the JSP page at various scopes. Scripting variables can be used like implicit objects within their defined scope.
Define a new scripting variable by using the <teiclass> element to identify a Java class that extends javax.servlet.jsp.tagext.TagExtraInfo. For example:
<teiclass>weblogic.taglib.session.ListTagExtraInfo</teiclass>
Then write the TagExtraInfo class. For example:
package weblogic.taglib.session;
import javax.servlet.jsp.tagext.*;
public class ListTagExtraInfo extends TagExtraInfo {
public VariableInfo[] getVariableInfo(TagData data) {
return new VariableInfo[] {
new VariableInfo("username",
"String",
true,
VariableInfo.NESTED),
new VariableInfo("dob",
"java.util.Date",
true,
VariableInfo.NESTED)
};
}
}
The example above defines a single method, getVariableInfo(), which returns an array of VariableInfo elements. Each element defines a new scripting variable. The example shown above defines two scripting variables called username and dob which are of type java.lang.String and java.util.Date respectively.
The constructor for VariableInfo() takes four arguments.
Configure your tag handler to initialize the value of the scripting variables via the page context. For example, the following Java source could be used in the doStartTag() method to initialize the values of the scripting variables defined above:
pageContext.setAttribute("name", nameStr);
pageContext.setAttribute("dob", bday);
Where the first parameter names the scripting variable, and the second parameter is the value assigned. Here, the Java variable nameStr is of type String and bday is of type java.util.Date.
You can also access variables created with the TagExtraInfo class by referencing it the same way you access a JavaBean that was created with useBean.
Dynamically Named Scripting Variables
It is possible to define the name of a new scripting variable from a tag attribute. This definition allows you to use multiple instances of a tag that define a scripting variable at the same scope, without the scripting variables of the tag clashing. In order to achieve this from your class that extends TagExtraInfo, you must get the name of the scripting variable from the TagData that is passed into the getVariableInfo() method.
From TagData, you can retrieve the value of the attribute that names the scripting variable using the getAttributeString() method. There is also the getId() method that returns the value of the id attribute, which is often used to name a new implicit object from JSP tag.
Writing Cooperative Nested Tags
You can design your tags to implicitly use properties from tags they are nested within. For example, in the code example called SQL Query (see the samples/examples/jsp/tagext/sql directory of your WebLogic Server installation) a <sql:query> tag is nested within a <sql:connection> tag. The query tag searches for a parent scope connection tag and uses the JDBC connection established by the parent scope.
To locate a parent scope tag, your nested tag uses the static findAncestorWithClass() method of the TagSupport class. The following is an example taken from the QueryTag example.
try {
ConnectionTag connTag = (ConnectionTag)
findAncestorWithClass(this,
Class.forName("weblogic.taglib.sql.ConnectionTag"));
} catch(ClassNotFoundException cnfe) {
throw new JspException("Query tag connection "+
"attribute not nested "+
"within connection tag");
}
This example returns the closest parent tag class whose tag handler class matched the class given. If the direct parent tag is not of this type, then it is parent is checked and so on until a matching tag is found, or a ClassNotFoundException is thrown.
Using this feature in your custom tags can simplify the syntax and usage of tags in the JSP page.
|
Copyright © 2000 BEA Systems, Inc. All rights reserved.
|