Main Tutorials

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 Author

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

Comments

Subscribe
Notify of
12 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments
Nitesh Apte
10 years ago

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
10 years ago

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
10 years ago

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
10 years ago

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

mahesh
11 years ago

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
11 years ago

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

wayne
11 years ago

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

Shiv
12 years ago

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
12 years ago

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
12 years ago

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.

Durgadas
11 years ago
Reply to  mkyong

How do we achieve this using annotation ?
is it like return “redirect : success.htm”
create a controller which will be matched to success.htm and in get function , return success.jsp ?