Struts2: method attribute in <s:submit> button doesn't work

null picture null · Nov 11, 2012 · Viewed 28.3k times · Source

I have a form in jsp. There are two submit buttons: "Search" and "Add New" button. I had set each button with their own method attribute.

<s:form name="searchForm" action="employeeAction" method="post">
    <s:textfield name="id" label="Employee ID"/>
    <s:textfield name="name" label="Employee Name"/>

    <s:submit value="Search" method="doSearch"/>
    <s:submit value="Add New" method="doAddNew"/>
</s:form>

In struts.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
    "http://struts.apache.org/dtds/struts-2.3.dtd">

<struts>

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

    <package name="default" namespace="/" extends="struts-default">

        <default-action-ref name="index" />

        <global-results>
            <result name="error">/error.jsp</result>
        </global-results>

        <global-exception-mappings>
            <exception-mapping exception="java.lang.Exception" result="error"/>
        </global-exception-mappings>

    </package>

    <package name="example" namespace="/example" extends="default">

        <action name="employeeAction" class="example.EmployeeAction">
           <result name="search">/example/search.jsp</result>
           <result name="add">/example/add.jsp</result>
        </action>

    </package>
</struts>

In EmployeeAction class

public class EmployeeAction extends ActionSupport {

    private static final Logger logger = Logger.getLogger(EmployeeAction.class);

    @Override
    public String execute() throws Exception {    
        logger.info("Calling execute!");    
        return SUCCESS;
    }

    public String doSearch() throws Exception {    
        logger.info("Calling doSearch!");    
        return "search";
    }

    public String doAddNew() throws Exception {    
        logger.info("Calling doAddNew!");    
        return "add";
    }
}

The problem is when I clicked "Search" or "Add New" button, the method doSearch() or doAddNew() was never called, instead it called method execute(). What is wrong with my code above?

I'm using struts v2.3.

Answer

Andrea Ligios picture Andrea Ligios · Nov 12, 2012

Set

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

to

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

Another way is to define multiple mappings for the same Action, like

in JSP:

<s:submit value="Search"  action="employeeSearchAction" />
<s:submit value="Add New" action="employeeAddNewAction"/>

in Struts.xml

<action name="employeeSearchAction" class="example.EmployeeAction" method="doSearch">
       <result>/example/search.jsp</result>
</action>
<action name="employeeAddNewAction" class="example.EmployeeAction" method="doAddNew">
       <result>/example/add.jsp</result>
</action>

A third way is to use Wildcard Mappings.

P.S: If you go for the second one, I'll suggest, as a best practice, to use one Action for every logical action you have to perform...

If you have common data loaded / managed by both your actions, "search" and "addNew", then you can define a employeeBaseAction, extended by both employeeSearchAction and employeeAddNewAction.


EDIT

It's 2014 now, and DMI usage is unanimously discouraged (today more than ever), other than pretty useless, so I strongly suggest you to use solution n.2.