user1884155
user1884155

Reputation: 3736

Struts2 Tiles setting a var to a tiles attribute as string

I use struts 2.3.16 and tiles 2.0.6.

A tiles definition 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 empty as well.

I tried to test on whether or not this attribute is empty by using a struts "set" tag 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 performed 11 logical tests, in two variation: 11 tests used the hashtag, and the other 11 did not:

#sidePanelName vs sidePanelName

I did the tests with 2 different JSP pages, one that has actually put a value in tiles and one that didn't. So in total there 44 logical tests:

  1. 11 tests using # on a page where the tiles attribute is empty
  2. 11 tests not using # on a page where the tiles attribute is empty
  3. 11 tests using # on a page where the tiles attribute is filled in with a value
  4. 11 tests not using # on a page where the tiles attribute is filled in with a value

ONLY situation 3 was correct. All the other situation gave wrong results. For example, in situation 1, if I test #var == null I get false, but if I test var == null (without the hashtag) i get true. So there's two things I need to clear up:

  1. What is the effect of using # or not?
  2. what is the effect of the tiles attribute having a value or not, Does the struts var regard it as null or as the 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>

Upvotes: 3

Views: 4400

Answers (2)

Aleksandr M
Aleksandr M

Reputation: 24396

The <tiles:getAsString> tag will return empty string if you haven't defined its value in tiles definition. So your code

<s:set var="sidePanelName"><tiles:getAsString name='pageSidePanel'/></s:set>

will be the same as just an empty <s:set> tag.

<s:set var="sidePanelName"></s:set>

And an empty <s:set> tag w/o value attribute will assign the top to a variable (in most cases it would be the current action instance).

Try to print its value with <s:property value="#sidePanelName"/>. You will probably see something like your_package.YourClass@hash.

Upvotes: 4

Andrea Ligios
Andrea Ligios

Reputation: 50203

You can't invoke methods on a null object...

Then

  • isEmpty() and length() are uncallable, because invoked on the object itself, while
  • for the comparisons with equals() and equalsIgnoreCase(), they're callable without generating NPE if invoked on the known object , like "".equalsIgnoreCase(#sidePanelName).

BTW, if the object is null, also "".equalsIgnoreCase(#sidePanelName) will give false, because it is not equals to an empty String, it is just null...


P.S: pay attention to your description, that is misleading:

I have a tiles attribute that is NOT of type string

[...]

The results are CORRECT whenever the string is not empty/is filled in/has at least one character-

Upvotes: 1

Related Questions