"Welcome To Ashok IT" "Spring Boot and MicroServices" Topic : Spring MVC - Form Submission Date : 21/11/2024 (Session - 71) _____________________________________________________________________________________________________________________________ Problem : Double Posting ========================== * If a user refreshes a page after submitting a form, he may accidentally post the content again by using refresh button(F5) resulting in duplicate submission, this causing duplicate record creation in database and it is known as "Double Posting Problem (or) Double submitting form". Example ======= 1) When we deploy the webapplication into tomcat server will get loaded into browser window with below URL http://localhost:1234/29_SpringMVC_FormSubmission_App/ >>>>>>>>>>>>>>>> GET Request 2) User can fill the data in the form and submit form to post Request Processor method, so that post request processor method will read the data from Dispatcherservlet using annotation called @ModelAttribute. 3) Post Request Processor Method will save form information into database table and If record got inserted successfully will direct to another view page i.e.,confirmation.jsp with below browser URL. http://localhost:1234/29_SpringMVC_FormSubmission_App/sendEnquiryDetails >>>>>>>>>>>>>>>> After Submitting the form 4) After rendering the confirmation.jsp page content into browser and user may try to refresh the page by using F5 key in keyboard it will leads for inserting duplication record in database table. ============================================== Example Application On Double Posting Problem ============================================== web.xml ======= AshokITFormSubmission ashokit org.springframework.web.servlet.DispatcherServlet 1 ashokit / mvc-servlet.xml =============== EnquiryController.java ====================== package com.ashokit.controller; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.servlet.ModelAndView; import com.ashokit.beans.Enquiry; import com.ashokit.services.EnquiryService; @Controller public class EnquiryController { @Autowired private EnquiryService enquiryService; @RequestMapping("/") public ModelAndView getEnquiryPage() { ModelAndView mav = new ModelAndView("enquiryDetails"); mav.addObject("enquiryForm", new Enquiry()); return mav; } @RequestMapping(value="sendEnquiry",method = RequestMethod.POST) public ModelAndView processEnquiryDetails(@RequestParam Map formData) { ModelAndView mav = new ModelAndView("confirmation"); System.out.println("FormData::::" + formData); //creating the object For Enquiry class for storing form data Enquiry enquiry = new Enquiry(); enquiry.setName(formData.get("firstName")); enquiry.setEmailId(formData.get("emailId")); enquiry.setContactNo(formData.get("contactNo")); enquiry.setCourseName(formData.get("courseName")); //sharing the data to view page mav.addObject("enquiryDetails", enquiry); return mav; } @RequestMapping(value="sendEnquiryDetails", method=RequestMethod.POST) public ModelAndView processEnquiry(@ModelAttribute("enquiryForm") Enquiry enquiry) { ModelAndView mav = new ModelAndView(); //sharing the data to view page mav.addObject("enquiryDetails", enquiry); //service call boolean saveEnquiryFlag = enquiryService.saveEnquiryDetails(enquiry); if(saveEnquiryFlag) { mav.setViewName("confirmation"); //mav.setViewName("enquiresInfo"); //mav.addObject("enquiryInfo", enquiryService.getAllEnquires()); }else { mav.setViewName("enquiryDetails"); } return mav; } } confirmation.jsp ================ <%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> confirmation.jsp
Student Name : ${enquiryDetails.name}
Course Name : ${enquiryDetails.courseName}
Your Enquiry is Received for above Details Admin Team will connect with you shortly.....
DBTable Records =============== 2000 Mahesh mahesh@gmail.com 123232 Angular 20-AUG-23 2001 Suresh Suresh@gmail.com 1232323 React 20-AUG-23 2002 Suresh Suresh@gmail.com 1232323 React 20-AUG-23 2003 Suresh Suresh@gmail.com 123232323 Devops 21-AUG-23 2004 Ramesh ramesh@gmail.com 1232323 SpringBoot 21-AUG-23 2005 Nagesh Nagesh@gmail.com 1232323 Devops 21-AUG-23 2006 Nagesh Nagesh@gmail.com 1232323 Devops 21-AUG-23 2007 Nagesh Nagesh@gmail.com 1232323 Devops 21-AUG-23 2008 Nagesh Nagesh@gmail.com 1232323 Devops 21-AUG-23 Solution : PRG Pattern ====================== * Post/Redirect/Get(PRG) is a web development design pattern that prevents the duplicate form submissions. * Programatically we can implement this design pattern with following approach 1) Post Request method having capability to redirect the request to GET Request after submitting the form. 2) In the Spring MVC we can have the option to redirect the request from one request processor method to another request method using "redirect" attribute. 3) Please find the below code snippet for how we can redirect the request between request processor methods @RequestMapping(value="processEnquiryForm", method=RequestMethod.POST) public String processEnquiry(){ return "redirect:enquiryList"; } @RequestMapping(value="enquiryList,method=RequestMethod.GET) public String displayEnquiryList(){ return "enquiryList"; } ========================================= Example Application On PRG Design Pattern ========================================= web.xml ======= Archetype Created Web Application mvc org.springframework.web.servlet.DispatcherServlet 25 mvc / mvc-servlet.xml =============== package com.ashokit.controller; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.support.RedirectAttributes; import com.ashokit.beans.Enquiry; import com.ashokit.services.EnquiryService; import jakarta.servlet.http.HttpServletRequest; @Controller public class EnquiryController { @Autowired private EnquiryService enquiryService; @RequestMapping("/") public ModelAndView getEnquiryPage() { ModelAndView mav = new ModelAndView("enquiryDetails"); mav.addObject("enquiryForm", new Enquiry()); return mav; } @RequestMapping(value="sendEnquiry",method = RequestMethod.POST) public ModelAndView processEnquiryDetails(@RequestParam Map formData) { ModelAndView mav = new ModelAndView("confirmation"); System.out.println("FormData::::" + formData); //creating the object For Enquiry class for storing form data Enquiry enquiry = new Enquiry(); enquiry.setName(formData.get("firstName")); enquiry.setEmailId(formData.get("emailId")); enquiry.setContactNo(formData.get("contactNo")); enquiry.setCourseName(formData.get("courseName")); //sharing the data to view page mav.addObject("enquiryDetails", enquiry); return mav; } @RequestMapping(value="sendEnquiryDetails", method=RequestMethod.POST) public String processEnquiry(@ModelAttribute("enquiryForm") Enquiry enquiry, HttpServletRequest request, RedirectAttributes redirectAttributes) { //service call boolean saveEnquiryFlag = enquiryService.saveEnquiryDetails(enquiry); if(saveEnquiryFlag) { //mav.setViewName("confirmation"); //mav.setViewName("enquiresInfo"); //mav.addObject("enquiryInfo", enquiryService.getAllEnquires()); System.out.println("Request Object Hashcode::::" + request.hashCode()); request.setAttribute("enquiryDetails", enquiry); redirectAttributes.addFlashAttribute("enquiryDetails",enquiry); return "redirect:acknowledge"; }else { return "enquiryDetails"; } } @RequestMapping(value="acknowledge",method=RequestMethod.GET) public String getAcknowledgementEnquiry(HttpServletRequest request) { System.out.println("Request Object Hashcode-1::::" + request.hashCode()); System.out.println("Request Information::::" + request.getAttribute("enquiryDetails")); return "confirmation"; } } Confirmation.jsp ================ <%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> confirmation.jsp
Student Name : ${enquiryDetails.name}
Course Name : ${enquiryDetails.courseName}
Your Enquiry is Received for above Details Admin Team will connect with you shortly.....
NOTE ==== 1) In Spring MVC We can have option for redirecting the request from one Request Processor method to another request processor method using redirection mechanism. 2) While redirecting request from one method(Source) to another method(Destination) the shared data is not accessable in destination method inorder to overcome this problem we can use flash attribute in spring MVC. Inorder to work with flash attribute as part of Spring MVC we need to use RedirectAttributes interface and contains method as addflashattribute(key,name); 3) If particular request processor method required request and response object means we need to use parameters of request processor method of HttpservletRequest,HttpServletResponse Object. 4) If you execute the above code by submitting data to the form after submission if user refreshing page by using F5 key at this time won't create the duplicate records. Earlier URL : http://localhost:1234/29_SpringMVC_FormSubmission_App/sendEnquiryDetails >>> Directly get into post request Present URL : http://localhost:1234/29_SpringMVC_FormSubmission_App/acknowledge >>> First will get into post request and redirected to get request ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++