From: David L. <dav...@se...> - 2004-04-23 01:04:42
|
I'm running into what I'm told is a common problem, so I'm hoping that someone out there has a common solution. My users are submitting the page multiple times. Based on the user input and the state my code does a number of calculations. If I get the same input multiple times the data can become corrupted, which, of course, is a bad situation. I did see a post previously that dealt with database access, but since I'm doing more than just that (and I have the pleasure of working with oracle) I was trying for a 'better' solution. I had already known that I couldn't rely upon javascript to solve my problem. What I was thinking, is that since all of my calculations are done within the awake method of a single class (and then a particular page is chosen to forward to), I could just have a 'working' flag set and released in the awake method (and stored in the session) of this controller class. Setting and testing the flag works fine, but I am lacking some vital piece of knowledge because I now get blank pages. This is probably due to my calling self.endResponse() if the controller class receives a response while it is still processing. I'm hoping that by now someone has a good idea of what the problem and solution is. Is the solution something as simple storing the first response/transaction and then replacing the last response with the old one? Or am I going in the wrong direction? I am really hoping that someone has a solution because I know that telling the users to 'only click once' is not going to work. David London dav...@se... |
From: Eduardo E. <eel...@na...> - 2004-04-23 13:27:09
|
David, I was having this same problem and, from feed-back from the list, I=20 changed the way I obtained my database connections. I used to simply get=20 a cursor from a session stored connection. Now, I use a thread lock (I=20 this it's called so): : from threading import Lock : class MySessionData (): __init__ (self, ....): : : self._conLock =3D Lock() def cursor (self, cClass =3D None): self._conLock.acquire() if cClass !=3D None: c =3D self.db.cursor(cClass) else: c =3D self.db.cursor() self._conLock.release() return c This has been working very good for about a week, so I think it's the=20 solution. You say you're doing much more than simply database work, and you=20 forward to a calculated page. I that case, I'd lock the calculation=20 method (assuming it's short/fast enough): self._conLock.acquire() destination =3D self.calculations() self._conLock.release() return Hope this helps! Ed. David London wrote: > I'm running into what I'm told is a common problem, so I'm > hoping that someone out there has a common solution. >=20 > My users are submitting the page multiple times. >=20 > Based on the user input and the state my code does a number of > calculations. If I get the same input multiple times the data > can become corrupted, which, of course, is a bad situation. >=20 > I did see a post previously that dealt with database access, but > since I'm doing more than just that (and I have the pleasure of > working with oracle) I was trying for a 'better' solution. I had > already known that I couldn't rely upon javascript to solve my > problem. >=20 > What I was thinking, is that since all of my calculations are > done within the awake method of a single class (and then a > particular page is chosen to forward to), I could just have a > 'working' flag set and released in the awake method (and stored > in the session) of this controller class. > Setting and testing the flag works fine, but I am lacking some > vital piece of knowledge because I now get blank pages. This is > probably due to my calling self.endResponse() if the controller > class receives a response while it is still processing. >=20 > I'm hoping that by now someone has a good idea of what the > problem and solution is. >=20 > Is the solution something as simple storing the first > response/transaction and then replacing the last response with > the old one? Or am I going in the wrong direction? >=20 > I am really hoping that someone has a solution because I know > that telling the users to 'only click once' is not going to > work. >=20 > David London > dav...@se... >=20 >=20 >=20 >=20 >=20 >=20 > ------------------------------------------------------- > This SF.net email is sponsored by: The Robotic Monkeys at ThinkGeek > For a limited time only, get FREE Ground shipping on all orders of $35 > or more. Hurry up and shop folks, this offer expires April 30th! > http://www.thinkgeek.com/freeshipping/?cpg=3D12297 > _______________________________________________ > Webware-discuss mailing list > Web...@li... > https://lists.sourceforge.net/lists/listinfo/webware-discuss >=20 --=20 Eduardo Elgueta Senior Consultant Navix correo/email: eel...@na... tel=E9fono/phone: +56 (2) 209-8905 celular/mobile: +56 (9) 821-0033 web: www.navix.cl Av. Pedro de Valdivia 555 Of. 216 Providencia 7500913 Santiago, Chile |
From: Matt F. <ma...@da...> - 2004-04-26 12:23:52
|
I'm not sure what the *best* solution to that is, but if you've got something that you like, and are merely having trouble with the blank page, I can help. self.endResponse() simply stops output; it doesn't send a redirect message to the browser. You want "self.sendRedirectAndEnd()" which you pass an url. It will stop output *and* tell the browser to move along. Another note: the "working flag" may only exist in one thread in webkit; if you have enough concurrency happening, that flag may not exist in other instances of your servlet; it's probably likely that a client will get the same instance often, but I don't think it's guaranteed. Perhaps moving your working flag into your database wrapper or some such is better. I watched a client use a CMS that we're working on yesterday. He did the same thing you're describing: I watched as he said "wait; what was that?" and went back and re-submitted the same input 3 times in about 10 seconds. It doesn't corrupt our database, but it sure fills it with junk. We can't rely on a flag, though, because it only takes a blip to store the data; there's no concurrency problem, just redundancy. Blah. There's probably a way to "cache" an input chunk in session, and not to process similar chunks if it was seen in the last "n" seconds. I've got to think about that. David London wrote: >I'm running into what I'm told is a common problem, so I'm >hoping that someone out there has a common solution. > >My users are submitting the page multiple times. > > >Based on the user input and the state my code does a number of >calculations. If I get the same input multiple times the data >can become corrupted, which, of course, is a bad situation. > >I did see a post previously that dealt with database access, but >since I'm doing more than just that (and I have the pleasure of >working with oracle) I was trying for a 'better' solution. I had >already known that I couldn't rely upon javascript to solve my >problem. > >What I was thinking, is that since all of my calculations are >done within the awake method of a single class (and then a >particular page is chosen to forward to), I could just have a >'working' flag set and released in the awake method (and stored >in the session) of this controller class. >Setting and testing the flag works fine, but I am lacking some >vital piece of knowledge because I now get blank pages. This is >probably due to my calling self.endResponse() if the controller >class receives a response while it is still processing. > >I'm hoping that by now someone has a good idea of what the >problem and solution is. > >Is the solution something as simple storing the first >response/transaction and then replacing the last response with >the old one? Or am I going in the wrong direction? > >I am really hoping that someone has a solution because I know >that telling the users to 'only click once' is not going to >work. > >David London >dav...@se... > > > > > > >------------------------------------------------------- >This SF.net email is sponsored by: The Robotic Monkeys at ThinkGeek >For a limited time only, get FREE Ground shipping on all orders of $35 >or more. Hurry up and shop folks, this offer expires April 30th! >http://www.thinkgeek.com/freeshipping/?cpg=12297 >_______________________________________________ >Webware-discuss mailing list >Web...@li... >https://lists.sourceforge.net/lists/listinfo/webware-discuss > > > |
From: David L. <dav...@se...> - 2004-04-26 19:02:59
|
Hello all, I'm posting this for a few reasons. 1) To publicly acknowledge the help that I got from Ken Lalonde (Again, many thanks). 2) To summarize everything so that someone else can find this solution in the archives. 3) See if anyone can find a problem/issue that I have not yet considered. Building on Ken's code that can be found here, http://sourceforge.net/mailarchive/forum.php?thread_id=3561201&forum_id=3505 Firstly, all of my pages now include a unique identifier that is contained within a hidden field on the page. The identifier is a combination of the time and a random number (as per Ken's code). In my Controller class (which makes decisions about input and forwards request to other pages), immediately after the base class awake method I check to see if this page can be processed. This check consists of 2 parts. In the first part I check a dictionary that is stored in the session. The keys to this dictionary are the unique page identifiers. If the identifier is found in the dictionary, then the page can NOT be processed. This is the same check that is done within Ken's code. If the identifier is not found then we check the session to see if a 'processing' flag has been set. If the flag exists, then we can NOT process the page since we are currently processing a different request. If the above method indicates that we can process the page, then we set a processing flag and start the various calculations. These calculations can take less than a second or up to a minute (slow machine and slow database connection). As the request finishes off control is forwarded to another page (goodInputPage, badInputPage, needMoreInputPage, etc). The forwarded page writes out all of the information that it recovered from the database. Then, it it's respond method, it removes the processing flag (if it exists) and sets the 'lastPageVisited' session variable. If the user submits a request that can not be processed, then the writeContent of the controller class is called. This is the only time that this code is called. It will display a page telling the user that the request is still being processed and supply them with a method to submit the page. if they submit the page will the processing flag is still set they will be directed back to the 'wait' page. Eventually the processing flag will be removed and the user will submit the page. This will allow the controller class to make some decisions based on the input it was given. However, at this point, the page will have no input. There will be the submit button, but that has been stripped out of the request in the method that checks if the page can be processed. If the page is submitted, but there are no other fields in the request, then the last page that was displayed is re-displayed. As noted above, the last displayed page is stored in the session. Due to the hierarchy of classes, the controller class never sets itself as a last displayed page. If I have all this figured out then the original response is being processed and will eventually update the session data with whatever is appropriate and the user can sit in the 'canProcess' loop for as long as necessary for the original response to complete. If anyone can see a problem with this, please say something. It seems to be working right now, but I don't like leaving bugs lying around. David London |