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]

Reply via email to