12/10/2013

[Java] Keep HTML form filled after failed Spring validation

I was working on a JSR-168 portlet written in Java 4 using Spring 2 and I had plain HTML forms validated via Spring validators. Everything works fine with this setting but upon failed validation, the page would reload showing the errors and an empty form.

Instead of replacing all the forms with Spring ones (form:form), I found an alternative solution which let me keep my current project structure and tone down the necessary modifications.

It requires modification of three parts: the JSP containing the form, the form controller and the controller that redirects users to the page.


Form controller:

 protected ModelAndView renderFormSubmission(RenderRequest request, RenderResponse response, Object command, BindException errors)  
      throws Exception{  
           PortletSession session = request.getPortletSession();    
           if(errors.hasErrors()){  
                session.setAttribute("myForm", command, PortletSession.APPLICATION_SCOPE);  
                return showForm(request, errors, getFormView());  
           }  
           else{  
                session.setAttribute("myForm", new myForm(), PortletSession.APPLICATION_SCOPE);  
                return onSubmitRender( request, response, command, errors);  
           }  
 }  

We override the renderFormSubmission method and check for errors after validation. If there are none, we let the flow continue by calling the onSubmitRender, else we put the wrongly filled form in session and call the showForm method to redirect the user on the form page showing him the errors. In the example I always redirect on the same page, that's why, if there are no validation errors, I have to store an empty form in session, otherwise the user would see his correctly filled form after submission instead of a blank one.

JSP page:

 <%@page import="com.groglogs.forms.myForm"%> 
   
 <%  
 myForm form = (myForm)request.getSession().getAttribute("myForm");  
 String field1 = "";  
 String fieldN = "";  
 if(form!=null){  
      field1 = form.getField1();  
      fieldN = form.getFieldN();  
 }  
 %>  
   

Here we simply grab the submitted form from session, and use it to initialize the page's form. Note that some session form fields might be null instead of empty strings.

Navigation controller:

session.setAttribute("myForm", new myForm(), PortletSession.APPLICATION_SCOPE);

Modifying the navigation controller is mandatory since we stored our filled form in session; this means that a user could be presented with the wrongly filled form if he navigates back and forth after a failed validation. In this way, we always show an empty form on page initialization.

It's not as pretty as directly using Spring forms, but in a few minutes and without huge rewriting, everything worked fine.

No comments:

Post a Comment

With great power comes great responsibility