Struts2 Tiles sets var attribute for tile attribute as string
I am using struts 2.3.16 and tiles 2.0.6.
Defining fragments with an empty attribute (among others):
<put-attribute name="pageSidePanel" value="" />
Some other definitions extend it and they can choose to either fill in the value:
<put-attribute name="pageSidePanel" value="/panels/greenPanel.jsp" />
or leave it blank.
I tried to check if this attribute is empty using the "set" tag for struts and some basic if / else logic. For example:
<s:set var="sidePanelName"><tiles:getAsString name='pageSidePanel'/></s:set>
<s:if test='%{#sidePanelName.isEmpty()}'>TRUE</s:if><s:else>FALSE</s:else>
The results were not what I expected. I ran 11 logic tests in two flavors, 11 tests used a hashtag and another 11 did not:
#sidePanelName vs sidePanelName
I was doing tests with two different JSP pages that actually put the value into tiles and the other did not. So, there are 44 logical tests in total:
- 11 tests using # on a page where the snippets attribute is empty
- 11 tests don't use # on a page where the snippets attribute is empty
- 11 tests using # on a page where tiles attribute is populated with value
- 11 tests don't use # on a page where tile attribute is populated with value
Situation 3 was ONLY correct. The whole other situation gave the wrong results. For example, in situation 1, if I test #var == null
, I get false, but if I test var == null
(no hashtag) i
, I get true. So, I need to clarify two things:
- What is the effect of using # or not?
- What is the effect of the tile attribute having value or not. Does struts var treat it as null or as an empty string or does it depend on whether I used # or not?
For reference, here are all the tests:
<s:set var="sidePanelName"><tiles:getAsString name='pageSidePanel'/></s:set>
<s:if test='#sidePanelName != ""'>TRUE</s:if><s:else>FALSE</s:else>
<s:if test="#sidePanelName != ''">TRUE</s:if><s:else>FALSE</s:else>
<s:if test='#sidePanelName == ""'>TRUE</s:if><s:else>FALSE</s:else>
<s:if test="#sidePanelName == ''">TRUE</s:if><s:else>FALSE</s:else>
<s:if test='%{!#sidePanelName.isEmpty()}'>TRUE</s:if><s:else>FALSE</s:else>
<s:if test='%{#sidePanelName.length() > 0}'>TRUE</s:if><s:else>FALSE</s:else>
<s:if test='%{#sidePanelName.length() == 0}'>TRUE</s:if><s:else>FALSE</s:else>
<s:if test='%{#sidePanelName.equals("")}'>TRUE</s:if><s:else>FALSE</s:else>
<s:if test='%{#sidePanelName.equalsIgnoreCase("")}'>TRUE</s:if><s:else>FALSE</s:else>
<s:if test='#sidePanelName == null'>TRUE</s:if><s:else>FALSE</s:else>
<s:if test='#sidePanelName != null'>TRUE</s:if><s:else>FALSE</s:else>
<s:if test='sidePanelName != ""'>TRUE</s:if><s:else>FALSE</s:else>
<s:if test="sidePanelName != ''">TRUE</s:if><s:else>FALSE</s:else>
<s:if test='sidePanelName == ""'>TRUE</s:if><s:else>FALSE</s:else>
<s:if test="sidePanelName == ''">TRUE</s:if><s:else>FALSE</s:else>
<s:if test='%{!sidePanelName.isEmpty()}'>TRUE</s:if><s:else>FALSE</s:else>
<s:if test='%{sidePanelName.length() > 0}'>TRUE</s:if><s:else>FALSE</s:else>
<s:if test='%{sidePanelName.length() == 0}'>TRUE</s:if><s:else>FALSE</s:else>
<s:if test='%{sidePanelName.equals("")}'>TRUE</s:if><s:else>FALSE</s:else>
<s:if test='%{sidePanelName.equalsIgnoreCase("")}'>TRUE</s:if><s:else>FALSE</s:else>
<s:if test='sidePanelName == null'>TRUE</s:if><s:else>FALSE</s:else>
<s:if test='sidePanelName != null'>TRUE</s:if><s:else>FALSE</s:else>
source to share
The tag <tiles:getAsString>
returns an empty string if you have not defined its value in the tile definition. So your code is
<s:set var="sidePanelName"><tiles:getAsString name='pageSidePanel'/></s:set>
will be the same as an empty tag <s:set>
.
<s:set var="sidePanelName"></s:set>
And an empty tag <s:set>
with the w / o value
attribute assigns the variable to the top
variable (in most cases, this will be the current instance of the action).
Try to print its value with <s:property value="#sidePanelName"/>
. You will probably see something like your_package.YourClass@hash
.
source to share
You cannot call methods on an object null
...
Then
-
isEmpty()
andlength()
are invalid because they are called on the object itself, while - for comparison with
equals()
andequalsIgnoreCase()
, they can be called without generating NPEs if they are called on a known object, for example"".equalsIgnoreCase(#sidePanelName)
.
BTW if the object is null "".equalsIgnoreCase(#sidePanelName)
will also throw false because it is not an empty String, it is just null ...
PS: pay attention to your description which is misleading:
I have a tile attribute NOT of a string like
[...]
CORRECT results when the string is not empty / filled / has at least one character -
source to share