Search code examples
jspstruts2ognlhttp-request-parametersstruts-tags

Struts parameters not accessible in <s:if> tag


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.


Solution

  • 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).