You use the session id so that you don't maintain the reference to the
actual session.  When the session listener sees that the session dies,
he removes all object locks for that session.  Now, this still doesn't
solve the problem of one user opening multiple windows and trying to
edit the same object, but if they're that stupid, then they deserve to
lose their work (kidding of course, but just wanted to point out the
issue).


On 2/21/07, Andrea Chiumenti <[EMAIL PROTECTED]> wrote:
nice to know ;)

On 2/21/07, Peter Stavrinides <[EMAIL PROTECTED]> wrote:
>
> Andrea,
> You can do this If you create a state object that has an application
> scope... you can wire your session listener to it to add and remove the
> session id's.
>
> <state-object name="ApplicationManager" scope="application">
>
> Andrea Chiumenti wrote:
> > But session is user specific and you want to lock the record accross the
> > application, how whould you do this ?
> >
> > On 2/21/07, Robert Zeigler <[EMAIL PROTECTED]> wrote:
> >>
> >> Actually, no, if the browser dies, the record won't stay locked.
> >> The updating happens from the edit page; if the browser crashes,
> >> there's no edit page, so no updating, so the lock expires.
> >>
> >> Cheers,
> >>
> >> Robert
> >>
> >> On Feb 21, 2007, at 2/214:03 AM , Andrea Chiumenti 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]
> >>
> >>
> >
>
> --
> 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]

Reply via email to