Handling duplicate form submission in Spring MVC

In last Spring MVC form handling example, if you refresh the form success view, most browsers will prompt a pop-up dialog to confirm about the form resubmission. If you click “yes”, the form will be resubmitted again, this scenario is well-known as duplicated form submission.

Figure : example of duplicated form submission.

SpringMVC-Duplicate-Form-Submit

The common solution to this is using “Post/Redirect/Get” Design Pattern. It will redirect to another URL if the form submission is successfully, instead of returning a web page directly.

Note
Check the details explanation of Post/Redirect/Get Design Pattern in Wiki.

Post/Redirect/Get Design Pattern in Spring MVC

In this tutorial, we show you how to apply the “Post/Redirect/Get” Design Pattern in Spring MVC to solve the duplicated form submission problem in last form handling example.

1. Duplicate form submission

See below normal form declaration that will hits the duplicate form submission problem.

File : mvc-dispatcher-servlet.xml


<bean 
class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping" />

   <bean class="com.mkyong.customer.controller.CustomerController">
	<property name="formView" value="CustomerForm" />
	<property name="successView" value="CustomerSuccess" />
   </bean>
	
   <bean id="viewResolver"
        class="org.springframework.web.servlet.view.InternalResourceViewResolver" >
        <property name="prefix">
             <value>/WEB-INF/pages/</value>
        </property>
        <property name="suffix">
             <value>.jsp</value>
        </property>
    </bean>

In above snippet, the CustomerController returns a “CustomerSuccess” view directly, which should be replace with a redirect URL instead.

2. Redirect View

Declared a review view, named “customerSuccessRedirect” and return an URL “CustomerSuccess.htm“.

File : spring-views.xml


<beans ...>
   <!-- Redirect view --> 
   <bean id="customerSuccessRedirect" 
       class="org.springframework.web.servlet.view.RedirectView">
       <property name="url" value="CustomerSuccess.htm" />
    </bean>	 
</beans>

3. Spring Configuration

Update the mvc-dispatcher-servlet.xml settings to link all Spring’s configuration together.

  1. Update the “successView” to the new redirect view, named “customerSuccessRedirect“.
  2. Declare a “XmlViewResolver” to load the redirect view.
  3. Put a priority order for the “InternalResourceViewResolver” and “XmlViewResolver“, otherwise the “InternalResourceViewResolver” will always match and give your application no chance to call the “XmlViewResolver“.
  4. Declare a “ParameterizableViewController” controller to match the redirect URL and return a view to user. Since the “ControllerClassNameHandlerMapping” won’t generated the mapping for any build-in Spring’s controller, so you have to define the explicit mapping in “SimpleUrlHandlerMapping“.

File : mvc-dispatcher-servlet.xml



<bean 
class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping" />

   <bean class="com.mkyong.customer.controller.CustomerController">
	<property name="formView" value="CustomerForm" />
	<property name="successView" value="customerSuccessRedirect" />
		
	<!-- it was
	<property name="successView" value="CustomerSuccess" />
	-->
   </bean>
	
   <!-- Redirect Controller -->
   <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <prop key="/CustomerSuccess.htm">customerSuccessController</prop>
            </props>
        </property>
   </bean>
	
   <bean id="customerSuccessController" 
        class="org.springframework.web.servlet.mvc.ParameterizableViewController">
       <property name="viewName" value="CustomerSuccess" />
   </bean>
	
   <bean id="viewResolver"
        class="org.springframework.web.servlet.view.InternalResourceViewResolver" >
        <property name="prefix">
             <value>/WEB-INF/pages/</value>
        </property>
        <property name="suffix">
             <value>.jsp</value>
         </property>
         <property name="order" value="1" />
   </bean>

   <bean class="org.springframework.web.servlet.view.XmlViewResolver">
        <property name="location">
	      <value>/WEB-INF/spring-views.xml</value>
	 </property>
	 <property name="order" value="0" />
   </bean>	

4. How it works?

1. Access URL : http://localhost:8080/SpringMVC/customer.htm.

2. Fill in and submits the form.

3. Return “successView”, which is “customerSuccessRedirect“.


   <bean class="com.mkyong.customer.controller.CustomerController">
	<property name="formView" value="CustomerForm" />
	<property name="successView" value="customerSuccessRedirect" />
   </bean>

4. “XmlViewResolver” match it and return a “RedirectView” with URL “CustomerSuccess.htm“.


   <bean id="customerSuccessRedirect" 
       class="org.springframework.web.servlet.view.RedirectView">
       <property name="url" value="CustomerSuccess.htm" />
    </bean>

5. “SimpleUrlHandlerMapping” match it and return a ParameterizableViewController, “customerSuccessController“, and return the view name “CustomerSuccess“.


   <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <prop key="/CustomerSuccess.htm">customerSuccessController</prop>
            </props>
        </property>
   </bean>
   <bean id="customerSuccessController" 
        class="org.springframework.web.servlet.mvc.ParameterizableViewController">
       <property name="viewName" value="CustomerSuccess" />
   </bean>

6. “InternalResourceViewResolver” match it and return the final view “/WEB-INF/pages/CustomerSuccess.jsp“.


   <bean id="viewResolver"
        class="org.springframework.web.servlet.view.InternalResourceViewResolver" >
        <property name="prefix">
             <value>/WEB-INF/pages/</value>
        </property>
        <property name="suffix">
             <value>.jsp</value>
         </property>
         <property name="order" value="1" />
   </bean>

7. URL changed to http://localhost:8080/SpringMVC/CustomerSuccess.htm.

8. Try refresh the success form page , the form resubmission dialog will not prompt anymore.

Note
The overall concept is return a redirect URL instead of a direct page.

Download Source Code

References

  1. Post/Redirect/Get design pattern
  2. Form handling in Spring MVC

About the Author

author image
mkyong
Founder of Mkyong.com, love Java and open source stuff. Follow him on Twitter, or befriend him on Facebook or Google Plus. If you like my tutorials, consider make a donation to these charities.

Comments

avatar
14 Comment threads
2 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
11 Comment authors
Nitesh ApteAmeet SagarCarinaimac repair kuala lumpur imac repair kuala lumpur imac retina display repair kuala lumpurmahesh Recent comment authors
newest oldest most voted
Nitesh Apte
Guest
Nitesh Apte

Hi.

I published today something similar. But only annotation is used. Please have a look and let me know there is something that I can do to make it more better. Here is the link – http://blogs.niteshapte.com/2013-07-15-how-to-prevent-duplicate-form-submission-in-spring-mvc.htm

Ameet Sagar
Guest
Ameet Sagar

Nice Tutorial?!!!

If i am using annotation config. can i use following logic???

@Controller
@RequestMapping(?/customers?)
public class EmployeeController
{
//in post method
@RequestMapping(method=RequestMethod.POST)
public String createCustomer(Customer customer)
{
customerDao.add(customer);
return ?redirect:/customers?;
}

@RequestMapping(method=RequestMethod.GET)
public String showCustomers(Model model)
{
List custombers = customerDao.list();
model.addAttribute(?custombers?, customers);
return ?customers/list?;
}
}

Carina
Guest
Carina

Wonderful beat ! I would like to apprentice whilst you amend your site,
how can i subscribe for a weblog website? The account aided me a applicable deal.
I had been a little bit familiar of this your
broadcast provided vivid clear concept

imac repair kuala lumpur imac repair kuala lumpur imac retina display repair kuala lumpur
Guest
imac repair kuala lumpur imac repair kuala lumpur imac retina display repair kuala lumpur

I really like it when people get together and share ideas.
Great site, stick with it!

mahesh
Guest
mahesh

Thanks for sharing this tutorial but how this can be achieved in Spring 3 with annotations somehow redirect:path doesn’t work. It would be great if we get same kind of example from you for spring 3 with annotations.

andrew
Guest
andrew

can you write example how to do this for the annotation example?

wayne
Guest
wayne

hi can you do this for the annotation example as well??? can’t get it working using redirect

trackback
Spring MVC Tutorial

[…] XML based version.Form handling annotation example Form handling in Spring MVC, annotation version.Handling duplicate form submission “Post/Redirect/Get” Design Pattern is the common solution for this duplicated form […]

trackback
JSF 2 does not update the url after a form action? » Mihail Stoynov's blog

[…] did not know that the upper link solves that http://www.mkyong.com/spring-mvc/handling-duplicate-form-submission-in-spring-mvc/ (which is a problem I have in my current […]

Shiv
Guest
Shiv

Hi,
Great site.
i am facing a problem with this solution. the url is changed but form/command data is missing. please help me out on this.

Ravising
Guest
Ravising

I tried implementing the similar concept in my application. xmlViewResolver is able to match the corresponding redirectView. But after that SimpleUrlHandlerMapping is unable to get the proper controller i.e. customerSuccessController in this example. I have mapped everything properly but even then it is working properly. I am using spring 2.0 dtd.

Below is my configuration.

taskSuccessController

can you please help me out.

Ravising
Guest
Ravising

I tried implementing the similar concept in my application. xmlViewResolver is able to match the corresponding redirectView. But after that SimpleUrlHandlerMapping is unable to get the proper controller i.e. customerSuccessController in this example. I have mapped everything properly but even then it is working properly. I am using spring 2.0 dtd.

Below is my configuration.

 
   
       
    		
		






	
		
			
taskSuccessController
			
		

	
        
	 	
   

can you please help me out.

trackback
JSF : Page Forward vs Page Redirect

[…] The default page forward mechanism is more faster if compare to page redirection, because the page redirect added extra HTTP request to the server. So, only enable the page redirect when necessary, for example use the Post/Redirect/Get Design Pattern to solve the classic duplicated form submission problem. […]

trackback
Spring MVC RedirectView example

[…] DummyController.java //… public class DummyController extends AbstractController{   @Override protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception {   return new ModelAndView("redirect:DummyRedirectPage.htm");   } } Use case One of the use case is applying the “RedirectView” concept to solve the duplicate form submission in Spring MVC. […]