ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.


AddThis Social Bookmark Button

Handling Multiple Submits

by Al Saganich

The primary purpose of the web site of today is to display dynamic content. At some point, the user sends input to a web application to be processed and the results returned. Typically, back-end operations occur quickly enough and all is well, from the user perspective. Occasionally, more time-consuming processing must take place, resulting in delays. Eventually the delay may become so noticable that the user believes he has made a mistake and either gives up or resubmits his request.

The problem of handling operations that run for long periods of time isn't a new one. Java provides a robust threading mechanism that can create background tasks. Additionally, with the arrival of the EJB 2.0 specification, Message-based EJBs (so-called MDBs) can be used to perform background operations. However, remember that these mechanisms are designed to handle asynchronous operations. You start a thread or background process, and at some later point you are notified or must check for a result, all asynchronously.

What about slightly long-running applications that are synchronous in nature but still take a noticable amount of processing? Imagine the scenario where a concert goer logs on to her favorite web site to order tickets for a show that's just gone on sale. (Recent sales of Bruce Springsteen tickets come to mind!) Under normal circumstances, the site performs fine and our would-be concertgoer purchases her tickets and is on her way. However, when a heavy load occurs, the server slows down, frustrating the user (who thinks her purchase request failed), so she hits the submit button again and again. Unfortunately, each hit of the submit button ends up ordering another set of tickets.

There are many ways to handle this type of scenario. The most obvious is to prevent the user from submitting the same request repeatedly in the first place. Another might be to somehow track that a user has previously submitted a request and revert to the previously-submitted action. The figure below shows the output from a simple servlet that processes the input as it arrives and assigns a ticket number to each request.

Processing Simple Submissions

Figure 1: Processing simple submissions
processing simple submissions

The primary and most effective way to handle the multiple submits problem is to prevent it from happening. ConcertTickets.html shows the underlying HTML for a simple form that captures the name of a concert and submits it to a servlet to order tickets. The process works perfectly when the web site responds quickly. However, if the web site bogs down and the submit is not processed quickly enough, the user gets frustrated and resubmits. The processing shown below results.

Listing 1: ConcertTickets.html

01: <html>
02: <head><title>Online Concert Tickets</title></head>
04: <center><h1>Order Tickets</h1></center>
06: <form name="Order" action="./SimpleOrder" method="GET">
07: <table border="2" width="50%" align="center"  bgcolor="CCCCCC">
08: <tr><td align="right" width="40%">Concert:  </td>
09: <td width="60%"><input type="text" name="Concert" value=""></td></tr>
11: <tr><td colspan="2" align="center">
12: <input type="submit" name="btnSubmit"
13: value="Do Submit"></td></tr>
14: </table>
15: </form>
16: </body>
17: </html>

Figure 2: Repeated submissions
repeated submissions

Preventing Multiple Submits

The simplest way to handle the multiple submit problem is to prevent it from happening. Below is a revised version of our form, which includes a small amount of JavaScript. The embedded JavaScript remembers if the submit button was previously pressed. On a resubmit, an alert pops up and the form is not submitted again. We can short-circuit the normal submit processing by adding an onClick attribute to the submit button. Every time the button is clicked, the onClick code executes. In our case, this results in the JavaScript checksubmitcount() being called. However, just calling a function doesn't really help. If we did no more then add the onClick, we'd get our popup alert box every time the submit button was pressed, and then immediately the submit would happen. The user would be alerted that she made a mistake, but the request would be sent anyway. This is an improvement only from the user perspective. The end result to the server is the same: multiple submits.

Listing 2: Concert2.html

01: <html>
. . .<!-- repeated code removed //-->
12: <input type="button" name="btnSubmit"
13: value="Do Submit"
14: onClick="checksubmitcount();"></td></tr>
15: </table>
16: </form>
18: <script language="javascript">
19: <!--
20: var submitcount = 0;
21: function checksubmitcount()
22: {
23: 	submitcount++;
24: 	if (1 == submitcount )
25: 	{
26: 		document.Order.submit();
27: 	}
28: 	else
29: 	{
30:  	if ( 2 == submitcount)
31:  		alert("You have already submitted  this form");
32:  	else
33:  		alert("You have submitted this form"
34:  		+ submitcount.toString()
35:  		+ " times already");
36: 	}
37: }
38: //-->
39: </script>
40: </body>
41: </html>

We can solve the problem by going one step further and subtly changing the way our page works. Sharp readers might have noticed one additional change to the form. The type of our button, line 12, originally submit, is now replaced by button. The look and feel of the page is identical. However, the default action associated with the form, shown on line 6, to invoke the servlet, is no longer automatic. We can now programmatically choose to submit the form to our server and our problem is solved--or is it?

Pages: 1, 2

Next Pagearrow