java - Spring Form Validation with Two Objects -


got complicated problem spring boot application i've been trying solve while , i'm hoping can me. i've removed other parts of project , tried make simple possible. if go localhost:8080, there'll form 2 text boxes enter 2 names into, , submit button. first name stored in nominee object, second in submitter object. when click submit, perform validation on fields make sure neither of them empty. i'll post code below , explain problem @ end.

application.java

package nomination;    import org.springframework.boot.springapplication;  import org.springframework.boot.autoconfigure.springbootapplication;  import org.springframework.context.annotation.bean;  import org.springframework.jms.annotation.enablejms;  import org.springframework.jms.config.jmslistenercontainerfactory;  import org.springframework.jms.config.simplejmslistenercontainerfactory;  import org.springframework.web.servlet.config.annotation.enablewebmvc;    @springbootapplication  @enablejms  @enablewebmvc  public class application {        public static void main(string[] args) throws exception {          // launch application          springapplication.run(application.class, args);      }    }

webcontroller.java

package nomination;    import javax.validation.valid;  import org.slf4j.logger;  import org.slf4j.loggerfactory;  import org.springframework.ui.model;  import org.springframework.web.bind.webdatabinder;  import org.springframework.web.bind.annotation.initbinder;  import org.springframework.web.bind.annotation.modelattribute;  import org.springframework.stereotype.controller;  import org.springframework.validation.bindingresult;  import org.springframework.web.bind.annotation.requestmapping;  import org.springframework.web.bind.annotation.requestmethod;  import org.springframework.web.servlet.config.annotation.viewcontrollerregistry;  import org.springframework.web.servlet.config.annotation.webmvcconfigureradapter;    @controller  public class webcontroller extends webmvcconfigureradapter {      protected static final logger log = loggerfactory.getlogger(webcontroller.class);        @initbinder("nominee")      protected void initnomineebinder(webdatabinder binder) {          binder.setvalidator(new nomineevalidator());      }        @initbinder("submitter")      protected void initsubmitterbinder(webdatabinder binder) {          binder.setvalidator(new submittervalidator());      }        @override      public void addviewcontrollers(viewcontrollerregistry registry) {          registry.addviewcontroller("/success").setviewname("success");      }        @requestmapping(value="/", method=requestmethod.get)      public string showform(model model) {          model.addattribute("nominee", new nominee());          model.addattribute("submitter", new submitter());          return "form";      }        @requestmapping(value="/", method=requestmethod.post)      public string checkpersoninfo(@modelattribute(value="nominee") @valid nominee nominee,                                    @modelattribute(value="submitter") @valid submitter submitter,                                    bindingresult bindingresult, @valid model model) {          log.info("nominee string: " + nominee.tostring());          log.info("submitter string: " + submitter.tostring());          log.info("bindingresult string: " + bindingresult.tostring());          if (bindingresult.haserrors()) {              return "form";          }            return "redirect:/success";      }    }

nominee.java

package nomination;    import lombok.data;    @data  public class nominee {      private string name;  }

nomineevalidatior.java

package nomination;    import org.springframework.validation.errors;  import org.springframework.validation.validationutils;  import org.springframework.validation.validator;    public class nomineevalidator implements validator {        public boolean supports(class clazz) {          return nominee.class.equals(clazz);      }        public void validate(object object, errors errors) {          validationutils.rejectifempty(errors, "name", "name", "this field empty.");      }  }

submitter.java

package nomination;    import lombok.data;    @data  public class submitter {      private string sname;  }

submittervalidator.java

package nomination;    import org.springframework.validation.errors;  import org.springframework.validation.validationutils;  import org.springframework.validation.validator;    public class submittervalidator implements validator {        public boolean supports(class clazz) {          return submitter.class.equals(clazz);      }        public void validate(object object, errors errors) {          validationutils.rejectifempty(errors, "sname", "sname", "this field empty.");      }  }

form.html

<html><body>      <form role="form" th:action="@{/}" method="post">          <h2>nominee details</h2>          <table>              <tr>                  <td>name:</td>                  <td>                      <input type="text" th:field="${nominee.name}" />                  </td>                  <td><p th:if="${#fields.haserrors('nominee.name')}" th:errors="${nominee.name}">empty field</p></td>              </tr>          </table>          <h2>your details</h2>          <table>              <tr>                  <td>your name:</td>                  <td>                      <input type="text" th:field="${submitter.sname}" />                  </td>                  <td><p th:if="${#fields.haserrors('submitter.sname')}" th:errors="${submitter.sname}">empty field</p></td>              </tr>          </table>          <div>              <button type="submit">submit nomination</button>          </div>      </form>  </body></html>

success.html

<html><body>form submitted.</body></html>

if leave first text field blank (and fill or don't fill in second text field), error message appears on screen reads:

whitelabel error page

this application has no explicit mapping /error, seeing fallback. tue may 12 13:10:17 aest 2015 there unexpected error (type=bad request, status=400). validation failed object='nominee'. error count: 1

i don't know how fix leaving first textbox blank won't cause whitelabel error page. if leave second text field blank fill in first, acts normal, i'm not sure why causes error if try other way around. fixing appreciated.

also, may have noticed had use 'name' , 'sname' variables in nominee , submitter, if set them both 'name' doesn't work properly. if there's way edit both can use 'name', i'd love know how.

edit: found solution. in webcontroller, checkpersoninfo needs separate bindingresult each object being validated. bindingresult needs in method parameters following each @valid object.

so, in webcontroller.java, this:

    @requestmapping(value="/", method=requestmethod.post) public string checkpersoninfo(@modelattribute(value="nominee") @valid nominee nominee,                               @modelattribute(value="submitter") @valid submitter submitter,                               bindingresult bindingresult, @valid model model) {     log.info("nominee string: " + nominee.tostring());     log.info("submitter string: " + submitter.tostring());     log.info("bindingresult string: " + bindingresult.tostring());     if (bindingresult.haserrors()) {         return "form";     }      return "redirect:/success"; } 

needs become this:

    @requestmapping(value="/", method=requestmethod.post) public string checkpersoninfo(@modelattribute(value="nominee") @valid nominee nominee,                               bindingresult bindingresultnominee,                               @modelattribute(value="submitter") @valid submitter submitter,                               bindingresult bindingresultsubmitter) {     log.info("nominee string: " + nominee.tostring());     log.info("submitter string: " + submitter.tostring());     if (bindingresultnominee.haserrors() || bindingresultsubmitter.haserrors()) {         return "form";     }      return "redirect:/success"; } 

(the model object removed since it's never used anywhere, if needed validate @valid you'd add third bindingresult object.)

found solution. in webcontroller, checkpersoninfo needs separate bindingresult each object being validated. bindingresult needs in method parameters following each @valid object.

so, in webcontroller.java, this:

    @requestmapping(value="/", method=requestmethod.post) public string checkpersoninfo(@modelattribute(value="nominee") @valid nominee nominee,                               @modelattribute(value="submitter") @valid submitter submitter,                               bindingresult bindingresult, @valid model model) {     log.info("nominee string: " + nominee.tostring());     log.info("submitter string: " + submitter.tostring());     log.info("bindingresult string: " + bindingresult.tostring());     if (bindingresult.haserrors()) {         return "form";     }      return "redirect:/success"; } 

needs become this:

    @requestmapping(value="/", method=requestmethod.post) public string checkpersoninfo(@modelattribute(value="nominee") @valid nominee nominee,                               bindingresult bindingresultnominee,                               @modelattribute(value="submitter") @valid submitter submitter,                               bindingresult bindingresultsubmitter) {     log.info("nominee string: " + nominee.tostring());     log.info("submitter string: " + submitter.tostring());     if (bindingresultnominee.haserrors() || bindingresultsubmitter.haserrors()) {         return "form";     }      return "redirect:/success"; } 

(the model object removed since it's never used anywhere, if needed validate @valid you'd add third bindingresult object.)


Comments

Popular posts from this blog

android - MPAndroidChart - How to add Annotations or images to the chart -

javascript - Add class to another page attribute using URL id - Jquery -

firefox - Where is 'webgl.osmesalib' parameter? -