Announcement Announcement Module
Collapse
No announcement yet.
Double Click problem in spring MVC (anootation present) Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Double Click problem in spring MVC (anootation present)

    How to prevent from double click problem in spring 2.5 MVC ? I have annotated with Controller method (which is controller in fact), with "showForm" method to display view, and "handleSubmit" method to handle spring form. When I do "double submit/double click" on submit button, this form is "double handled", and data from submited form are inserted in database twice. How to resolve this "double click" problem in spring with annotation ?

  • #2
    There are a couple things you can do, one on the client side and one on the server-side. On the client side, you can add JavaScript that disables the submit button immediately after the user presses it. On the server side, handle a successful submission by redirecting to the "success" page (whether that's a "thanks!" page or a confirmation page or whatever it is). That way if the user hits the reload button on the browser it won't resubmit your form.

    Hope that helps.

    Comment


    • #3
      I believe I did my controller the second way ("handle a successful submission by redirecting to the "success" page"):

      //****************** controller code ****************************//
      @Controller
      @RequestMapping("/main/create-place.html")
      public class CreatePlaceController {

      @Autowired
      UserDao userDao;
      @Autowired
      CreatePlaceValidator createPlaceValidator;

      @RequestMapping(method = RequestMethod.GET)
      public String showForm(ModelMap modelMap) {

      //backing bean
      CreatePlaceBean createPlaceBean = new CreatePlaceBean();

      modelMap.addAttribute("createPlaceBean", createPlaceBean);
      return "/main/create-place";
      }

      @RequestMapping(method = RequestMethod.POST)
      public String handleSubmit(@ModelAttribute("createPlaceBean") CreatePlaceBean createPlaceBean, BindingResult result, HttpSession session ) {

      createPlaceValidator.validate(createPlaceBean, result);
      if(result.hasErrors()){
      //if errors, back to the same page
      return "/main/create-place";
      }
      else {
      //if there is no errors run this code, and redirect to successfull page
      return "redirect:/main/main.html";

      }
      }
      }
      //************************************************** *********//

      when the form is correctly filled, and I keep quickly clicking on submitt button, until success page (main.html) appears, then I notice that this form, was two or three times (depends on how quick I was) submitted. In my database, there is rows with duplicated data, (only PK is diffrent, according to fact that primary key is unique). So I think I has done my controller with the second way you advise me. This problem occurs, after first click on submit button but before redirect to "success" page. According to my requirements, solution with JavaScript is not allowed. Thanks for your answer, but is there any other solution ? I do some research before first post, and I found post, where someone has written, that this problem was resolved in Web Flow, but not in Spring MVC, but that was post form 2006.

      P.S. Thanks for the answer

      Comment


      • #4
        Makes sense. I can see why JavaScript might not be allowed as the complete solution (some people may have it off) though if it were used in conjunction with a server-side dupe check it would only help. Anyway...

        On the server side, I'm not sure of best practices in this area, though I can think of a couple possible approaches.

        1) If there's a natural key over which you can define a uniqueness constraint, you might do that. The only thing is that constraint bleeds over into your entire app, not just your form double-submit, so you'd need to make sure the constraint is generally sensible. Also this isn't a general solution since not all data has a natural key.

        2) Before serving the form, you might autogenerate a random long value and include it in the form as a hidden field. Then when somebody submits the form you can grab the submitted hidden value and check it against a LAST_SUBMITTED_PLACE_KEY on the session. If it matches then reject the entire submission; otherwise accept it and store the submitted hidden value under the LAST_SUBMITTED_PLACE_KEY.

        There are probably more standard approaches to solving this but #2 should be pretty general. You could replace LAST_SUBMITTED_PLACE_KEY with LAST_SUBMITTED_FORM_KEY and still be in good shape, practically speaking.

        Comment


        • #5
          I followed the 2nd way, and it works. Now my controller looks like this, and works properly:

          //****************** controller code ****************************//
          @Controller
          @RequestMapping("/main/create-place.html")
          public class CreatePlaceController {

          @Autowired
          UserDao userDao;
          @Autowired
          CreatePlaceValidator createPlaceValidator;
          Long PLACE_KEY;

          @RequestMapping(method = RequestMethod.GET)
          public String showForm(ModelMap modelMap) {

          PLACE_KEY = (new Random()).nextLong();

          //backing bean
          CreatePlaceBean createPlaceBean = new CreatePlaceBean();

          modelMap.addAttribute("createPlaceBean", createPlaceBean);
          return "/main/create-place";
          }

          @RequestMapping(method = RequestMethod.POST)
          public String handleSubmit(@ModelAttribute("createPlaceBean") CreatePlaceBean createPlaceBean, BindingResult result, HttpSession session ) {

          if (((Long) session.getAttribute("LAST_PLACE_KEY"))!=null && ((Long) session.getAttribute("LAST_PLACE_KEY")).equals(PLA CE_KEY)) {
          return "redirect:/main/main.html";
          }
          session.setAttribute("LAST_PLACE_KEY", PLACE_KEY);


          createPlaceValidator.validate(createPlaceBean, result);
          if(result.hasErrors()){
          //if errors, back to the same page
          return "/main/create-place";
          }
          else {
          //if there is no errors run this code, and redirect to successfull page
          return "redirect:/main/main.html";
          }}}
          //************************************************** *********//

          Again, thanks a lot for your answer, it was good idea to store key in session.

          Comment


          • #6
            No sweat; glad it helped. :-D

            Comment


            • #7
              This was such a huge help to me that I just created an account simply to say thank you! I managed to fix this bug in under two hours from discovery with the help of this thread.

              Comment

              Working...
              X