Results 1 to 7 of 7

Thread: Double Click problem in spring MVC (anootation present)

  1. #1
    Join Date
    Sep 2008
    Posts
    9

    Default 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. #2
    Join Date
    Jan 2005
    Location
    Phoenix, AZ
    Posts
    139

    Default

    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.
    Willie Wheeler
    Author, Spring in Practice (Manning Publications)
    Spring stuff: Tutorials | Blog

  3. #3
    Join Date
    Sep 2008
    Posts
    9

    Default

    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

  4. #4
    Join Date
    Jan 2005
    Location
    Phoenix, AZ
    Posts
    139

    Default

    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.
    Willie Wheeler
    Author, Spring in Practice (Manning Publications)
    Spring stuff: Tutorials | Blog

  5. #5
    Join Date
    Sep 2008
    Posts
    9

    Default

    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.

  6. #6
    Join Date
    Jan 2005
    Location
    Phoenix, AZ
    Posts
    139

    Default

    No sweat; glad it helped. :-D
    Willie Wheeler
    Author, Spring in Practice (Manning Publications)
    Spring stuff: Tutorials | Blog

  7. #7
    Join Date
    May 2012
    Posts
    1

    Default

    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.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •