Announcement Announcement Module
Collapse
No announcement yet.
Display Errors attached to command on jsp Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Display Errors attached to command on jsp

    I am using multiaction controller with the form attached to command obj. If I associate errors to my command, how can I display these errors on the jsp?
    For complete description, please see:
    http://forum.springsource.org/showthread.php?t=65328

  • #2
    Team,

    Here is the code I have:
    Code:
        /*
         * This method is called when  admin enters customer number and selects "Retrieve Customer Information"
         */
        public ModelAndView getCustomer(HttpServletRequest request, HttpServletResponse response, CustomerEntity customerEntity)
                throws ServletException, IOException,Exception { 
    
            
    				ServletRequestDataBinder binder = createBinder(request, customerEntity);
    				binder.bind(request);
            ModelAndView modelAndView = null;
            Errors errors = binder.getBindingResult();
            Map model = binder.getBindingResult().getModel();
    
    
    				customerNumber = customerEntity.getCustomerNum();
    				customerEntity  = adminService.getCustomer(customerEntity.getCustomerNum());
    				//no customernum exists in DB
    
    				if(customerEntity == null){
    
    						customerEntity = new CustomerEntity();
    						customerEntity.setCustomerNum(customerNumber);
    
    
    						//Error 1
    						String[] codes = new String[]{"admin.chair.add.customerNotFound"};
    						ObjectError error = new ObjectError("CustomerEntity", codes, null, "Customernumber not found!");
    						binder.getBindingResult().addError(error);
    `
    						//Error2
    						errors.reject("11", "Customernumber not found11");
    				}
    				model.put("customerEntity", customerEntity);
    				modelAndView = new ModelAndView("/admin/addChairProfile");
    				modelAndView.addAllObjects(model);
    
    
    				//testing --> Printing two errors successfully
    				Map mp = modelAndView.getModel();
    				for (Object obj : mp.entrySet()) {
    						Map.Entry pair = (Map.Entry)obj;
    						System.out.println(pair.getKey() + " = " + pair.getValue());
    						logger.debug(pair.getKey() + " = " + pair.getValue());
    				}
    
            return modelAndView;
        }
    My JSP:
    Code:
    <spring:hasBindErrors name="customerEntity">
       <p>There were ${errors.errorCount} error(s) in total:</p>
       <ul>
          <c:forEach var="errMsgObj" items="${errors.allErrors}">
             <li>
                <spring:message code="${errMsgObj.code}" text="${errMsgObj.defaultMessage}"/>
             </li>
          </c:forEach>
       </ul>
    </spring:hasBindErrors>
    
    <form:form  method="POST" action="${..}" commandName="customerEntity" onsubmit="return ..();">     
    ....
    I am not seeing any errors on the screen. Not sure what is the mistake I am doing. Can somebody help?

    Comment


    • #3
      First off, you don't want to pass CustomerEntity into the method since that will trigger binding already. Remove that argument. Instead the command should be instantiated inside the method instead.

      Second, your calling bindingResult.getModel() and then adding a custom error. Since getModel() creates a new HashMap each time, your custom error is not going to make it through. You need to call the bindingResult.getModel() after you have added ALL errors to the BindingResult. Just after you created the ModelAndView. Of course adding it to the ModelAndView at that point.

      Third, you don't need to explicitly add the CustomerEntity object to the model. It will be added for you when use use the bindingResult.getModel() call. This call adds the command in the BindingResult.getTarget() and under the command name directly. (So it can be accessed in two different ways from inside the model).

      Now, once those are fixed you should use the <form:errors /> tag to render the errors. That would look like:

      Code:
      <form:errors path="" />
      This will show your custom error where you are using ObjectError and the reject(), which is also an ObjectError (not specific to any field in the CustomerEntity object).

      Comment


      • #4
        Thank you for your reply. I am still not getting the sequence of events.

        As per my requirements,
        REQ1:
        1. user enters cust number first and selects a button.
        2. getCustomer of multiaction controller will be called.
        3. I got to get the data relating to this customer number from DB and show it on jsp

        As per your posting in http://forum.springsource.org/showthread.php?t=65328
        Code:
        public ModelAndView saveCustomer(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        	Object command = newCommandObject(Customer.class); 
        	ServletRequestDataBinder binder = createBinder(request, command);
        ..
        If you do new for command obj, won't my member number be lost?

        Can you point me to the right page in the documentation where the steps that you have mentioned are explained. Is there an example in documentation with multiaction controller, command obj, error objs and jsp.

        Comment


        • #5
          What does "getCustomer" do? And how have you configured the MultiActionController? If "saveCustomer" is "registered" as an action, then it is a different request and will not have the command object passed in (new request new object, unless your using session binding). However, if you are calling "saveCustomer" from inside another method that is "registered", like "getCustomer", then you can safely pass in your already instantiated command object. However this would mean "getCustomer" is performing the binding and there is no need to bind in the "saveCustomer" method, since that would have already been done.

          If "getCustomer" is doing what I mention above, than you need to move the binding code from "saveCustomer" to "getCustomer" and pass the BindingResult into the "saveCustomer" method. That will allow you access to add the custom ObjectErrors, upon errors while saving to the DB. Also, in this case you should pass an already created ModelAndView into this method as well, since the "registered" action should really be the one controlling the ModelAndView.

          It really depends on your code as to what your doing. By providing only one method it is hard to determine from your description how each method is actually being called, whether by code or by a request. This makes a big difference.

          As for documentation, this is scattered about. You can read the JavaDocs or about the MultiActionController. I don't know of anything example that fully matches what your trying to accomplish. Perhaps someone else in the forums can provide one.
          Last edited by mrcritical; Dec 28th, 2008, 10:06 AM. Reason: Forgot documentation comment

          Comment


          • #6
            1. I have a form with Text fields for customer number, name, email..3 butoons.

            Form has:
            Customer number (text field) : GetCustomer button

            Customer name, cust phone ,..((text fields) --> SaveCustomer Button

            Button1: GetCustomer: when clicked, should retrieve customer info(Customer POJO) for the customer number entered.
            If customer number is not present, should display error msg.

            This calls getCustomer(req, res, Command.)
            retrieves customer info from DB
            if customer number not present, should add the errors to command to get displayed on screen.

            Button2. SaveCustomer: When selected, should get the edited information from the form and save to dB

            If errors occurs while saving to db, errors object should be associated to command obj (customer) which
            is used on the form to display errors.

            I am using multiaction controller and Customer as command object (simple pojo).

            I believe my requirement is simplest web requirement and I am not sure why I am not able to get the correct
            documentation in any of the books or on the internet. It is very frustating..

            Thank you very much for your patience.

            Comment


            • #7
              Ok, so you should not pass in the command object to the "saveCustomer" method. This is because it is a handler method and, as such, passing in the command object will signal that automatic binding should occur. The command object doesn't exist until binding occurs. So, your concern about remembering the customer number is not an issue.

              When a command object is present in the method arguments the MultiActionController with call a MethodResolver. This MethodResolver is what performs the binding. After binding, the controller passes the newly created and bound command object into the appropriate method.

              The BindingResult is not accessible outside the MethodResolver. So, if you want the BindingResult in order to add custom errors to it, you will need remove the command object from the method arguments (to prevent the MethodResolver from binding). Instead instantiate the command object inside the method and bind, in essence simulating the binding that would occur in the MethodResolver, and it will bind the request parameters to the newly created command object.

              The MultiActionController attempts to simplify multiple actions, but in doing so it complicates slightly more complex scenarios. Most people will never need to add custom error messaging.

              Comment


              • #8
                I found a work around. Here is how I solved my problem. Seems to be working fine. Let me know if this is not the right way of doing:

                My controller code
                Code:
                public class CustomerFormController extends MultiActionController {
                ..
                
                /* First method to be called> Called even before jsp is displayed. Called from other
                controller */
                public ModelAndView addCustomer(HttpServletRequest request, HttpServletResponse response)
                            throws ServletException, IOException {
                        //initializing the command obj - this is bound to form in jsp
                        Customer customer = new Customer();
                        return new ModelAndView("customerInfo","customer", customer);
                    }    
                
                }
                
                /* This is called after user enters customer number and selects "get customer info" */
                public ModelAndView getCustomer(HttpServletRequest request, HttpServletResponse response, Customer customer){
                
                		Map<String, Object> model = new HashMap<String, Object>();
                		String enteredCustomerNumber = "" ;
                		
                		//this errorList carries back the errors to form
                		ArrayList<String> errorList = null;
                
                		//since the Customer command obj is bound to form, can retrieve from command. This is same as 
                		//setting the customer in request scope.
                		enteredCustomerNumber = customer.getCustomerNumber();
                		customer  = daoImpl.getCustomer(customer.getCustomerNumber());
                
                		//no records exist in the database.
                		if(customer == null){
                				customer = new Customer();
                				customer.setCustomerNum(enteredCustomerNumber);  
                				
                				errorList = new ArrayList();
                				errorList.add(messageSource.getMessage("customerNotFound", null, request.getLocale()));
                		}
                
                		model.put("customer", customer);
                		if(errorList != null){
                				model.put("errorList", errorList);
                		}
                
                		ModelAndView modelAndView = new ModelAndView("customerInfo", model);
                
                		return modelAndView;
                }  
                
                ....
                
                }
                My jsp: customerInfo.jsp
                Code:
                <form:form  method="POST" action="${actionURL}" commandName="customer" onsubmit="return doValidate();">
                
                		<!-- display errors -->
                    <table width="800" cellpadding="3" cellspacing="3" border="1" align="center">
                    <c:forEach var="strErr" items="${errorList}">
                      <tr>
                        <td>
                            <c:out value="${strErr}"></c:out>
                        </td>
                      </tr>
                    </c:forEach>
                    </table>
                <form:input path="customerNumber" />
                
                </form:form>

                Comment


                • #9
                  Yes, it will work that way. However, it is strange that your overwriting the bound Customer object with one from the DB. It is usually bad practice to directly expose a DB object to the view. It also isn't wise to overwrite one object with another. Of course this is your decision.

                  Also note that validation errors will not be available to the view since you are creating a ModelAndView without adding BindingResult.getModel(). But if you don't need it, then it isn't a problem.

                  Comment


                  • #10
                    I am using the same domain object for the vie(command) as well as DB entity. Will this cause any problems?

                    I am seeing the validation messages that I have put in the map on the jsp.

                    Comment

                    Working...
                    X