Details
-
Improvement
-
Status: Open
-
Minor
-
Resolution: Unresolved
-
1.2.6 Beta
-
None
-
Operating System: All
Platform: PC
-
33064
Description
There is an architectural problem with Struts tags used in tag files.
As you know, in every Struts tag decision on whether attribute has a value set
is based on comparison to null. Example:
if (accesskey != null)
Where "accesskey" is an attribute of html:select tag.
The following example shows why usage of Struts tags is substantially restricted
in tag files because of that feature.
The following "icon" tag renders a hyperlink based on "type" attribute (say,
"remove" or "add"), displaying corresponding icon. It has 2 mutually exclusive
attributes: "action" and "href" and one optional attribute "onclick".
=== icon.tagx begins ===
<?xml version="1.0" encoding="UTF-8"?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page"
xmlns:html="http://struts.apache.org/tags-html" version="2.0" >
<jsp:directive.tag body-content="empty"/>
<jsp:directive.attribute name="type" required="true" rtexprvalue="true" />
<jsp:directive.attribute name="action" required="false" rtexprvalue="true" />
<jsp:directive.attribute name="href" required="false" rtexprvalue="true" />
<jsp:directive.attribute name="onclick" required="false" rtexprvalue="true" />
<html:link action="${action}">
<html:img page="images/${type}.gif" border="0"/>
</html:link>
</jsp:root>
=== icon.tagx ends ===
Question here is how should we invoke html:link tag based on value of the
attributes? Ok, we could use <c:choose> like:
<c:choose>
<c:if test="${not empty action}">
<!-- use value of action atribute -->
<html:link action="${action}">
<html:img page="images/${type}.gif" border="0"/>
</html:link>
</c:if>
<c:otherwise>
<!-- use value of href atribute -->
<html:link href="${href}">
<html:img page="images/${type}.gif" border="0"/>
</html:link>
</c:otherwise>
</c:choose>
this would be correct if we had only "action" and "href", but we also have
"onclick". That means, that in every if/otherwise section we need to add same
check for presence of "onclick" attribute. If we had not 3 but 10 attributes,
then total number of <if> statements would be 2^9 which is far beyond reasonable
limits.
The most obvious and conscious solution would be to use the following
construction instead:
<html:link action="${action}" href="${href}" onclick="${onclick}">
<html:img page="images/${type}.gif" border="0"/>
</html:link>
So if icon tag is invoked via <my:icon action="/Action" type="add"/> then "href"
and "onclick" attributes would be nulls and, say, href="${href}" will not change
the default value (null) of the html:link "href" property (call setHref(null);
on tag handler). But this is not true because EL evaluates nulls into empty
strings, so what happens is that html:link tag receives empty (not null) "href"
and "onclick" properties which produces an error message (setHref(""); on tag
handler).
The solution would be to make Struts to check attributes for emptiness (like
StringUtils.isEmpty(), i.e. == null or ""), not just for nulls. Then it would work.
Example:
if (StringUtils.isNotEmpty(accesskey)) { results.append(" accesskey=""); results.append(accesskey); results.append("""); }
Where StringUtils is from jakarta commons lang package.