1

We currently use the following javascript to submit the form when one of the field values change.

var url = "project/location/myAction.action?name="+ lname ; 
document.forms[0].action = url;
document.forms[0].submit();

which calls the following Struts2 action

<action name="myAction" class="project.location.NameAction">
    <result name="success" type="tiles">myAction</result>   
</action>

which then goes to the execute() method of the Action class NameAction where I have to check to see if the form was submitted from the javascript.

I would prefer to call the findName() method in NameAction directly from the javascript. In other words I want the javascript to act like the following jsp code.

<s:submit method="findName" key="button.clear" cssClass="submit" >
Roman C
  • 49,761
  • 33
  • 66
  • 176
ponder275
  • 903
  • 2
  • 12
  • 33
  • Do you know that such submit doesn't work by default? – Roman C Mar 03 '16 at 17:10
  • @Roman Are you referring to the javascript submit or the struts submit? – ponder275 Mar 03 '16 at 18:15
  • If you want javascript act like the struts submit, you should be aware that struts submit shouldn't have method attribute, see my answer below. You should elaborate what do you mean by *act like*. – Roman C Mar 03 '16 at 18:19

3 Answers3

2

There are different ways to achieve what you want, but probably the simpler is to map different actions to different methods of the same action class file, eg. with annotations:

public class NameAction {

    @Action("myAction")
    public String execute(){ ... }

    @Action("myActionFindName")
    public String findName(){ ... }

}

or with XML:

<action name="myAction" class="project.location.NameAction">
    <result name="success" type="tiles">myAction</result>   
</action>

<action name="myActionFindName" class="project.location.NameAction" method="findName">
    <result name="success" type="tiles">myAction</result>   
</action>

Then in javascript:

var url = "project/location/myActionFindName.action?name="+ lname ;
Andrea Ligios
  • 49,480
  • 26
  • 114
  • 243
  • If I use a different action to map to the same action class do I lose any values already entered? I need the javascript to send me to the same page so I can save any entered values before I go to a different action to process the data. I thought of using the XML like you showed but I didn't know if I would lose the data already entered on the page. – ponder275 Mar 03 '16 at 18:22
  • 1
    Absolutely no, that's the advantage of sharing the same java file to two actions: you share all the attributes, the getters and the setters. You will find (when landing on the JSP for the second time, after executing`findName()`) all the attributes you had in the JSP page before calling `findName()`, the only thing missing would be the static data, like select boxes elements. But that also happens with a single action when validation or conversion errors happens... that's what `prepare()` (along with other alternative methods) is for. Read more http://stackoverflow.com/a/25682007/1654265 – Andrea Ligios Mar 03 '16 at 20:38
  • Also don't use DMI... even if it is still possible to enable it, avoid it like the plague. – Andrea Ligios Mar 03 '16 at 20:39
  • The project I am working on was set up by someone else so I'm not sure I can get it changed. This was his first project with Struts2 after years of using Struts1. If you don't use DMI do you use annotations or XML per your example to accomplish the same thing? – ponder275 Mar 03 '16 at 23:46
  • Well, you don't need to change the code of the actions if you can't, just avoid using DMI while writing new actions. XML is the old way, annotations are provided by the Convention plugin, that soon will become the standard, but you need to use *all* xml or *all* annotations, you can't mix – Andrea Ligios Mar 04 '16 at 00:08
  • 1
    Should I avoid using the `method` attribute of the `` tag also and instead use the `action` attribute along with xml? – ponder275 Mar 07 '16 at 18:07
1

You can use the same action class to map different methods using method attribute

<action name="myAction" class="project.location.NameAction" method="findName">

By default the method attribute if omitted uses execute method.

This approach requires changing the action name and hence URL to map the action. If you want to keep the same URL for different actions, then you should pass a method name as parameter to the action. Then in execute method parse this parameter for the method name and call the corresponding method.

When DMI was enabled in the previous versions to call the method you could use a method attribute of the s:submit tag. Currently the method: parameter name is blocked by the params interceptor, even if it gets to the action mapper.

You also read other possibilities from the How to exclude the submit action from a list of parameters in struts2.

Roman C
  • 49,761
  • 33
  • 66
  • 176
  • We currently parse in the execute method as you suggested but I wanted to simplify the execute method if I could. We use the method attribute of the s:submit tag all of the time and it is still listed in the Struts2 documentation so I must not understand your point about the parameter name being blocked. – ponder275 Mar 03 '16 at 18:30
  • 1
    If you use s:submit tag with the method attribute then you should have DMI is enabled. The point that DMI was disabled by default due security reason and changes affected the functionality of the s:submit tag that doesn't work with method attribute if DMI is disabled. You can post `struts.xml` to see your configuration. – Roman C Mar 03 '16 at 18:39
  • We do have it enabled. – ponder275 Mar 03 '16 at 20:30
  • If you have it enabled, then you can modify url with the method included `myAction.action!findName` – Roman C Mar 04 '16 at 09:06
  • @ponder275 Did you find how to use DMI or you need more info? If you use mapping a method to the url then you have to change the url to execute different actions, however you can keep it the same if you are doing post request. – Roman C Mar 05 '16 at 10:02
  • I have changed the code to call a different Struts action which uses the same java file but calls the desired method.. It appears to be working but I have to finish debugging it on Monday. Thanks for the follow-up. I will post how it worked after I finish debugging it. – ponder275 Mar 06 '16 at 01:10
0

For completeness here is how I implemented the advice from Andrea and Roman.

When the user enters data in both the firstName and lastName fields we show them a list of names to choose from to fill in the rest of the form. The jsp is

                <div class="row">
                <div class=" col-sm-2 col-xs-12 no-padding-right text-right"><span class="required">*</span><label class="pull-right" for="lastNameId"><s:text name="lastName"></s:text>:</label></div>             
                <div class=" col-sm-2 col-xs-12 no-padding-right ">
                    <s:textfield name="lastName"  id="lastNameId" maxlength="50" onchange ="dirtyFlag();" onblur="selectNameInfo(\'newRequest\');" class="form-control"/>
                </div>
                <div class=" col-sm-2 col-xs-12 no-padding-right text-right " ><span class="required">*</span><label class="pull-right" for="firstNameId"><s:text name="firstName"></s:text>:</label></div>             
                <div class=" col-sm-2 col-xs-12 no-padding-right ">
                    <s:textfield name="firstName" id="firstNameId" maxlength="50" onchange ="dirtyFlag();" onblur="selectNameInfo(\'newRequest\');" class="form-control"/>
                </div>   
            </div>      

The javascript is

        function selectNameInfo(formId) {
        var lastName = document.forms[0].elements["lastNameId"].value;
        var firstName = document.forms[0].elements["firstNameId"].value;

        if(lastName != "" && firstName != ""){
        clearDirtyFlag(); 
        var oldAction = document.getElementById(formId).action;
        var actionName = document.getElementById(formId).name;
        var url = oldAction.replace(actionName,actionName+"_NameSearch");
            document.forms[0].action = url;
            document.forms[0].submit();
        };
    }

The javascript forms a url by adding "_NameSearch" to the action of the form calling the selectNameInfo() function. In this case the new action is newRequest_NameSearch which goes to the following xml which calls the generateNameList() method of the action class without using DMI which was my original question.

    <action name="newRequest_NameSearch" class="gov.mo.dnr.egims.controller.evaluation.NewRequestAction" method = "generateNameList">           
        <result name="success" type="tiles">newRequest</result>
        <result name="nameSearch" type="tiles">selectNameInfo</result>
        <result name="error" type="tiles">error</result>            
    </action>
ponder275
  • 903
  • 2
  • 12
  • 33