Announcement Announcement Module
Collapse
No announcement yet.
How to do validation using MultiActionController Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • How to do validation using MultiActionController

    Dear friends,

    I am trying to validation with MultiActionController, Could anyone help me in this regard?

    Could anyone have sample code how to do validation with MultiActionController?

    ----------

    I am doing sample 'phonebook' application using MultiActionController, here is my code,

    public class PhoneBookController extends MultiActionController
    {
    public ModelAndView newcontactHandler(HttpServletRequest request, HttpServletResponse response)
    {
    try
    {
    Contact newContact = (Contact)newCommandObject(Contact.class);
    bind(request, newContact);
    phoneBook.addNewContact(newContact);
    return new ModelAndView("add-success");
    }
    catch(Exception e){}
    }
    }

    -----------------------------------

    here is my bean definition file,

    <bean id="phoneBookController" class="controller.PhoneBookController">
    <property name="methodNameResolver" ref="internalPathMethodNameResolver"/>
    <property name="phoneBook" ref="phoneBook"/>
    <property name="validators" ref="contactInfoValidator"/>
    </bean>

    <bean id="contactInfoValidator" class="validator.ContactInfoValidator"/>


    but I am getting the following error,******************
    org.springframework.web.bind.ServletRequestBinding Exception: Errors binding onto object 'command'; nested exception is org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBinding Result: 2 errors
    Field error in object 'command' on field 'contactName': rejected value []; codes [contactName.emptyerror.command.contactName,contact Name.emptyerror.contactName,contactName.emptyerror .java.lang.String,contactName.emptyerror]; arguments []; default message [null]
    Field error in object 'command' on field 'phoneNumber': rejected value []; codes [phoneNumber.emptyerror.command.phoneNumber,phoneNu mber.emptyerror.phoneNumber,phoneNumber.emptyerror .java.lang.String,phoneNumber.emptyerror]; arguments []; default message [null]

  • #2
    As you might understand, a validator is only applicable for a form based controller. And a MultiaActionController is NOT a form based controller.

    Comment


    • #3
      Then, could you tell me what is the purpose of the following method,

      public final void setValidators(Validator[] validators)

      When I use the above method,

      I am ending up with the following error,
      org.springframework.web.bind.ServletRequestBinding Exception: Errors binding onto object 'command'; nested exception is org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBinding Result: 2 errors

      Field error in object 'command' on field 'contactName': rejected value []; codes [contactName.emptyerror.command.contactName,contact Name.emptyerror.contactName,contactName.emptyerror .java.lang.String,contactName.emptyerror]; arguments []; default message [null]

      Field error in object 'command' on field 'phoneNumber': rejected value []; codes [phoneNumber.emptyerror.command.phoneNumber,phoneNu mber.emptyerror.phoneNumber,phoneNumber.emptyerror .java.lang.String,phoneNumber.emptyerror]; arguments []; default message [null]

      Thanks

      Comment


      • #4
        You can of course do validation for multiactioncontroller.

        The error you got is not from validation first of all. it is from the data binding. The data binder is not able to bind the input to the command object. Your code hasn't reached validation.

        I don't know if you really understand the multiactioncontroller or not.

        In multiactioncontroller source, this is really important to understand. what is your command object.

        // If last parameter isn't of HttpSession type, it's a command.
        if (paramTypes.length >= 3 &&
        !paramTypes[paramTypes.length - 1].equals(HttpSession.class)) {
        Object command = newCommandObject(paramTypes[paramTypes.length - 1]);
        params.add(command);
        bind(request, command);
        }

        There is a final method invokeNamedMethod. It includes this piece of code. What it really means is the flexibility of command object of this type of controller. So, you can want to pass your command object as the 3rd parameter to your method signature: public ModelAndView newcontactHandler(HttpServletRequest request, HttpServletResponse response, Phonebook phoneBook) for example.

        Comment


        • #5
          hi jerry.yan.mj,

          Yes, I am unable to understand the MultiActionController to apply Validation.

          Actually command class is Contact.java containing 2 attributes contactName and phoneNumber.

          I have written validator class called ContactInfoValidator.java which implements the interface validator

          and mycontroller extends MultiActionController,

          As you suggested I have used 3 argument handler

          public ModelAndView newcontactHandler(HttpServletRequest request, HttpServletResponse response, Contact newContact)

          but again I end up with the same error

          *****************************************
          I am ending up with the following error,
          org.springframework.web.bind.ServletRequestBinding Exception: Errors binding onto object 'command'; nested exception is org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBinding Result: 2 errors

          Field error in object 'command' on field 'contactName': rejected value []; codes [contactName.emptyerror.command.contactName,contact Name.emptyerror.contactName,contactName.emptyerror .java.lang.String,contactName.emptyerror]; arguments []; default message [null]

          Field error in object 'command' on field 'phoneNumber': rejected value []; codes [phoneNumber.emptyerror.command.phoneNumber,phoneNu mber.emptyerror.phoneNumber,phoneNumber.emptyerror .java.lang.String,phoneNumber.emptyerror]; arguments []; default message [null]
          ***************************



          Could u tell me exactly how to do validation with the MultiActionController?


          Thanking you
          Last edited by saravanansivaji; Jun 1st, 2009, 11:51 PM.

          Comment


          • #6
            Could you please attach your validator source?

            Could you please attach your validator source?

            Comment


            • #7
              hi jerry.yan.mj,

              First, Thank u for ur reply. Here is my complete code,

              ****************
              The following is my domain class, Contact.java
              ****************

              package domain;

              import java.io.Serializable;

              public class Contact implements Serializable
              {
              String contactName;
              String phoneNumber;

              public String getContactName() {
              return contactName;
              }
              public void setContactName(String contactName) {
              this.contactName = contactName;
              }
              public String getPhoneNumber() {
              return phoneNumber;
              }
              public void setPhoneNumber(String phoneNumber) {
              this.phoneNumber = phoneNumber;
              }
              }
              -----------------------------------------------------------------

              The following is my validator class, ContactInfoValidator.java

              package validator;

              import org.springframework.validation.*;

              import domain.Contact;

              public class ContactInfoValidator implements Validator {

              public boolean supports(Class cls)
              {
              return Contact.class.equals(cls);
              }

              public void validate(Object obj, Errors errors)
              {
              System.out.println("############");
              ValidationUtils.rejectIfEmpty(errors, "contactName", "contactName.emptyerror", "Contact Name should not be Empty!");
              ValidationUtils.rejectIfEmpty(errors, "phoneNumber", "phoneNumber.emptyerror", "Phone Number should not be Empty!");
              }
              }

              //Just checking for isEmpty or not
              --------------------------------------------------------------------

              The following is my controller class file, extends MultiActionController,

              package controller;

              import javax.servlet.http.HttpServletRequest;
              import javax.servlet.http.HttpServletResponse;
              import javax.servlet.http.HttpSession;


              import org.springframework.validation.Validator;
              import org.springframework.web.servlet.ModelAndView;
              import org.springframework.web.servlet.mvc.SimpleFormCont roller;
              import org.springframework.web.servlet.mvc.multiaction.Mu ltiActionController;

              import domain.Contact;

              import service.PhoneBook;
              import validator.ContactInfoValidator;

              public class PhoneBookController extends MultiActionController
              {
              public ModelAndView newcontactHandler(HttpServletRequest request, HttpServletResponse response)
              {
              try
              {
              Contact newContact = (Contact)newCommandObject(Contact.class);
              bind(request, newContact);
              phoneBook.addNewContact(newContact);
              return new ModelAndView("add-success");
              }
              catch(Exception expObj)
              {
              System.out.println(expObj);
              return new ModelAndView("add-fail");
              }
              }
              }

              //in the above code, phoneBook is an interface, containing 2 methods, addNewContact() and getContactsList()
              I have written separate class to implement this interface, this is not a problem
              ---------------------------------------------------------------------

              The following is my app-servlet.xml

              <bean id="phoneBookController" class="controller.PhoneBookController">
              <property name="methodNameResolver" ref="internalPathMethodNameResolver"/>
              <property name="phoneBook" ref="phoneBook"/>
              <property name="validators" ref="contactInfoValidator"/>
              </bean>

              <bean id="contactInfoValidator" class="validator.ContactInfoValidator"/>

              <bean id="internalPathMethodNameResolver" class="org.springframework.web.servlet.mvc.multiac tion.InternalPathMethodNameResolver">
              <property name="suffix" value="Handler"/>
              </bean>

              <bean id="phoneBook" class="service.PhoneBookManager">
              <property name="dataSource" ref="dataSource"/>
              </bean>

              //PhoneBookManager is a class that implements the interface called "PhoneBook" as I said above
              -------------------------------------------------------------------

              The following is my jsp file called addcontact.jsp

              <form:form action="newcontact.do" commandName="command">
              <table>
              <tr>
              <td align="left">Contact Name:</td>
              <td><form:input path="contactName"/></td>
              </tr>
              <tr>
              <td colspan="2">
              <form:errors path="contactName" cssClass="errorBox"/>
              </td>
              </tr>
              <tr></tr>
              <tr></tr>
              <tr>
              <td align="left">Phone Number:</td>
              <td><form:input path="phoneNumber"/></td>
              </tr>
              <tr>
              <td colspan="2">
              <form:errors path="phoneNumber" cssClass="errorBox"/>
              </td>
              </tr>
              <tr></tr>
              <tr></tr>
              <tr>
              <td colspan="2">
              <input type="submit" value="Submit New Contact"/>
              </td>
              </tr>
              </table>
              </form:form>


              ********* My requirement is **********

              when I click the submit button in the above form, the controller should validate the 2 fields and display the error message. I am checking only for isEmpty or not. when validation is success, it has to insert record in the DB (which I alread did) and should fetch the add-success.jsp else add-fail.jsp

              All I need is how to apply validation class with the multiactioncontroller?


              Thanking you,

              Waiting for you replay jerry.........

              Comment


              • #8
                You are almost correct, but odd

                My friend,

                You are doing it in a very special way. First of all, if there is binding error, you should let spring return to a form view.
                sth like:
                BindingResult errors = getBindingResult(request, eventFormData);
                if (errors.hasErrors()) {
                Map<String, Object> modelMap = prepareErrorViewForEditEvent(eventFormData);
                return new ModelAndView(getFormView(), errors.getModel()).addAllObjects(modelMap);
                }

                second, remember that i told you if you use the third parameter, you should not call bind the method in your action method because it is already called.

                Let's try this:

                public ModelAndView newcontactHandler(HttpServletRequest request, HttpServletResponse response, Contact contact)
                {
                BindingResult errors = getBindingResult(request, contact);
                if (errors.hasErrors()) {
                return new ModelAndView("***Your form jsp path*******");
                }
                try
                {
                phoneBook.addNewContact(contact);
                return new ModelAndView("add-success");
                }
                catch(Exception expObj)
                {
                System.out.println(expObj);
                return new ModelAndView("add-fail");
                }

                Comment


                • #9
                  Thank you for your Great Job Jerry

                  hi jerry,

                  if (errors.hasErrors()) {
                  Map<String, Object> modelMap = prepareErrorViewForEditEvent(eventFormData);
                  return new ModelAndView(getFormView(), errors.getModel()).addAllObjects(modelMap);
                  }

                  could you tell me what "eventFormData" refers to from the above code?

                  Thank you

                  Comment


                  • #10
                    It is an example

                    Hi,

                    It's just an example I've included. Please read my reply. I asked you to try this:

                    public ModelAndView newcontactHandler(HttpServletRequest request, HttpServletResponse response, Contact contact)
                    {
                    BindingResult errors = getBindingResult(request, contact);
                    if (errors.hasErrors()) {
                    return new ModelAndView("***Your form jsp path*******");
                    }
                    try
                    {
                    phoneBook.addNewContact(contact);
                    return new ModelAndView("add-success");
                    }
                    catch(Exception expObj)
                    {
                    System.out.println(expObj);
                    return new ModelAndView("add-fail");
                    }

                    Comment


                    • #11
                      hi jerry, I am getting same error

                      hi jerry,

                      As you suggested, I have tried the following in my handler,

                      public ModelAndView newcontactHandler(HttpServletRequest request, HttpServletResponse response, Contact contact)
                      {
                      try
                      {
                      ServletRequestDataBinder binder = createBinder(request, contact);
                      BindingResult errors = binder.getBindingResult();
                      if (errors.hasErrors())
                      {
                      return new ModelAndView("addcontact");
                      }

                      phoneBook.addNewContact(contact);
                      return new ModelAndView("add-success");
                      }
                      catch(Exception expObj)
                      {
                      System.out.println(expObj);
                      return new ModelAndView("add-fail");
                      }
                      }

                      Am I did the one that u have said?

                      I am ending up with the same error,
                      ----------------------------------------------------------------
                      org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBinding Result: 2 errors
                      Field error in object 'command' on field 'contactName': rejected value []; codes [contactName.emptyerror.command.contactName,contact Name.emptyerror.contactName,contactName.emptyerror .java.lang.String,contactName.emptyerror]; arguments []; default message [Contact Name should not be Empty!]
                      Field error in object 'command' on field 'phoneNumber': rejected value []; codes [phoneNumber.emptyerror.command.phoneNumber,phoneNu mber.emptyerror.phoneNumber,phoneNumber.emptyerror .java.lang.String,phoneNumber.emptyerror]; arguments []; default message [Phone Number should not be Empty!]
                      ----------------------------------------------------------------------

                      Comment


                      • #12
                        can you post the complete stacktrace?

                        can you post the complete stacktrace?

                        Comment


                        • #13
                          my complete stack Trace

                          Thank you very much jerry...as I was eagerly waiting for ur replay...here is my complete stack trace


                          SEVERE: Servlet.service() for servlet phonebook threw exception
                          org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBinding Result: 2 errors
                          Field error in object 'command' on field 'contactName': rejected value []; codes [contactName.emptyerror.command.contactName,contact Name.emptyerror.contactName,contactName.emptyerror .java.lang.String,contactName.emptyerror]; arguments []; default message [Contact Name should not be Empty!]
                          Field error in object 'command' on field 'phoneNumber': rejected value []; codes [phoneNumber.emptyerror.command.phoneNumber,phoneNu mber.emptyerror.phoneNumber,phoneNumber.emptyerror .java.lang.String,phoneNumber.emptyerror]; arguments []; default message [Phone Number should not be Empty!]
                          at org.springframework.web.bind.ServletRequestDataBin der.closeNoCatch(ServletRequestDataBinder.java:121 )
                          at org.springframework.web.servlet.mvc.multiaction.Mu ltiActionController.bind(MultiActionController.jav a:541)
                          at org.springframework.web.servlet.mvc.multiaction.Mu ltiActionController.invokeNamedMethod(MultiActionC ontroller.java:470)
                          at org.springframework.web.servlet.mvc.multiaction.Mu ltiActionController.handleRequestInternal(MultiAct ionController.java:410)
                          at org.springframework.web.servlet.mvc.AbstractContro ller.handleRequest(AbstractController.java:153)
                          at org.springframework.web.servlet.mvc.SimpleControll erHandlerAdapter.handle(SimpleControllerHandlerAda pter.java:48)
                          at org.springframework.web.servlet.DispatcherServlet. doDispatch(DispatcherServlet.java:875)
                          at org.springframework.web.servlet.DispatcherServlet. doService(DispatcherServlet.java:807)
                          at org.springframework.web.servlet.FrameworkServlet.p rocessRequest(FrameworkServlet.java:571)
                          at org.springframework.web.servlet.FrameworkServlet.d oPost(FrameworkServlet.java:511)
                          at javax.servlet.http.HttpServlet.service(HttpServlet .java:647)
                          at javax.servlet.http.HttpServlet.service(HttpServlet .java:729)
                          at org.apache.catalina.core.ApplicationFilterChain.in ternalDoFilter(ApplicationFilterChain.java:269)
                          at org.apache.catalina.core.ApplicationFilterChain.do Filter(ApplicationFilterChain.java:188)
                          at org.apache.catalina.core.StandardWrapperValve.invo ke(StandardWrapperValve.java:213)
                          at org.apache.catalina.core.StandardContextValve.invo ke(StandardContextValve.java:172)
                          at org.apache.catalina.core.StandardHostValve.invoke( StandardHostValve.java:127)
                          at org.apache.catalina.valves.ErrorReportValve.invoke (ErrorReportValve.java:117)
                          at org.apache.catalina.core.StandardEngineValve.invok e(StandardEngineValve.java:108)
                          at org.apache.catalina.connector.CoyoteAdapter.servic e(CoyoteAdapter.java:174)
                          at org.apache.coyote.http11.Http11Processor.process(H ttp11Processor.java:875)
                          at org.apache.coyote.http11.Http11BaseProtocol$Http11 ConnectionHandler.processConnection(Http11BaseProt ocol.java:665)
                          at org.apache.tomcat.util.net.PoolTcpEndpoint.process Socket(PoolTcpEndpoint.java:528)
                          at org.apache.tomcat.util.net.LeaderFollowerWorkerThr ead.runIt(LeaderFollowerWorkerThread.java:81)
                          at org.apache.tomcat.util.threads.ThreadPool$ControlR unnable.run(ThreadPool.java:689)
                          at java.lang.Thread.run(Unknown Source)

                          Comment


                          • #14
                            Hi jerry

                            Hi jerry,

                            The following classNoCatch() method is throwing that exception

                            public void closeNoCatch() throws ServletRequestBindingException {
                            if (getBindingResult().hasErrors()) {
                            throw new ServletRequestBindingException(
                            "Errors binding onto object '" + getBindingResult().getObjectName() + "'",
                            new BindException(getBindingResult()));
                            }
                            }

                            Comment


                            • #15
                              this is corrent!

                              This correct actually.

                              As you see from the spring source,
                              /**
                              * Bind request parameters onto the given command bean
                              * @param request request from which parameters will be bound
                              * @param command command object, that must be a JavaBean
                              * @throws Exception in case of invalid state or arguments
                              */
                              protected void bind(HttpServletRequest request, Object command) throws Exception {
                              logger.debug("Binding request parameters onto MultiActionController command");
                              ServletRequestDataBinder binder = createBinder(request, command);
                              binder.bind(request);
                              if (this.validators != null) {
                              for (int i = 0; i < this.validators.length; i++) {
                              if (this.validators[i].supports(command.getClass())) {
                              ValidationUtils.invokeValidator(this.validators[i], command, binder.getBindingResult());
                              }
                              }
                              }
                              binder.closeNoCatch();
                              }

                              it throws out anyways.

                              Now the question is how to control this?

                              The reason I do not have it is because I have my own multiactioncontroller wrapped the spring's mac. In that I override the bind method:

                              protected void bind(HttpServletRequest request, Object command) throws Exception {
                              if (logger.isDebugEnabled()) logger.debug("Binding request parameters onto MultiActionController command");
                              ServletRequestDataBinder binder = createBinder(request, command);
                              binder.bind(request);
                              BindingResult errors = binder.getBindingResult();
                              request.setAttribute(BindingResult.MODEL_KEY_PREFI X + getCommandName(command), errors);
                              String methodName = (String) request.getAttribute(METHOD_ATTRIBUTE_NAME);
                              Validator[] validators = (isCancelled(request)) ? null : getValidators();
                              if (validators != null) {
                              for (int i = 0; i < validators.length; i++) {
                              Validator v = validators[i];
                              if (v instanceof BaseValidator) {
                              if (((BaseValidator)v).supports(command.getClass(), methodName)) {
                              ValidationUtils.invokeValidator(validators[i], command, errors);
                              }
                              } else if (v.supports(command.getClass())) {
                              ValidationUtils.invokeValidator(validators[i], command, errors);
                              }
                              }
                              }
                              if (logger.isDebugEnabled()) {
                              logger.debug("Data binding errors: " + errors.getErrorCount());
                              }
                              if (errors.hasErrors()) {
                              if (throwExceptionOnBindingError) {
                              binder.closeNoCatch(); // drastic error
                              }
                              }
                              }


                              Now, there is a parameter that controls the throwing.
                              if (errors.hasErrors()) {
                              if (throwExceptionOnBindingError) {
                              binder.closeNoCatch(); // drastic error
                              }
                              }

                              All my other mac extends this class, and the property can be configured in the app-servlet.xml.

                              Comment

                              Working...
                              X