Win a copy of Re-engineering Legacy Software this week in the Refactoring forum
or Docker in Action in the Cloud/Virtualization forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Struts 2: %{} or #

 
Vu Pham
Ranch Hand
Posts: 100
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi all,

1. I'm confuse about %{variable} and #variable. What are the different between them?


2. I have 1 more question
In my project, I use

<s:text name="%{response}"/>

It can get the value from getResponse(), I can't use <s:text name="response"/>

However, in the same form, I use

<s:textarea rows="4" name="remarks" id="remarks" cols="100" />

It can get the value from getRemarks()

Do you know why?


Thanks :-)
 
Sonny Gill
Ranch Hand
Posts: 1211
IntelliJ IDE Mac
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
AFAIK..

%{variable} and #variable

Ok.. in Struts tags, whenever you enter a value for an attribute, it can either be treated as a literal value or it can be treated as an expression that is evaluated against the current value stack.

%{} syntax is used to force OGNL evaluation where Struts would otherwise be treating the value as a String literal.

For example,
<s:property value="name" />
will look for a name property in the value stack i.e. is a value retrieved by calling getName().
If you wanted to force it to use literal value "name", you will need to use the %{} syntax -
<s:property value="%{'name'}" />

#variable is used to refer to a variable that does not exist on the value stack, but rather exists somewhere else on the action context. This could be variables created by using the <set> tag, or values in session scope etc.


For your second question -
<s:textarea> tries to use the value of name attribute to get the same property from the value stack, so it gets the value from getRemarks(). No surprise there.
Normally <s:text> expects the name to be a key to be looked up in a resource bundle, so it can't get the value from getResponse() method.
If <s:text name="%{response}"/> is getting the value from getResponse(), then my guess is that this is because of forced OGNL evaluation as I explained earlier.


Struts 2 In Action book covers these concepts in a fair bit of detail. Or search online for "Struts 2 Value Stack", you should be able to find web pages or mailing list posts that explain these concepts in more detail.

Cheers,
Sonny
 
Vu Pham
Ranch Hand
Posts: 100
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Sonny,

In my 2nd question, I used

<s:text name="response"/>

This one will be incorrect. Why it doesn't get the value from getResponse()?
 
David Newton
Author
Rancher
Posts: 12617
IntelliJ IDE Ruby
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Because it's looking for a resource (message) under the key "response", not calling getResponse().
 
Victor Hou
Greenhorn
Posts: 4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
honestly I didnt quite get the second question.
you mean different tags may save in different stack? but I thought all the parameters you defined in the Action would be save at value stack which means you can use the parameter without #. Am I right?
Another way to help you out, use the

Still I have a question for my own, hope any one could help me here is the code:

notice this wont work but if I change it to this code will go well.
Thanks in advance!
 
Vu Pham
Ranch Hand
Posts: 100
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ok, thanks Sony and David :-)
 
Vu Pham
Ranch Hand
Posts: 100
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Victor,

As I know, sometimes we can't use #variable, we must use %{#variable}. But I don't know why? Anyone know about this?
 
Victor Hou
Greenhorn
Posts: 4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I got these sentences:
All String attribute types are parsed for the %{ ... } characters.
All non-String attribute types are not parsed, but instead evaluated directly as an OGNL expression
The exception to rule #2 is that if the non-String attribute starts with %{ and ends with }, those characters are cut off before evaluating the expression.
from:http://wiki.opensymphony.com/display/WW/Tag+Syntax
Now I doubt these from every problems I have faced.

It seems you may not use %{} to parse OGNL Expression only in this tag

and others if you wannar use OGNL Expression you should put it into the brace.
 
Sonny Gill
Ranch Hand
Posts: 1211
IntelliJ IDE Mac
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Victor Hou:

Still I have a question for my own, hope any one could help me here is the code:

notice this wont work but if I change it to this code will go well.


Because s:hidden expects the value to be a String literal by default i.e. if the value is "abc" it will try to call getAbc(). In this case, you dont' want "#st.index" to be treated as a String literal. Rather, you want to force Struts to treat it as an OGNL expression. That is why you need the %{} around it.
 
Victor Hou
Greenhorn
Posts: 4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I think I now fully understand
The second question
<s:text name="%{response}"/>

It can get the value from getResponse(), I can't use <s:text name="response"/>


If you read the source code "text.ftl" from template.simple of struts2-core* you will understand.
Look these codes below


See? the property of name is using a freemarker expression ${}, this will output a literl string, so you can just use the sring which you wannar to output. But if you wannar get a value from a parameter you should add %{} then struts will see it as an OGNL expression and this will be parsed as


Futher, I checked most of the tags in package of template.simple(which we always use in the project), I found only the value property of tag is calling a struts tag(@s.property value="parameters.nameValue"), that means it will do exactly as what Sonny said
<s:property value="name" />
will look for a name property in the value stack i.e. is a value retrieved by calling getName().
If you wanted to force it to use literal value "name", you will need to use the %{} syntax -
<s:property value="%{'name'}" />


Thanks Sonny and I must confess I didnt read your post carefully, plus,
here s:property value="%{'name'} why did you add '' around name? It's not a nessersary , I think.

P.S. I am not a native English speaker, so hope you can get what I mean.
 
Sailesh Ganeshan
Greenhorn
Posts: 13
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi guys,

I'm using <s:property> default attribute. But, I cant use EL here,

please suggest a solution for this.

eg:

<s:property value="#itnObjl" default="%{testVar}"/>
I've tried this too : %{#testVar}

Where testVar is an <s:set>
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic