If the browser dies, then the session will timeout. The record will not stay locked (if you just keep an in-memory record of who is editing what). You could use a "do you want to save your changes" notification (a la GMail and others) to either save the data or send a request to clear the lock when they leave the edit screen.
On 2/21/07, Andrea Chiumenti <[EMAIL PROTECTED]> wrote:
... But if the browser dies for some reason (very frequent especially with MS products), then the record will remain locked, the only possibility with this solution would be to add a locking timeout with application scope. On 2/21/07, Robert Zeigler <[EMAIL PROTECTED]> wrote: > > In my case, it was straightforward: the user is considered to be > "still editing" if they have a browser window open to the edit page > for the object in question; if they navigate away from that page, the > system considers their edit session over. > > Robert > > > On Feb 21, 2007, at 2/212:47 AM , Peter Stavrinides wrote: > > > Hi Robert > > > > I like your idea, "you say that periodic ajax calls are sent to the > > server to inform of the fact that the user is still editing" how > > exactly do you track if a user is still editing? > > > > Robert Zeigler wrote: > >> The main problem with using a session timeout for the lock is that > >> it doesn't allow you to detect events where a user starts to edit > >> an object, does not finish, but remains active in the webapp; the > >> session won't die, and neither will your lock. You have to > >> incorporate time at least to some degree. I implemented similar > >> functionality in an application recently, but used a bit of ajax > >> magic to ensure that the lock was held for exactly as long as it > >> needed to be and no longer (while the user is editing the object, > >> periodic ajax calls are sent to the server to inform of the fact > >> that the user is still editing; if the user saves, the lock is > >> released; if the user moves to a different portion of the webapp > >> without saving or canceling the lock, the lock expires since there > >> are no more ajax calls to keep the lock valid) > >> > >> Robert > >> > >> On Feb 21, 2007, at 2/211:56 AM , Peter Stavrinides wrote: > >> > >>> I don't think the benefits justify the effort involved to > >>> maintain all those timestamps, its a bit too complex. Perhaps its > >>> better to stick to a single table as well... rather write the > >>> session id into the database to checkout a customer record. > >>> > >>> Allow updates to a customer record if its not checked out, and > >>> this way you have no worries about lock expiration etc. > >>> > >>> You should maintain an ASO that tracks all active sessions by > >>> session id. Once a user queries for a customer record that has > >>> been checked out, if the session ID still exists in the ASO, then > >>> refuse update access and grant only read access, simple and > >>> elegant. Once the user saves successfully release the lock in the > >>> database. if a session is interrupted for whatever reason, then > >>> using a session timeout of 20 or 30 minutes and a session > >>> listener you clean up removing the session ID from the ASO and > >>> database... so you are well covered. I am no guru like some of > >>> these other guys, but this works for me and its nice and > >>> simple... here is a brief implementation outline: > >>> > >>> public class ApplicationManager { > >>> > >>> /** variable to store the singleton ApplicationManager */ > >>> private static final ApplicationManager > >>> applicationManagerInstance_ = new ApplicationManager(); > >>> > >>> /** Hashtable containing visit history objects. <String,Visit> is > >>> the sessionid and the Visit Object */ > >>> private static ConcurrentHashMap<String,Visit> visitHistory_ = > >>> new ConcurrentHashMap<String,Visit>(); > >>> > >>> /** @return the ApplicationManager instance */ > >>> public synchronized static ApplicationManager getInstance(){ > >>> return applicationManagerInstance_; > >>> } > >>> > >>> } > >>> > >>> public class SessionMonitor implements HttpSessionListener { > >>> > >>> /** @see javax.servlet.http.HttpSessionListener#sessionDestroyed > >>> (javax.servlet.http.HttpSessionEvent) */ > >>> public void sessionDestroyed(HttpSessionEvent event) { > >>> String sid = event.getSession().getId(); > >>> ApplicationManager manager = ApplicationManager.getInstance(); > >>> manager.removeUserSession(sid); > >>> } > >>> > >>> > >>> Hivemodule.xml: > >>> > >>> <contribution configuration-id="tapestry.state.ApplicationObjects"> > >>> <state-object name="visit" scope="session"> > >>> <create-instance class="application.Visit"/> > >>> </state-object> > >>> </contribution> > >>> > >>> <contribution configuration-id="tapestry.state.ApplicationObjects"> > >>> <state-object name="ApplicationManager" scope="application"> > >>> <create-instance class="application.ApplicationManager"/> > >>> </state-object> > >>> </contribution> > >>> > >>> cheers, > >>> Peter > >>> > >>> Murray Collingwood wrote: > >>>> Wow - what a lot of responses. > >>>> > >>>> First a little more detail - use case (for example): > >>>> > >>>> Take a customer record, a basic record has previously been > >>>> created and the > >>>> customer has completed some forms so we are now wanting to > >>>> complete all of the > >>>> details about contact information, financial details, key > >>>> assets, health > >>>> information, etc, etc. The system relies on a number of > >>>> classifications which > >>>> need to be looked up, anyways, editing this record can take upto > >>>> 20 minutes. The size of this record certainly justifies breaking > >>>> it up into a number of > >>>> smaller records stored in separate tables, however the same > >>>> problem remains > >>>> because the user wants to see all of this information on 1 > >>>> (scrollable) web > >>>> page, we are still holding a lock on the information for the > >>>> duration of the > >>>> request. > >>>> > >>>> Potentially there are maybe 700 people who could be editing this > >>>> record for > >>>> different reasons. Accuracy of the information is critical - we > >>>> don't want > >>>> personal details being sent to a neighbour. > >>>> > >>>> The nature of the application means that users will be reviewing > >>>> a record each > >>>> year, and if any changes are made they are often made to the > >>>> same record around > >>>> the same time of the year - increasing the possibility of two > >>>> people wanting to > >>>> edit the record at the same time. > >>>> > >>>> Besides all of the above, the user has asked for exclusive > >>>> editing of a record - > >>>> such that other users can still read the existing record but > >>>> nobody else can > >>>> update the record while it is locked. The user understands the > >>>> concept of > >>>> networks issues and broken connections and therefore accepts a > >>>> timeout condition > >>>> on the lock of say 20 minutes. > >>>> > >>>> Next, how I will do this: > >>>> > >>>> 1. To establish a lock: > >>>> a. I need a LOCK table: foreign-key, timestamp, userid > >>>> b. In my Session I need a collection of timestamps > >>>> c. Create a timestamp value - add it to my collection of timestamps > >>>> d. Add a record to the LOCK table using my timestamp value > >>>> e. Select from the lock table by foreign-key - if mine is the > >>>> only record then > >>>> read the record and begin editing, the lock was successful > >>>> > >>>> 2. Release the lock: (PS This is the difficult bit) > >>>> a. Retrieve the LOCK records by foreign-key and userid, > >>>> hopefully there should > >>>> only be one. > >>>> b. Check the timestamp value against my Session collection of > >>>> timestamp values > >>>> c. If the timestamp is in my collection then save the edited > >>>> record and delete > >>>> my LOCK record > >>>> d. If the timestamp is not in my collection then the save has > >>>> failed - tell the > >>>> user gently > >>>> > >>>> 3. Dealing with an existing lock: > >>>> a. While trying to establish a lock I find 2 LOCK records > >>>> b. The latest record is mine, ignore that and look at the > >>>> earlier record > >>>> c. Look at the timestamp on the earlier record, if older than 20 > >>>> minutes then > >>>> delete this record and continue as normal > >>>> d. Look at the userid on the earlier record, if it is mine then > >>>> delete it and > >>>> continue as normal (assumes my browser died, rebooted my > >>>> computer, whatever, > >>>> it's very typical for people to go straight back to what they > >>>> were doing when > >>>> their system crashed) > >>>> e. If the timestamp is less than 20 minutes old then delete my > >>>> LOCK record and > >>>> report to the user that the record is locked by another user > >>>> > >>>> 4. You may want a maintenance process that cleans up broken > >>>> locks, automatically > >>>> deleting locks with a timestamp older than 24 hours. You could > >>>> schedule this > >>>> nightly or weekly - it's not critical. > >>>> > >>>> > >>>> Why the collection of timestamps? > >>>> > >>>> 1. It allows the user to use the back button on the browser, > >>>> either during > >>>> editing or after editing (if it didn't save correctly the first > >>>> time). > >>>> > >>>> 2. They might need to edit a related record in a different table > >>>> as part of > >>>> updating the main record - by storing each timestamp in a > >>>> session collection we > >>>> don't need to maintain these timestamps on our forms. > >>>> > >>>> > >>>> Why add the lock record first? > >>>> > >>>> To avoid sequence problems like: > >>>> a: User 1 looks for lock on id=1 - none found > >>>> b: User 2 looks for lock on id=1 - none found > >>>> c: User 1 adds a lock record > >>>> d: user 2 adds a lock record > >>>> Now the worst possible outcome is: > >>>> a: User 1 adds a lock record on id=1 > >>>> b: User 2 adds a lock record on id=1 > >>>> c: Both users read and find two records with short timestamps - > >>>> they are both > >>>> informed the record is in use and to try again later - both > >>>> records are deleted. > >>>> > >>>> > >>>> Finally - the weakness: > >>>> > >>>> 1. The lock this gives you is only guaranteed for 20 minutes. > >>>> Once that time is > >>>> up somebody else can overwrite your lock with their own. It is > >>>> better to set > >>>> this timeout higher rather than lower. > >>>> > >>>> 2. You can overwrite your own lock. A user could open two > >>>> browsers and edit the > >>>> same record in each, the latter save overwriting the first. > >>>> Hmmm, I think this > >>>> comes under 'user error'. > >>>> > >>>> > >>>> I think that explains it fairly well. > >>>> > >>>> Cheers > >>>> mc > >>>> > >>>> > >>>> > >>>> ------------------------------------------------------------------- > >>>> -- > >>>> To unsubscribe, e-mail: [EMAIL PROTECTED] > >>>> For additional commands, e-mail: [EMAIL PROTECTED] > >>>> > >>>> > >>> > >>> --Peter Stavrinides > >>> Albourne Partners (Cyprus) Ltd > >>> Tel: +357 22 750652 > >>> If you are not an intended recipient of this e-mail, please > >>> notify the sender, delete it and do not read, act upon, print, > >>> disclose, copy, retain or redistribute it. Please visit http:// > >>> www.albourne.com/email.html for important additional terms > >>> relating to this e-mail. > >> > >> > >> --------------------------------------------------------------------- > >> To unsubscribe, e-mail: [EMAIL PROTECTED] > >> For additional commands, e-mail: [EMAIL PROTECTED] > >> > > > > -- > > Peter Stavrinides > > Albourne Partners (Cyprus) Ltd > > Tel: +357 22 750652 > > If you are not an intended recipient of this e-mail, please notify > > the sender, delete it and do not read, act upon, print, disclose, > > copy, retain or redistribute it. Please visit http:// > > www.albourne.com/email.html for important additional terms relating > > to this e-mail. > > > > > > --------------------------------------------------------------------- > > To unsubscribe, e-mail: [EMAIL PROTECTED] > > For additional commands, e-mail: [EMAIL PROTECTED] > > > --------------------------------------------------------------------- > To unsubscribe, e-mail: [EMAIL PROTECTED] > For additional commands, e-mail: [EMAIL PROTECTED] > >
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]