4

I'm trying to exclude a submit action from a parameter list.

The following is the action class:

@Namespace("/admin_side")
@ResultPath("/WEB-INF/content")
@InterceptorRefs({
    @InterceptorRef(value="validation", params={"excludeMethods", "test"}),
    @InterceptorRef(value="params", params={"excludeParams", "action:postAction"})})
public final class TestAction extends ActionSupport implements Serializable, ValidationAware
{
    private static final long serialVersionUID = 1L;
    private static final String SUCCESS = "success";

    private String name;

    @Action(value = "test", results = {
    @Result(name="success", location="Test.jsp"),
    @Result(name = "input", location = "Test.jsp")})
    public String test() throws Exception
    {
        System.out.println("name = "+name);
        return SUCCESS;
    }

    @Action(value = "postAction", results = {
    @Result(name="success", location="Test.jsp"),
    @Result(name = "input", location = "Test.jsp")})
    public String postAction()
    {
        System.out.println("Post invoked");
        System.out.println("name = "+name);
        return SUCCESS;
    }

    @RequiredStringValidator(type= ValidatorType.FIELD, message = "The name is required.")
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public void validate()
    {
        if(!hasErrors()&&name.length()<2)
        {
            addFieldError("name", "The name must compose of 2 letters.");
        }
    }
}

The Test.jsp page:

<s:form namespace="/admin_side" action="test" validate="true">
    <s:textfield id="name" name="name" label="Name"/>
    <s:submit id="btnSubmit" name="btnSubmit" value="Submit" action="postAction"/>
</s:form>

The generated HTML code for <s:submit> would be like as follows.

<input type="submit" id="btnSubmit" name="action:postAction" value="Submit"/>

The @InterceptorRef above the class:

@InterceptorRef(value="params", params={"excludeParams", "action:postAction"})

doesn't seem to work. The method postAction() is never invoked causing the following warning to be issued.

Dec 24, 2013 10:49:16 PM com.opensymphony.xwork2.interceptor.ParametersInterceptor warn WARNING: Parameter [action:postAction] is on the excludeParams list of patterns!


In the struts.properties file, I have the following properties until now.

struts.enable.DynamicMethodInvocation=false
struts.devMode=false
struts.ui.theme=simple

struts.convention.package.locators=actions
struts.convention.action.suffix=Controller
struts.convention.action.mapAllMatches=true

struts.convention.result.path=/WEB-INF/content //No need. It is the default.
struts.mapper.action.prefix.enabled=true

I'm using Struts 2.3.16.


Why doesn't it exclude the submit button's parameter? How to invoke the postAction() method, when <s:submit> is clicked?

Roman C
  • 49,761
  • 33
  • 66
  • 176
Tiny
  • 27,221
  • 105
  • 339
  • 599

1 Answers1

4

Why doesn't it exclude the submit button's parameter?

Because this parameter is in the excludeParams list of the params interceptor in the defaultStack which your action is referenced by default.

How to invoke the postAction() method, when <s:submit> is clicked?

In this question you ask how to invoke a method (not an action). The difference between the action and method the first is mapped to a specified URL using a namespace and action name. So, to invoke a method other than an action you should turn DMI on. Struts, since 2.3.16 turned off this option. The following configuration constant to use in struts.xml:

<constant name="struts.enable.DynamicMethodInvocation" value="true"/>

and use a method attribute instead of action attribute.

<s:form namespace="/admin_side" action="test">
  <s:submit value="Submit" method="postAction"/>
</s:form> 

as I already told in this answer.

If you don't want to use DMI, then you have an option to enable action: prefix to the parameter

<constant name="struts.mapper.action.prefix.enabled" value="true"/>

and use an action mapped to the method postAction

<s:form namespace="/admin_side" action="test">
  <s:submit value="Submit" action="postAction"/>
</s:form> 

and use annotation without params.excludeParams.

@InterceptorRef(value="defaultStack" params={"validation.excludeMethods", "test"})

The warning that action:postAction parameter is on exclude list still persist, but it appears only if the struts.devMode=true. You shouldn't worry about it because it warns all parameters from the excludeParams list that passed through. To turn off devMode you should set

<constant name="struts.devMode" value="false" />
Roman C
  • 49,761
  • 33
  • 66
  • 176
  • Actually, I want the method `postAction()` to be mapped by a given `action` of `` (not `method`), since DMI is discouraged. This interceptor above the action class - `@InterceptorRef(value="defaultStack", params={"params.excludeParams", "action:postAction", "validation.excludeMethods", "test"})})` still cannot remove this warning - `WARNING: Parameter [action:postAction] is on the excludeParams list of patterns!`. I cannot find relavent/suitable examples on the internet. – Tiny Dec 25 '13 at 18:08
  • Then it issues this warning - `WARNING: Parameter [action:postAction] didn't match acceptedPattern pattern!` – Tiny Dec 25 '13 at 19:49
  • Then it causes these warnings to be issued : `WARNING: Parameter [action:postAction] didn't match acceptParams list of patterns!` and `WARNING: Parameter [name] didn't match acceptParams list of patterns!` – Tiny Dec 25 '13 at 20:40
  • I have tried this : `@InterceptorRef(value="defaultStack", params={"params.excludeParams", "^action:(?!postAction$)\\w*$", "params.acceptParamNames", "action:postAction"})`. It shows the warnings as indicated by the previous comment. – Tiny Dec 25 '13 at 20:43
  • This `@InterceptorRef(value="defaultStack", params={"params.excludeParams", "^action:(?!postAction$)\\w*$", "params.acceptParamNames", "^action:(?!postAction$)\\w*$","params.acceptParamNames", "name",}` and this `@InterceptorRef(value="defaultStack", params={"params.excludeParams", "action:postAction", "params.acceptParamNames", "action:postAction","params.acceptParamNames", "name",}` both issuse the same warning : `WARNING: Parameter [action:postAction] didn't match acceptParams list of patterns!` – Tiny Dec 25 '13 at 21:15
  • Is it really possible to map an action of `` to a method in a corresponding action class? It doesn't seem possible. You seem to have been using the Struts framework for a long time and must have faced and solved this problem in the past, a long time ago! How did you actually solve it? Could you please tell me? – Tiny Dec 26 '13 at 03:41
  • I thought you put me in the wrong direction, see updated answer. – Roman C Dec 26 '13 at 13:55
  • I have done according to the update but the method in the action class, `postAction()` is never invoked. Removed `excludeParams`, set `struts.mapper.action.prefix.enabled` to true in `struts.properties` (yes, the system is able to find `struts.properties` on the classpath, I have verified it). – Tiny Dec 26 '13 at 14:55
  • 1
    No really sorry. It works according the updated answer. The method was not invoked only because of validations. I was submitting the page without any values in the fields preventing it from being validated. Thank you very much and sorry for much concerned. – Tiny Dec 26 '13 at 15:16
  • 1
    It should be invoked, If you have validation errors in the validate method then it will not invoke, the INPUT result is returned. – Roman C Dec 26 '13 at 15:16
  • Does activating `struts.mapper.action.prefix.enabled` opens any security vulnerability? – Stephan Mar 20 '17 at 16:36