| Sign In/My Account | View Cart |
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.
Figure 1: 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>
03:
04: <center><h1>Order Tickets</h1></center>
05:
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>
10:
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
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>
17:
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 |