Announcement Announcement Module
Collapse
No announcement yet.
Behaviour of handleRequest() in MultiActionController Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Behaviour of handleRequest() in MultiActionController

    I extended a MultiActionController and added a bunch of methods that i mapped from my JSP page.

    public ModelAndView addAccount(req,resp)
    public ModelAndView updateAccount(req,resp)
    public ModelAndView disableAccount(req,resp)


    In my config file i had the following configuration settings
    <bean id="paramResolver" class=".....ParameterMethodNameResolver">
    <property name="methodParamNames">
    <list>
    <value>addAccount</value>
    <value>updateAccount</value>
    <value>disableAccount</value>
    </list>
    </property>
    </bean>


    I was expecting these methods to get called when i invoked each of the actions in my page however the only method that kept getting called was
    handleRequest in my controller. When i removed this from the controller code i got a 404 error The requested resource () is not available message.

    Can any one tell me why this happens and what more do i need to add to make this work?

    Thanks in advance

  • #2
    [ code][/code ] tags please when posting code/configuration.

    How are you accessing the links and what is happening really, do you get an exception somewhere?

    Comment


    • #3
      I dont get any exceptions. I keep seeing "Inside handleRequestInternal" log message. None of my methods are getting called. Attaching my code:
      Code:
      <TABLE border=0 cellpadding=2 cellspacing=1 align="center">
      		<TR>
      			<TD align="center" noWrap>
      				<input class=button type="submit" name="addAccount" value="Add New Account" onclick="dispatch('addAccount')"/>		
      			</TD>
      			<TD align="center" noWrap>
      				<input class=button type="submit" name="updateAccount" value="Update Existing Account" onclick="dispatch('updateAccount')"/>		
      			</TD>
      			<TD align="center" noWrap>
      				<input class=button type="submit" name="disableAccount" value="Disable Account" onclick="dispatch('disableAccount')"/>	
      			</TD>
      			<TD align="center" noWrap>
      				<input class=button type="submit" name="clear" value="Clear">
      			</TD>
      			<TD align="center" noWrap>
      				<input class=button type="submit" value="Exit">				
      			</TD>
      		</TR>
      	</TABLE>
      My Configuration File
      Code:
      <bean name="/actadmin.htm" class="eirapp.controller.AccountController">
      		<property name="accountManager" ref="accountManager" />
      		<property name="methodNameResolver">
      			<ref bean="paramResolver" />
      		</property>
      	</bean>
      	<bean id="paramResolver"
      		class="org.springframework.web.servlet.mvc.multiaction.ParameterMethodNameResolver">
      		<property name="methodParamNames">
      		<list>
      			<value>addAccount</value>
      			<value>updateAccount</value>
      			<value>disableAccount</value>
      		</list>
      		</property>
      	</bean>
      Controller Code
      Code:
      package eirapp.controller;
      
      import java.util.HashMap;
      import java.util.Map;
      
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;
      
      import org.apache.commons.logging.Log;
      import org.apache.commons.logging.LogFactory;
      import org.springframework.web.servlet.ModelAndView;
      import org.springframework.web.servlet.mvc.multiaction.MultiActionController;
      
      import eirapp.service.AccountManager;
      
      public class AccountController extends MultiActionController {
      
      	protected final Log logger = LogFactory.getLog(getClass());
      	private AccountManager accountManager;
      
      	public ModelAndView handleRequestInternal(HttpServletRequest request,
      			HttpServletResponse response) throws Exception {
      		logger.info("Inside handleRequestInternal");		
      		String now = (new java.util.Date()).toString();
      		Map<String, Object> myModel = new HashMap<String, Object>();
      		myModel.put("now", now);
      		myModel.put("accounts", this.accountManager.getAccounts());
      		return new ModelAndView("actadmin", "model", myModel);
      	}
      	
      	public ModelAndView addAccount(HttpServletRequest httpServletRequest,
      			HttpServletResponse httpServletResponse) {
      		logger
      				.info("******Inside AccountController addAccount Method *******");
      		return new ModelAndView("actadmin");
      	}
      
      	public ModelAndView updateAccount(HttpServletRequest httpServletRequest,
      			HttpServletResponse httpServletResponse) {
      		logger
      				.info("******Inside AccountController updateAccount Method *******");
      		return new ModelAndView("actadmin");
      	}
      
      	public ModelAndView disableAccount(HttpServletRequest httpServletRequest,
      			HttpServletResponse httpServletResponse) {
      		logger
      				.info("******Inside AccountController disableAccount Method *******");
      		return new ModelAndView("actadmin");
      	}
      
      	public void setAccountManager(AccountManager _accountManager) {
      		this.accountManager = _accountManager;
      	}
      
      	public AccountManager getAccountManager() {
      		return accountManager;
      	}
      }

      Comment


      • #4
        You mustn't override the handleRequestInternal method, that will screw up the behavior of the MultiActionController.

        Comment


        • #5
          You are overriding the handleRequestInternal method so you should be calling the super class method so that resolved methods get invoked.

          Code:
          public ModelAndView handleRequestInternal(HttpServletRequest request,
          			HttpServletResponse response) throws Exception {
          		logger.info("Inside handleRequestInternal");
          		ModelAndView modelAndView = super.handleRequestInternal(request, response);
          		String now = (new java.util.Date()).toString();
          		modelAndView.getModel().put("now", now);
          		modelAndView.getModel().put("accounts", accountManager.getAccounts());
          		return modelAndView;
          	}
          Hope this helps!

          Comment


          • #6
            so as a best practice i should avoid this approach to override as far as possible. Can you tell me why this is so?

            Comment


            • #7
              can you tell me how this will work

              Code:
              modelAndView.getModel()
              because i keep a null pointer exception and i was wondering i am not setting the model any where to begin with and hence the get will result in a null. I am sorry ... just learning this thing and i may be missing something.

              Comment


              • #8
                According to the API that method never returns null (meaning you should get an empty map) & that is how the internal implementation seems to be. Are you getting a valid ModelAndView in the first place from the super call?
                Last edited by maverickthinker; Aug 19th, 2008, 11:08 PM. Reason: more explanation

                Comment


                • #9
                  This is what i see in the log file:

                  INFO: Inside handleRequestInternal
                  Aug 20, 2008 10:40:04 AM org.springframework.web.servlet.mvc.multiaction.Mu ltiActionController handleNoSuchRequestHandlingMethod
                  WARNING: No matching handler method found for servlet request: path '/eirapp/actadmin.htm', method 'GET', parameters map[[empty]]

                  Comment


                  • #10
                    Ok...i see that in the documentation it says

                    Process the request and return a ModelAndView object which the DispatcherServlet will render. A null return value is not an error: It indicates that this object completed request processing itself, thus there is no ModelAndView to render.
                    And in my log i do see that the ModelAndView object = null. In such a case what do i do because if i execute a getModel on the ModelAndView object i am going to get a null pointer exception. Can you provide me a code snippet? That would help clear up my understanding.

                    My existing code looks like

                    Code:
                    public ModelAndView handleRequestInternal(HttpServletRequest request,
                    			HttpServletResponse response) throws Exception {
                    logger.info("Inside handleRequestInternal");
                    ModelAndView modelAndView = super.handleRequestInternal(request,
                    				response);
                    logger.info("Inside handleRequestInternal "+modelAndView);
                    String now = (new java.util.Date()).toString();
                    modelAndView.getModel().put("now", now);
                    modelAndView.getModel().put("accounts", accountManager.getAccounts());
                    return modelAndView;
                    
                    }
                    Thanks again.

                    Comment


                    • #11
                      Originally posted by va1224 View Post
                      This is what i see in the log file:

                      INFO: Inside handleRequestInternal
                      Aug 20, 2008 10:40:04 AM org.springframework.web.servlet.mvc.multiaction.Mu ltiActionController handleNoSuchRequestHandlingMethod
                      WARNING: No matching handler method found for servlet request: path '/eirapp/actadmin.htm', method 'GET', parameters map[[empty]]
                      I think this is where the problem is. The controller is getting a "GET" request without any parameters & is unable to resolve a method from the method resolver to execute the action. What you could do is in your bean definition add a default method as below & let it handle all the "GET" requests similar to the showForm in SimpleFormController.

                      Code:
                      <bean id="paramResolver"
                      		class="org.springframework.web.servlet.mvc.multiaction.ParameterMethodNameResolver">
                                      <property name="defaultMethodName" value="showForm"/>
                      		<property name="methodParamNames">
                      		<list>
                      			<value>addAccount</value>
                      			<value>updateAccount</value>
                      			<value>disableAccount</value>
                      		</list>
                      		</property>
                      	</bean>
                      and in your controller

                      Code:
                      public ModelAndView showForm(HttpServletRequest httpServletRequest,
                      			HttpServletResponse httpServletResponse) {
                      		return new ModelAndView("pageYouWantToShowOnInitialPageDisplay");
                      	}

                      Comment


                      • #12
                        Thank you very much. That worked for me. One last question do i have to always have this default method to handle GETS in my controller?

                        For everyone, in case you have struggled like me to make this controller work.

                        Case

                        How do we go about using a MultiActionController to provide a simple CRUD JSP.

                        JSP PAGE
                        Code:
                        <!-- Form & Javascript -->
                        <script type="text/javascript">
                        function dispatch(_param) {
                        document.eirform.param.value = _param;
                        }			
                        </script>
                        <form:form name="eirform" method="POST">
                        <input type="hidden" name="param" />
                        
                        <!-- HTML Snippet -->
                        <TABLE border=0 cellpadding=2 cellspacing=1 align="center">
                        		<TR>
                        			<TD align="center" noWrap>
                        				<input class=button type="submit" name="addAccount" value="Add New Account" onclick="dispatch('addAccount')"/>		
                        			</TD>
                        			<TD align="center" noWrap>
                        				<input class=button type="submit" name="updateAccount" value="Update Existing Account" onclick="dispatch('updateAccount')"/>		
                        			</TD>
                        			<TD align="center" noWrap>
                        				<input class=button type="submit" name="disableAccount" value="Disable Account" onclick="dispatch('disableAccount')"/>	
                        			</TD>
                        			<TD align="center" noWrap>
                        				<input class=button type="submit" name="clear" value="Clear">
                        			</TD>
                        			<TD align="center" noWrap>
                        				<input class=button type="submit" value="Exit">				
                        			</TD>
                        		</TR>
                        	</TABLE>
                        Spring Controller Config File

                        <bean name="/actadmin.htm" class="eirapp.controller.AccountController">
                        <property name="accountManager" ref="accountManager" />
                        <property name="methodNameResolver">
                        <ref bean="paramResolver" />
                        </property>
                        </bean>
                        <bean id="paramResolver" class="org.springframework.web.servlet.mvc.multiac tion.ParameterMethodNameResolver">
                        <property name="defaultMethodName" value="showForm" />
                        <property name="methodParamNames">
                        <list>
                        <value>addAccount</value>
                        <value>updateAccount</value>
                        <value>disableAccount</value>
                        </list>
                        </property>
                        </bean>

                        Note: The line in RED was required to make this work.
                        I think this is where the problem is. The controller is getting a "GET" request without any parameters & is unable to resolve a method from the method resolver to execute the action. What you could do is in your bean definition add a default method as below & let it handle all the "GET" requests similar to the showForm in SimpleFormController.

                        Controller Code

                        Code:
                        package eirapp.controller;
                        
                        import java.util.HashMap;
                        import java.util.Map;
                        
                        import javax.servlet.http.HttpServletRequest;
                        import javax.servlet.http.HttpServletResponse;
                        
                        import org.apache.commons.logging.Log;
                        import org.apache.commons.logging.LogFactory;
                        import org.springframework.web.servlet.ModelAndView;
                        import org.springframework.web.servlet.mvc.multiaction.MultiActionController;
                        
                        import eirapp.service.AccountManager;
                        
                        public class AccountController extends MultiActionController {
                        
                        	protected final Log logger = LogFactory.getLog(getClass());
                        	private AccountManager accountManager;
                        
                        	public ModelAndView showForm(HttpServletRequest httpServletRequest,
                                    HttpServletResponse httpServletResponse) {
                        		String now = (new java.util.Date()).toString();
                        		Map<String, Object> myModel = new HashMap<String, Object>();
                        		myModel.put("now", now);
                        		myModel.put("accounts", this.accountManager.getAccounts());
                        		return new ModelAndView("actadmin", "model", myModel);
                            }
                        	
                        	public ModelAndView handleRequestInternal(HttpServletRequest request,
                        			HttpServletResponse response) throws Exception {
                        		logger.info("Inside handleRequestInternal");
                        		ModelAndView modelAndView = super.handleRequestInternal(request,
                        				response);
                        		String now = (new java.util.Date()).toString();
                        
                        		modelAndView.getModel().put("now", now);
                        		modelAndView.getModel().put("accounts", accountManager.getAccounts());
                        		return modelAndView;
                        	}
                        
                        	public ModelAndView addAccount(HttpServletRequest httpServletRequest,
                        			HttpServletResponse httpServletResponse) {
                        		logger.info("******Inside AccountController addAccount Method *******");
                        		return new ModelAndView("actadmin");
                        	}
                        
                        	public ModelAndView updateAccount(HttpServletRequest httpServletRequest,
                        			HttpServletResponse httpServletResponse) {
                        		logger
                        				.info("******Inside AccountController updateAccount Method *******");
                        		return new ModelAndView("actadmin");
                        	}
                        
                        	public ModelAndView disableAccount(HttpServletRequest httpServletRequest,
                        			HttpServletResponse httpServletResponse) {
                        		logger
                        				.info("******Inside AccountController disableAccount Method *******");
                        		return new ModelAndView("actadmin");
                        	}
                        
                        	public void setAccountManager(AccountManager _accountManager) {
                        		this.accountManager = _accountManager;
                        	}
                        
                        	public AccountManager getAccountManager() {
                        		return accountManager;
                        	}
                        }
                        Many thanks again.

                        Comment


                        • #13
                          Yes if you want to use the MultiActionController to display the initial form, then there should be some way for the controller to know what to do on a GET. And I think default method is the best way unless you want to pass in a parameter in the GET which maps to a method, in this case the "showForm".

                          Comment

                          Working...
                          X