3

I have a .jsp page that does the following check to see if it should display an error message:

<s:if test="#parameters.error == 1">
    <ul><li>
        <s:text name="login.error"/>
    </li></ul>
</s:if>

The error parameter comes from the request parameter (i.e. /myPage.action?error=1).

I've debugged the jsp page into the org.apache.struts2.views.jspComponentTagSupport.doStartTag() method and from there I can access the ValueStack and see that the HttpParameters object does contain an "error" parameter, which I can access via:

stack.getContext().get("parameters")).get("error")).getValue();

This will return a String with the value of 1 as expected.
However, debugging down through the code further it seems that it's not properly evaluating the test attribute of the <s:if> tag.
The ognl.ASTEq.getValueBody(OgnlContext, Object) method attempts to get the value of the 'children' of the parsed test query.
It ends up in the ognl.OgnlRuntime.getFieldValue(OgnlContext, Object, String, boolean) method which returns a NotFound result, even though the HttpParameters contains the value it's looking for ("error").

It seems like this is a bug in struts/ognl for how it's parsing the parameters on the value stack, but I'm not sure.

I'm using Struts 2.5.5. Recently upgraded from Struts 2.3.x and this code worked fine with that version so either it's a bug or something changed in how these properties are accessed that I'm not aware of.

Andrea Ligios
  • 49,480
  • 26
  • 114
  • 243
Richard
  • 43
  • 4

2 Answers2

3

From a short research, it could be due to Issue WW-4572, AKA the refactoring of the Parameter management, from a Map of Objects to an HttpParameter class containing Parameter objects, shipped with version 2.5.5.

Looking at the Parameter class, it seems it should be enough to call the value attribute on it, like:

<s:if test="%{#parameters.error.value == 1}">

I hope is that, but meanwhile: try using more of the framework mechanisms and less the request parameters (eg. use an error variable with getter and setter on a base action, or even better, use actionErrors and fieldErrors to carry the messages, and check for their presence to detect when an error occurred).

Andrea Ligios
  • 49,480
  • 26
  • 114
  • 243
  • Using #parameters.value.error didn't work, but I added an error variable on the action and can access it using , which is probably better anyway as you mentioned. I still think there is a bug in how struts is parsing the parameters that likely was introduced by [WW-4572](https://issues.apache.org/jira/browse/WW-4572). – Richard Nov 01 '16 at 14:33
  • There was a typo in the answer, can you please try with `error.value` instead of `value.error` ? – Andrea Ligios Nov 01 '16 at 15:06
  • No, that doesn't work either. It seems to be parsing it incorrectly from what I'm seeing in my debugger. It can access the HttpParameters on the value stack, but seems like it parses parameters and error as separate field names and tries to find them independently on the stack, so instead of getting the HttpParameters via the parameters field and then looking for error in the HttpParameters, it looks for the error field on the value stack itself (at least that's my best guess as to what it's doing right now). – Richard Nov 01 '16 at 15:30
  • 1
    Here we go ;) +1 for identifying the cause. – Aleksandr M Nov 01 '16 at 17:19
  • Please report an issue in JIRA, it's related to change mentioned by @AndreaLigios – Lukasz Lenart Nov 02 '16 at 07:22
3

Only in Struts 2.5.5.

If you want to check value of the error parameter then:

<s:if test="#parameters.get('error').value == 1">
    <ul><li>
        <s:text name="login.error"/>
    </li></ul>
</s:if>

If you want to check whether parameter exists:

<s:if test="#parameters.contains('error')">
</s:if>

Andrea is right about the cause and about using request parameters.

Aleksandr M
  • 24,264
  • 12
  • 69
  • 143