Imagine my horror when I ran a validation check against a JSP/Struts project using XHTML, and found that it failed. I still tear up a bit when I think about it. There were several failures of certain tags not being properly closed. To make debugging matters worse, not all tags were exhibiting this problem.
The problem centered around <input> tags not being properly terminated. In XHTML, all tags, including those that do not have body contents, must be closed. A tag without a body should close itself (i.e. <input />). Looking at the generated HTML source, I could see that tags generated by the Struts html taglib weren’t being closed.
Typically this means that the page was not declared as XHTML; this is done by using the <html:html> tag with the xhtml attribute set to true. I looked at the JSP, and confirmed that the xhtml attribute was in fact set. When that attribute is set, the Struts taglibs are supposed to create XHTML-compliant code. In this case, it was not doing that.
I started looking around various Java and Struts web sites, looking for people having the same issue. If I did find a similar issue, it was due to a defect in very early releases of Struts, and was not applicable to the release I was using. I then started looking at the Struts html taglib documentation to see if I was using the <html:html> tag correctly, when I found the documentation for a similar tag, <html:xhtml>, which contained this pearl of wisdom:
Using this tag in a page tells all other html taglib tags to render themselves as XHTML 1.0. This is useful when composing pages with JSP includes or Tiles.
Not only am I compliant, I’m big on code reuse, which means using templates that use the aforementioned JSP includes. It turns out that the <html:html xhtml=”true”> tag does not apply to JSP’s that are included. To fix the problem, the <html:xhtml/> tag had to be placed at the start of all included files.
Then compliance nirvana began.