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]


Reply via email to