Note that there are some explanatory texts on larger screens.

plurals
  1. POSpring-MVC form validation with MultiActionController
    primarykey
    data
    text
    <p>I am trying to apply form validation on a MultiActionController (I do know that the controller classes are now deprecated).</p> <p>I've found this answer (which got me closer to my target, but not completely): <a href="https://stackoverflow.com/questions/2744587/how-to-perform-spring-validation-in-multiactioncontroller/2746912#2746912">How to perform Spring validation in MultiActionController?</a></p> <p>Ok, so according to the <a href="http://static.springsource.org/spring/docs/2.0.x/api/org/springframework/web/servlet/mvc/multiaction/MultiActionController.html" rel="nofollow noreferrer">javadoc</a>, an exception handler method is a controller's method with the parameters <code>(HttpServletRequest request, HttpServletResponse response, ExceptionClass exception)</code>.</p> <p>As far as I can see (correct me if I am wrong), it looks like the work flow is as follows: the spring dispatcher-servlet goes to the requested method of the controller, and if there happens an exception during its execution (e.g. a binding exception due to validation failure), it will go to the exception handler method that its exception parameter matches the occurring exception (if there is such an exception handler method).</p> <p>But unlike the regular controller's methods, this exception handler method has no command object parameter. <strong>So my question is how do I access in that method, the command object that was sent with the request in which the binding exception (due to a validation error) happened?</strong></p> <p>For example, when I use validation by annotations, I have in the request handler methods access <strong>(as method parameters)</strong> to both BindingResult and the command object, so in case of a validation error I can load the returned ModelAndView with the command object data.</p> <p>However, with my exception handler method (in my MultiActionController), which ends with </p> <pre><code>BindException bindException = (BindException) bindingException.getRootCause(); return new ModelAndView("myFormView").addAllObjects(bindException.getModel()); </code></pre> <p>— after submitting invalid data, I am getting and exception that my JSP view ("myFormView") cannot be rendered because the command object cannot be found.</p> <p>Thanks!</p> <p><strong>MORE INFO:</strong></p> <p>My actual request handler method in my controller (SearchBookController) looks like this:</p> <pre><code>public ModelAndView list(HttpServletRequest request, HttpServletResponse response, Book book) throws Exception { ModelMap modelMap = new ModelMap(); //getting a list of books according to the propertiest of the command object book... modelMap.addAttribute("bookList", bookDAO.listBooks(book)); return new ModelAndView("bookForm", modelMap); } </code></pre> <p>I've also added the following exception handler method to the controller:</p> <pre><code>public ModelAndView hanldeBindException(HttpServletRequest request, HttpServletResponse response, ServletRequestBindingException bindingException) { // do what you want right here //I WOULD LIKE TO ADD HERE THE SUBMITTED BOOK AND THE FETCHED BOOKLIST TO THE ModelAndView, BUT I DO NOT KNOW HOW TO DO IT BindException bindException = (BindException) bindingException.getRootCause(); return new ModelAndView("bookForm").addAllObjects(bindException.getModel()); } </code></pre> <p>This is how I added my validator to SearchBookController in my servlet-dispatcher.xml:</p> <pre><code>&lt;bean name="/book/search.htm" class="com.books.web.SearchBookController" p:validators-ref="searchBookValidator" &gt; &lt;property name="bookDAO" ref="myBookDAO" /&gt; &lt;/bean&gt; &lt;bean id="searchBookValidator" class="com.books.validator.SearchBookValidator" /&gt; </code></pre> <p>The validator right now just makes sure that the book properties are validated by ValidationUtils.rejectIfEmptyOrWhitespace.</p> <p>My view (bookForm.jsp) shows both the submit fields and the search results (it re-displays the submitted fields when the result view is rendered). So after the submit, the view should get both the book command object, and the bookList object.</p> <p>bookForm.jsp looks like this:</p> <pre><code> &lt;tr&gt; &lt;td&gt;Details :&lt;/td&gt; &lt;td&gt;&lt;form:input path="details" /&gt;&lt;/td&gt; &lt;td&gt;&lt;form:errors path="details" cssClass="error"/&gt;&lt;/td&gt; &lt;/tr&gt; </code></pre> <p>(details is one of the fields of Book).</p> <p>Here is the exception message I am getting when I try to load bookForm.jsp (even before the submit, simply when i try to load the page so I could fill in the form):</p> <p>(*** When I remove the <code>p:validators-ref="searchBookValidator"</code> from the controller definition in the servlet-dispatcher.xml, the jsp page loads correctly before and after the submit).</p> <pre><code>HTTP Status 500 - -------------------------------------------------------------------------------- type Exception report message description The server encountered an internal error () that prevented it from fulfilling this request. exception org.apache.jasper.JasperException: An exception occurred processing JSP page /WEB-INF/jsp/bookForm.jsp at line 209 206: --%&gt; 207: &lt;tr&gt; 208: &lt;td&gt;Details :&lt;/td&gt; 209: &lt;td&gt;&lt;form:input path="details" /&gt;&lt;/td&gt; 210: &lt;td&gt;&lt;form:errors path="details" cssClass="error"/&gt;&lt;/td&gt; 211: &lt;/tr&gt; 212: &lt;tr&gt; Stacktrace: org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:510) org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:413) org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:313) org.apache.jasper.servlet.JspServlet.service(JspServlet.java:260) javax.servlet.http.HttpServlet.service(HttpServlet.java:717) org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:238) org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:250) org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1047) org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:817) org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719) org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644) org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:549) javax.servlet.http.HttpServlet.service(HttpServlet.java:617) javax.servlet.http.HttpServlet.service(HttpServlet.java:717) root cause java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'book' available as request attribute org.springframework.web.servlet.support.BindStatus.&lt;init&gt;(BindStatus.java:141) org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.getBindStatus(AbstractDataBoundFormElementTag.java:174) org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.getPropertyPath(AbstractDataBoundFormElementTag.java:194) org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.getName(AbstractDataBoundFormElementTag.java:160) org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.autogenerateId(AbstractDataBoundFormElementTag.java:147) org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.resolveId(AbstractDataBoundFormElementTag.java:138) org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.writeDefaultAttributes(AbstractDataBoundFormElementTag.java:122) org.springframework.web.servlet.tags.form.AbstractHtmlElementTag.writeDefaultAttributes(AbstractHtmlElementTag.java:408) org.springframework.web.servlet.tags.form.InputTag.writeTagContent(InputTag.java:140) org.springframework.web.servlet.tags.form.AbstractFormTag.doStartTagInternal(AbstractFormTag.java:102) org.springframework.web.servlet.tags.RequestContextAwareTag.doStartTag(RequestContextAwareTag.java:79) org.apache.jsp.WEB_002dINF.jsp.bookForm_jsp._jspx_meth_form_005finput_005f0(bookForm_jsp.java:593) org.apache.jsp.WEB_002dINF.jsp.bookForm_jsp._jspService(bookForm_jsp.java:326) org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70) javax.servlet.http.HttpServlet.service(HttpServlet.java:717) org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:377) org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:313) org.apache.jasper.servlet.JspServlet.service(JspServlet.java:260) javax.servlet.http.HttpServlet.service(HttpServlet.java:717) org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:238) org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:250) org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1047) org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:817) org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719) org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644) org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:549) javax.servlet.http.HttpServlet.service(HttpServlet.java:617) javax.servlet.http.HttpServlet.service(HttpServlet.java:717) </code></pre> <p><strong>UPDATE:</strong></p> <p>Following the answer below, I can now access the command object from the exception handler method. I still have a problem though: if I submit data that should have triggered an error message, e.g. through</p> <pre><code>&lt;tr&gt; &lt;td&gt;Details :&lt;/td&gt; &lt;td&gt;&lt;form:input path="details" /&gt;&lt;/td&gt; &lt;td&gt;&lt;form:errors path="details" cssClass="error"/&gt;&lt;/td&gt; &lt;/tr&gt; </code></pre> <p>in the result view JSP - I do not see that error message.</p> <p>My validator looks like this:</p> <pre><code>public class SearchBookValidator implements Validator { //...... @Override public void validate(Object target, Errors errors) { ValidationUtils.rejectIfEmptyOrWhitespace(errors, "details", "details.required"); } } </code></pre> <p>and my messages.properties contains the following line:</p> <pre><code>details.required=details are required </code></pre> <p>To help me see what happens, I've included the following code in my controller's hanldeBindException:</p> <pre><code> Map mp = bindException.getModel(); for (Object o : mp.entrySet()) { Map.Entry pairs = (Map.Entry)o; System.out.println(pairs.getKey() + " = " + pairs.getValue()); } </code></pre> <p>When I submit the form with deliberately wrong data (i.e. the details text field is empty), I am getting the following input on the console:</p> <pre><code>command = com.books.domain.Book@1173447 org.springframework.validation.BindingResult.command = org.springframework.validation.BeanPropertyBindingResult: 1 errors Field error in object 'command' on field 'details': rejected value []; codes [details.required.command.details,details.required.details,details.required.java.lang.String,details.required]; arguments []; default message [null] </code></pre> <p>Can you see why I do not get any error message through the <code>&lt;form:errors path="details" cssClass="error"/&gt;</code> ?</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload