Kartik
Kartik

Reputation: 2609

Spring MVC: How do I preserve model attributes in spring validation errors

I searched around on Stack Overflow, but could not find the solution to my query. I have a controller function that adds multiple model attributes on a GET request

  @RequestMapping(method = RequestMethod.GET, value = "/showdeletesearchqueryform")
  public String showDeleteSearchQuery(final Model model) {
    if (LOG.isDebugEnabled()) {
      LOG.debug("Fetching all the search query results.");
    }
    ImmutableList<ArtQueryResults> results = this.searchQueriesService
        .getSearchQueries(APPNAME);

    // Adding model attribute # 1
    model.addAttribute("searchResults", results);
    if (LOG.isDebugEnabled()) {
      LOG.debug("\"searchResults\" model attribute has been intialized from "
          + results);
    }
    ArtDeleteQueryRequest request = new ArtDeleteQueryRequest();
    request.setAppName(APPNAME);
    if (LOG.isDebugEnabled()) {
      LOG.debug("Model attribute initialized = " + request);
    }
    // Adding model attribute # 2
    model.addAttribute("deletedAttributes", request);
    return "deletesearchqueries";
  }

My JSP

<div class="column-group">
           <form:form method="POST" action="${pageContext.request.contextPath}/arttestresults/showdeletesearchqueryform" modelAttribute="deletedAttributes">
             <form:errors path="*" cssClass="alert alert-danger column lg-units-5 units-2" element="div"/>
             <form:hidden path="appName" id="appNameId" htmlEscape="true"/>
             <div class = "units-1 column lg-units-12">
         <!--  Hidden Key for app name. -->


         <form:select path="idsToBeDeleted" id="IdsToBeDeletedSelectId">
           <c:forEach items="${searchResults}" var="searchResult" varStatus="loop">
       <form:option label="${searchResult.searchQuery}" value="${searchResult.id}" />
      </c:forEach>
         </form:select>
        </div>
        <div class="units-1 column lg-units-12">   
            <%-- This is a hack that make sure that form is submitted on a click. Not sure why form is not being submitted. --%>
           <button class="button" type="submit" onclick="javascript:$('form').submit();">Delete Selected Queries</button>
        </div>
           </form:form>

My controller POST function

  @RequestMapping(method = RequestMethod.POST, value = "/showdeletesearchqueryform")
  public String deleteSearchQueries(
      Model model,
      @ModelAttribute(value = "deletedAttributes") @Valid final ArtDeleteQueryRequest request,
      final BindingResult result) {
    if (result.hasErrors()) {
      LOG.warn("There are " + result.getErrorCount() + " validation errors.");
      return "deletesearchqueries";
    } else {
      if (LOG.isDebugEnabled()) {
        LOG.debug("The ids to be deleted are " + request.getIdsToBeDeleted());
      }
      this.searchQueriesService.deleteSearchQueriesById(
          ImmutableList.copyOf(request.getIdsToBeDeleted()));
      return "redirect:/arttestresults/showdeletesearchqueryform";
    }
  }

If there is a validation failure, the model attribute searchResults is not being picked up when I return a view on error condition? Is there a way to preserve the other defined model attributes as well?

Upvotes: 0

Views: 1624

Answers (2)

Serge Ballesta
Serge Ballesta

Reputation: 148870

The get and the post are different requests. What you get in the post request, is only what comes from the form, so only the "deletedAttributes" model attribute and only the fields that are <input> in the JSP.

You need to put again the searchResults model attribute explicitely like you did in get method.

As suggested by M. Deinum, if one or more attribute(s) will be used by all methods in a controller, you can use a @ModelAttribute annotated method to put it (them) in model automatically.

You can also use SessionAttributes model attributes, that is attributes that are stored in session and not in request. But it is hard to have them properly cleaned from session if user do not post the form but go into another part of the application. You have an example of usage ofSessionAttributes` in Spring's Petclinic example.

Upvotes: 1

rocky
rocky

Reputation: 5004

Seems that you need flash attributes which were added in spring 3.1. Please take a look at example/explanation:

http://viralpatel.net/blogs/spring-mvc-flash-attribute-example/

Upvotes: 1

Related Questions