Recently I've been implementing some tag handlers that emit HTML. In them, I want to carry through some of the standard HTML attributes such as id
and class
. And I've discovered that Tomcat is quite happy to accept the following TLD entry, but at runtime complains that it's unable to find a setter method for the attribute:
<attribute> <name>class</name> <rtexprvalue>true</rtexprvalue> <type>java.lang.String</type> </attribute>
Sun provides a schema definition for the JSP taglib deployment descriptor, and it defines the type tld-attributeType
for attribute declarations. Looking at that type definition, we see this:
<xsd:element name="name" type="j2ee:java-identifierType"/>
And jumping to the common definitions schema, here's the definition of java-identifierType
:
<xsd:complexType name="java-identifierType"> <xsd:annotation> <xsd:documentation> The java-identifierType defines a Java identifier. The users of this type should further verify that the content does not contain Java reserved keywords. </xsd:documentation> </xsd:annotation> <xsd:simpleContent> <xsd:restriction base="j2ee:string"> <xsd:pattern value="($|_|\p{L})(\p{L}|\p{Nd}|_|$)*"/> </xsd:restriction> </xsd:simpleContent> </xsd:complexType>
Did you read the comment? That users of the type should perform keyword validation?!? I couldn't believe it, until I turned to the XML Schema docs and discovered that there's no way to exclude values: the enumeration facet enumerates legal values only.
So, two lessons to draw from this: first, XML schema is not only complex but incomplete, and second, you can't use class
as a JSP tag attribute. Or any other Java keyword for that matter. At least not in a servlet container developed by people who have read the schema docs, because this restriction is not mentioned in the JSP specification text.
My solution? The ugly but descriptive htmlClass
.
(originally posted on my website 19 Nov 08)