| [ Team LiB ] |
|
22.4 Dynamic Attribute Values and TypesThroughout this book, you've seen how action element attributes can be given dynamic values, evaluated at runtime. A dynamic attribute value can be assigned by an EL expression, a Java expression (as shown in Chapter 16), or by a <jsp:attribute> element. Not all attributes accept dynamic values, though. To tell the container that a custom action attribute accepts a dynamic value, or a request-time attribute value as it's also called, you have to declare this fact in the TLD: <tag>
<name>geekContestEntry</name>
<tag-class>com.xmp.GeekContextEntry</tag-class>
<description>
Saves the submitted data in the Geek Contest database.
</description>
<attribute>
<name>yearsSinceLastVacation</name>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>hoursWithoutSleep</name>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>employersInAMonth</name>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
An <rtexprexprvalue> element with the value true enables this feature. You can then assign dynamic values to the attributes in a page like this: <xmp:geekContestEntry yearsSinceLastVacation="${param.noVacation}" hoursWithoutSleep='<%= request.getParameter("noSleep") %>'> <jsp:attribute name="employersInAMonth"> <xmp:getAvgEmployers id="${param.geekId}" /> </jsp:attribute> </xmp:geekContestEntry> An EL expression assigns the value of the noVacation request parameter to the first attribute, a Java expression assigns the noSleep parameter value to the second attribute, and a <jsp:attribute> element assigns the value produced by another custom action to the third attribute. In the tag handler, each action attribute is implemented as a property setter method that takes one argument (the value), in accordance with the JavaBeans conventions. As with regular beans, the property type for a tag handler attribute can be of any Java type, for instance an int: public setYearsSinceLastVacation(int value) {
yearsSinceLastVacation = value;
}
When a Java expression is used to set the value of the attribute, the return type of the expression must match the Java type declared for the property; otherwise an exception is thrown. For an EL expression, the value is converted to the attribute's type according to the rules described in Table 22-1.
When the value is set by a <jsp:attribute> element, the body is evaluated and the result is converted to a String. This value is then converted to the attribute's type according to the rules described next. Even an attribute that accepts a dynamic value must sometimes be set to a fixed value. Let's look at an example. For an attribute of type int, you can assign a fixed value with an EL expression like this: <xmp:geekContestEntry
yearsSinceLastVacation="${5}"
...
/>
It would be much nicer, however, if the value could be entered as a regular text value and still be converted to the correct type: <xmp:geekContestEntry yearsSinceLastVacation="5" ... /> That's exactly what the container does, with some help from the tag handler developer for types other than the most basic ones. This lets a page author set an action attribute declared to accept a request-time attribute value to either a static text value or a dynamic value. The next two sections describe this mechanism in detail. 22.4.1 Conversions Performed by the ContainerThe container automatically takes care of the conversion from text values to the most commonly used Java types. A JSP 2.0-compliant container supports the type conversions shown in Table 22-2.
These rules apply to attributes for standard actions and custom actions alike. 22.4.2 Using a PropertyEditor for ConversionIf the standard conversion rules are not enough for your needs, you can use a bean PropertyEditor to convert a literal string value to any Java data type you like. If an action attribute value is specified as a literal string for an attribute of a type other than String, the container looks for a property editor that can convert the string to the attribute's data type. The property editor is also used for EL expressions that evaluate to a String, and for <jsp:attribute> element values. Say you have an attribute of type java.util.Date. To let the page author specify it as a text value, you need a PropertyEditor that converts a String to a Date. Here's how it's done. First you implement the PropertyEditor: package com.foo;
import java.beans.*;
import java.text.*;
import java.util.*;
public class MyDatePE extends PropertyEditorSupport
implements PropertyEditor {
private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
private Date value;
public Object getValue( ) {
return value;
}
public void setAsText(String text)
throws IllegalArgumentException {
try {
value = sdf.parse(text);
}
catch (ParseException e) {
throw new IllegalArgumentException(e.getMessage( ));
}
}
}
The container calls the setAsText( ) method with the attribute's String value. This method creates a Date object from the string and saves it in the instance variable named value. The container then calls the getValue( ) method—which returns the new Date object—and uses the value to set the action's attribute value. Simple enough, but you must also tell the container to use your PropertyEditor for this action. You can do so by creating a BeanInfo class for the action's tag handler: package com.foo;
import java.beans.*;
import java.util.*;
public class MyTagBeanInfo extends SimpleBeanInfo {
public PropertyDescriptor[] getPropertyDescriptors( ) {
PropertyDescriptor[] pds = new PropertyDescriptor[4];
try {
pds[0] = new PropertyDescriptor("anInt", MyTag.class,
null, "setAnInt");
pds[1] = new PropertyDescriptor("aString", MyTag.class,
null, "setAString");
pds[2] = new PropertyDescriptor("firstDate", MyTag.class,
null, "setFirstDate");
pds[3] = new PropertyDescriptor("secondDate", MyTag.class,
null, "setSecondDate");
}
catch (Exception e) {}
pds[2].setPropertyEditorClass(MyDatePE.class);
pds[3].setPropertyEditorClass(MyDatePE.class);
return pds;
}
}
This BeanInfo class is for a tag handler with four attributes, named anInt, aString, firstDate, and secondDate. The getPropertyDescriptors( ) method first creates an array with one PropertyDescriptor for each attribute and then sets the property editors for the two Date attributes to the PropertyEditor class described earlier. A BeanInfo class is automatically bound to its bean class (in this case, the tag handler class is considered to be a bean) through a class-naming convention: the name of the BeanInfo class for a bean simply has the same name as the bean class plus "BeanInfo." So in this example, MyTagBeanInfo is the BeanInfo class for the MyTag class. The MyTag class is a regular tag handler class. You don't need to do anything special in the tag-handler class itself to use a PropertyEditor to convert string values to other types. |
| [ Team LiB ] |
|