Search code examples
struts2struts2-namespace

struts2 action not calling properly


On default I want my struts2 app to forward to an action:

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

<struts>

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

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


        <action name="Login_*" method="{1}" class="myApp.SessionManager">
            <result name="input">/myApp/Login.jsp</result>
            <result type="redirectAction">Menu</result>     
        </action>

    </package>

    <package name="default" namespace="/" extends="struts-default">
        <default-action-ref name="index" />
        <action name="index">
            <result type="redirectAction">
                <param name="actionName">Login_input.action</param>
                <param name="namespace">/myApp</param>
            </result>
        </action>
    </package>


</struts>

I'm looking for the application to call SessionManager.input(), but instead it calls SessionManager.execute().


Solution

  • You don't want typically a public input() method. The most basic and typical scenario for an Action is:

    • The Action is intended to "do something" (one thing), and this action needs some user input.
    • The Action does than something in the method execute()
    • If the Action did succesfully that something, it returs SUCCESS. This triggers a result informative JSP page.
    • If the Action didn't get the user input (because there wasn't any, or because it was insufficient or wrong) it returns INPUT. This triggers a "input form" JSP so that the user can fill the data and (re)try the action.

    Now, this basic scenario can be coded in several ways, among them:

    1) Two different mappings, one for the input form, other for the execution

    <!-- default action class: execute does nothing, returns SUCCES -->
    <action name="ActionXXXShowForm"> 
                    <result>/myApp/XXXForm.jsp</result>
    </action>
    
    <action name="ActionXXX" class="myApp.XXXAction"> 
                    <result name="input">/myApp/XXXForm.jsp</result>
                    <result>/myApp/XXXDone.jsp</result>
    </action>
    

    2) Just one mapping

    <action name="ActionXXX"  class="myApp.XXXAction"> 
                    <result name="input">/myApp/XXXForm.jsp</result>
                    <result>/myApp/XXXDone.jsp</result>
    </action>
    

    Both are very similar (specially if your are doing programmatic validation). In both cases, we have only a "struts" method in the action (execute), which is good practice as our action only "does one thing". But in the second case, we need to deal with the case in which no data is post, and dont emit an error message for that case.

    Example: In case 1:

    public class XXXAction extends ActionSupport {
        ...    
        public String execute() throws Exception {
            if(! inputOk()) return INPUT;
             // .. do your stuff
            return SUCCESS;
        }
    
        private boolean inputOk() {
           // ... check your inputs - sort of programatic validation
           if( surname == null ) addActionError("no surname");
           // .... more checks
           return ! hasActionErrors());
        }
    
    }
    

    In case 2 you modify it slightly:

    public class XXXAction extends ActionSupport {
        ....    
        public String execute() throws Exception {
            if( emptyInput() ) return INPUT;  // no error messages in this case
            if(! inputOk()) return INPUT;
             // .. do your stuff
            return SUCCESS;
        }
    
        private boolean inputOk() {
           // same as before
        }
    
        private boolean emptyInput() {
           // detect no input was sent. do not emit errors herer
        }
    }