2

I want to call to different actions in the same form. In a previous app I developed it works nice,(see code below), but now I have switched versions from Struts 2.1.6 to 2.5.8 and it's not working.

In the answer of this question, the use of different actions in the same form is discouraged. Instead, the author proposes to call different methods inside the same action. That's fine, but in my app I need to call these actions/methods from several places, not only this form, so I would prefer to separate the action calls in the struts.xml file.

Note: I'm calling "action" from the struts.xml point of view. Each action calls to a different method from the same class *Action.java. All actions of this .java class are grouped in the same package of the struts.xml

Form in list.jsp:

<s:form name="changeStatusForm" theme="simple" id="formList">
    <s:hidden id="idSelectedRow" name="idSelectedRow"/>
    <s:submit key="global.showMore" action="showMore" />
    <s:submit key="global.edit" action="edit"/>
    <s:submit key="global.delete" action="delete"/>
</s:form>

The jsp is a list of objects. When I click in one row, a menu with several options appear (the ones of the form). The id of the desired object is gathered in the variable idSelectedRow.

struts.xml

<package name="object" namespace="/object" extends="authenticate-default">
    <result-types>
        <result-type name="tiles" class="org.apache.struts2.views.tiles.TilesResult"/>
    </result-types>
    <global-results>
        <result name="error" type="tiles">error</result>
        <result name="errorLogin" type="tiles">errorLogin</result>
    </global-results>

    <action name="list" method="list" class="actions.ObjectAction"> 
        <result name="success" type="tiles">listObject</result>
        <result name="input" type="redirect">list</result>
        <result name="error" type="tiles">listObject</result>
    </action>
    <action name="showMore" method="showMore" class="actions.ObjectAction">
        <result name="success" type="tiles">showMore</result>
    </action>
    <action name="edit" method="edit" class="actions.ObjectAction">
        <result name="success" type="tiles">edit</result>
    </action>
    <action name="delete" method="delete" class="actions.ObjectAction">
        <result name="success" type="tiles">list</result>
    </action>

    .
    .
    .

</package>

Object.java:

public class ObjectAction extends BaseActionCRUD implements ModelDriven<ObjectDTO> {
    ...
    public String showMore() {
        ...
        return SUCCESS;
    }
    public String edit() {
        ...
        return SUCCESS;
    }
    public String delete() {
        ...
        return SUCCESS;
    }
    public String list() {
        ...
        return SUCCESS;
    }
    ...
}

So, how can I do this same thing in Struts 2.5.8?

Right now, the method executed in ObjectAction.java is always list() instead of the selected one. That's because the action that redirects to list.jsp is list.

Thanks!

Community
  • 1
  • 1
mardo
  • 581
  • 1
  • 7
  • 11

1 Answers1

2
  1. Extremely important: migrate to 2.5.10.1, not to 2.5.8.
    Any 2.5 version prior to 2.5.10.1 (and any recent 2.3 version prior to 2.3.32) is vulnerable to a critical security issue, S2-045.

  2. Since 2.3.15.3, you need to explicitly enable the action: prefix (that is generated by the action="" attribute in the <s:submit> tags) in struts.xml with:

    <constant name="struts.mapper.action.prefix.enabled" value="true"/>
    
  3. The method="" prefix, called DMI (Dynamic Method Invocation), which usage is suggested in the 2011's answer you've linked, it is now deprecated and completely discouraged.

Also the action: prefix method is discouraged against more robust solutions (like changing the target of the <form> with Javascript according to which of the <submit> buttons has been pressed) but, if you want, you can still enable and use it, there are no big problems with it.

Andrea Ligios
  • 49,480
  • 26
  • 114
  • 243
  • +1 and agree with @Andrea Ligios. Even so, just because Struts allows you to map multiple actions to the same class, that doesn't mean you should do so. Instead, consider refactoring your actions so each has a single responsibility. That would reduce coupling, improve cohesion of your action classes, simplify configuration and unit testing, and reduce defects. – Michael Peacock May 09 '17 at 14:32
  • I added the constant in struts.xml and is working fine. I have already thought about the Javascript solution, but I didn't want to complicate things. However, I will consider it. Thanks about the version warning. You are my hero! – mardo May 09 '17 at 14:48
  • You're welcome mardo :) @MichaelPeacock related: http://stackoverflow.com/a/35689796/1654265 (and http://stackoverflow.com/a/13530194/1654265) – Andrea Ligios May 09 '17 at 15:03