Re: Record locking

2007-02-21 Thread Robert Zeigler
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 ConcurrentHashMapString,Visit visitHistory_ = new  
ConcurrentHashMapString,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 

Re: Record locking

2007-02-21 Thread Peter Stavrinides

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 ConcurrentHashMapString,Visit visitHistory_ = new 
ConcurrentHashMapString,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 

Re: Record locking

2007-02-21 Thread Robert Zeigler
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 ConcurrentHashMapString,Visit visitHistory_ =  
new ConcurrentHashMapString,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 

Re: Record locking

2007-02-21 Thread James Carman

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 ConcurrentHashMapString,Visit visitHistory_ =
  new ConcurrentHashMapString,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 

Re: Record locking

2007-02-21 Thread Robert Zeigler

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 ConcurrentHashMapString,Visit visitHistory_ =
 new ConcurrentHashMapString,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 

Re: Record locking

2007-02-21 Thread Robert Zeigler
To clarify, by updating I'm referring to the ajax notifications  
that the user is still editing the object.


Robert

On Feb 21, 2007, at 2/215:50 AM , Robert Zeigler 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 ConcurrentHashMapString,Visit visitHistory_ =
 new ConcurrentHashMapString,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 

Re: Record locking

2007-02-21 Thread Peter Stavrinides

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 ConcurrentHashMapString,Visit visitHistory_ =
  new ConcurrentHashMapString,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 

Re: Record locking

2007-02-21 Thread Andrea Chiumenti

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 ConcurrentHashMapString,Visit visitHistory_ =
   new ConcurrentHashMapString,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
   

Re: Record locking

2007-02-21 Thread James Carman

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 ConcurrentHashMapString,Visit visitHistory_ =
new ConcurrentHashMapString,Visit();
   
/** @return the ApplicationManager instance */
public synchronized static ApplicationManager getInstance(){
return applicationManagerInstance_;
}
   
}
   
public class SessionMonitor implements HttpSessionListener {
   
/** @see javax.servlet.http.HttpSessionListener#sessionDestroyed

Re: Record locking

2007-02-20 Thread James Carman

Leaving a database connection open for that period of time (possibly
minutes/hours) isn't advisable from what I understand.


On 2/19/07, Fred Janon [EMAIL PROTECTED] wrote:

Yep, SELECT for UPDATE is what's behind TRANSACTION_SERIALIZABLE...

On 2/20/07, [EMAIL PROTECTED] [EMAIL PROTECTED] wrote:

 How about using  a SELECT  . . . FOR UPDATE statement to select the record
 being edited.  Once you read the record it will be locked, and as long as
 you keep the transaction open for the duration of the edit then no other
 transaction will be able to select the same record for update.  If the
 transaction times out the DB management system will release the record for
 someone else to work with.

 Roland.

 

 If you stand up and be counted, from time to time you may get yourself
 knocked down. But remember this: A man flattened by an opponent can get up
 again. A man flattened by conformity stays down for good. - Thomas J.
 Watson, Jr.

 Fred Janon [EMAIL PROTECTED] wrote on 20/02/2007 10:44:20:

  Interesting question! I don't have any experience in doing this but it
 made
  me search in one of my Websphere book. Not sure if that would fulfill
 your
  requirements but TRANSACTION_SERIALIZABLE and
 PessimisticUpdate-Exclusive
  might be worth investigating. I am not sure what container you use and
 if
  JTA is available to you. I would check the JDBC driver as well, it might
  have some extra transaction support. Writing your own is probably pretty
  tempting when the answer is not obvious and you would know how it works.
 On
  the other side you have an extra write (at least) each time and need to
  manage the lock if the transaction is abandoned.
 
  If you have the time to investigate more, you'll probably a transaction
 guru
  soon. We, developers, have a tendency to avoid transactions and
 isolation
  levels like plague... Not easy development and test subjects as the lack
 of
  answers indicates...
 
  Good luck and let us know what solution you end up with, I am curious.
 
  Fred
 
  On 2/20/07, Murray Collingwood [EMAIL PROTECTED] wrote:
  
   James Carman james at carmanconsulting.com writes:
You can use optimistic locking.  When the user submits and they have
outdated data, then you just merge the object's data with what is in
the data store and show it back to the user for them to confirm it.
  
   In an application where the user can spend 20 minutes completing the
   information
   in a row, they are not going to be happy when they find out somebody
 else
   has
   been updating this same row and the information has all been merged.
 They
   then
   spend another 10 minutes cleaning up all of the duplicated changes.
  
   Even pessimistic locking is not sufficient.
  
   I need guaranteed write-exclusive locking for the duration of the
 request.
   ie
   when I read-for-update the record should be locked against all other
   read-for-update requests until I save my changes and release the lock.
  
   It sounds as though I'm going to have to write my own...again.
  
   Cheers
   mc
  
  
  
  
  
   -
   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]



Re: Record locking

2007-02-20 Thread Barry Books

Murray,

I also have records that need to be 'checked out' for some time and
your solution seems simple and elegant. So much so I may steal it.

I use one sequence for every primary key in the database so a table
named lock with

key primary key
timestamp timestamp
userid

should do it. UserId lets me know who has it.

to see if a record is locked and get lock key

select count(*) as locked, key, timestamp from lock where key = ? and
timestamp less than 20 minutes old group by key, timestamp

1 is locked 0 unlocked timestamp is the key to lock the recored

to lock a record

if key == null
insert into lock values ( key, now, userid)
else
update lock set timestamp = now, userid = ? where key = ? and timestamp = ?

if you update 1 row you've got it otherwise someone else does

to unlock

update lock set timestamp = null where key = ? and timestamp = ?

if you don't get 1 row updated something bad happened

Seems easy. Records are locked a max of 20 minutes and no races I can see.

-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



Re: Record locking

2007-02-20 Thread James Carman

The suggestion of using the http session (its id actually) was pretty
cool I thought.  That allows you to timeout the checkout/lock.  You
need to make sure (as pointed out) that the locks don't get orphaned,
thereby locking everyone out of the object/record perpetually
(obviously you could write an admin screen to unlock it).

On 2/20/07, Barry Books [EMAIL PROTECTED] wrote:

Murray,

I also have records that need to be 'checked out' for some time and
your solution seems simple and elegant. So much so I may steal it.

I use one sequence for every primary key in the database so a table
named lock with

key primary key
timestamp timestamp
userid

should do it. UserId lets me know who has it.

to see if a record is locked and get lock key

select count(*) as locked, key, timestamp from lock where key = ? and
timestamp less than 20 minutes old group by key, timestamp

1 is locked 0 unlocked timestamp is the key to lock the recored

to lock a record

if key == null
insert into lock values ( key, now, userid)
else
update lock set timestamp = now, userid = ? where key = ? and timestamp = ?

if you update 1 row you've got it otherwise someone else does

to unlock

update lock set timestamp = null where key = ? and timestamp = ?

if you don't get 1 row updated something bad happened

Seems easy. Records are locked a max of 20 minutes and no races I can see.

-
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]



Re: Record locking

2007-02-20 Thread Barry Books

Datebase timestamp seems better than a session id. Can't get
perpetually locked and works outside a webserver session.

-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



Re: Record locking

2007-02-20 Thread Murray Collingwood
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]



Re: Record locking

2007-02-20 Thread Peter Stavrinides
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 ConcurrentHashMapString,Visit visitHistory_ = new 
ConcurrentHashMapString,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 

Re: Record locking

2007-02-19 Thread James Carman

You can use optimistic locking.  When the user submits and they have
outdated data, then you just merge the object's data with what is in
the data store and show it back to the user for them to confirm it.

On 2/19/07, Murray Collingwood [EMAIL PROTECTED] wrote:

Hi

Jesse Kuhnert jkuhnert at gmail.com writes:
 hibernate.org

This is a rather simplistic answer, however I have been away and read the
documentation and am not convinced that this is providing a method that will
warn a user if somebody else if already updating a record.

Even this example of pessimistic locking appears to allow for previous data
changes to be overwritten:
http://forum.springframework.org/archive/index.php/t-10188.html

What would convince me?

An example of a read-for-update operation that returned a condition (or
exception) indicating that the requested object was currently locked by another
user.  I'm yet to find that in Hibernate.

Cheers
mc



-
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]



Re: Record locking

2007-02-19 Thread Murray Collingwood
James Carman james at carmanconsulting.com writes:
 You can use optimistic locking.  When the user submits and they have
 outdated data, then you just merge the object's data with what is in
 the data store and show it back to the user for them to confirm it.

In an application where the user can spend 20 minutes completing the information
in a row, they are not going to be happy when they find out somebody else has
been updating this same row and the information has all been merged.  They then
spend another 10 minutes cleaning up all of the duplicated changes.

Even pessimistic locking is not sufficient.  

I need guaranteed write-exclusive locking for the duration of the request. ie
when I read-for-update the record should be locked against all other
read-for-update requests until I save my changes and release the lock.

It sounds as though I'm going to have to write my own...again.

Cheers
mc





-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



Re: Record locking

2007-02-19 Thread Fred Janon

Interesting question! I don't have any experience in doing this but it made
me search in one of my Websphere book. Not sure if that would fulfill your
requirements but TRANSACTION_SERIALIZABLE and PessimisticUpdate-Exclusive
might be worth investigating. I am not sure what container you use and if
JTA is available to you. I would check the JDBC driver as well, it might
have some extra transaction support. Writing your own is probably pretty
tempting when the answer is not obvious and you would know how it works. On
the other side you have an extra write (at least) each time and need to
manage the lock if the transaction is abandoned.

If you have the time to investigate more, you'll probably a transaction guru
soon. We, developers, have a tendency to avoid transactions and isolation
levels like plague... Not easy development and test subjects as the lack of
answers indicates...

Good luck and let us know what solution you end up with, I am curious.

Fred

On 2/20/07, Murray Collingwood [EMAIL PROTECTED] wrote:


James Carman james at carmanconsulting.com writes:
 You can use optimistic locking.  When the user submits and they have
 outdated data, then you just merge the object's data with what is in
 the data store and show it back to the user for them to confirm it.

In an application where the user can spend 20 minutes completing the
information
in a row, they are not going to be happy when they find out somebody else
has
been updating this same row and the information has all been merged.  They
then
spend another 10 minutes cleaning up all of the duplicated changes.

Even pessimistic locking is not sufficient.

I need guaranteed write-exclusive locking for the duration of the request.
ie
when I read-for-update the record should be locked against all other
read-for-update requests until I save my changes and release the lock.

It sounds as though I'm going to have to write my own...again.

Cheers
mc





-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]




Re: Record locking

2007-02-19 Thread Kalle Korhonen

Just out of curiosity, can you tell more about your use case? I just have a
hard time believing you'd need something like this for all of your tables -
rather I'd assume it's something specific to a type of a record. And if it's
the latter, I'd just implement it in the application level along the lines
you'd suggested. But I'm not sure I'd call it locking, which I understand as
a database feature for enforcing atomic transactions. It'd be fairly easy to
implement the checking and enforcing of your edit rule in a Hibernate
Interceptor. For obtaining the application level lock you can use
optimistic locking; this is sort of the same as doing svn lock.

Kalle

On 2/19/07, Murray Collingwood [EMAIL PROTECTED] wrote:


James Carman james at carmanconsulting.com writes:
 You can use optimistic locking.  When the user submits and they have
 outdated data, then you just merge the object's data with what is in
 the data store and show it back to the user for them to confirm it.

In an application where the user can spend 20 minutes completing the
information
in a row, they are not going to be happy when they find out somebody else
has
been updating this same row and the information has all been merged.  They
then
spend another 10 minutes cleaning up all of the duplicated changes.

Even pessimistic locking is not sufficient.

I need guaranteed write-exclusive locking for the duration of the request.
ie
when I read-for-update the record should be locked against all other
read-for-update requests until I save my changes and release the lock.

It sounds as though I'm going to have to write my own...again.

Cheers
mc





-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]




Re: Record locking

2007-02-19 Thread James Carman

I would say just put a property on the object that says that it has
been checked out or something.  That way, you can tell a user that
tries to edit it that they can't because so and so has this record
checked out and is editing it.


On 2/19/07, Kalle Korhonen [EMAIL PROTECTED] wrote:

Just out of curiosity, can you tell more about your use case? I just have a
hard time believing you'd need something like this for all of your tables -
rather I'd assume it's something specific to a type of a record. And if it's
the latter, I'd just implement it in the application level along the lines
you'd suggested. But I'm not sure I'd call it locking, which I understand as
a database feature for enforcing atomic transactions. It'd be fairly easy to
implement the checking and enforcing of your edit rule in a Hibernate
Interceptor. For obtaining the application level lock you can use
optimistic locking; this is sort of the same as doing svn lock.

Kalle

On 2/19/07, Murray Collingwood [EMAIL PROTECTED] wrote:

 James Carman james at carmanconsulting.com writes:
  You can use optimistic locking.  When the user submits and they have
  outdated data, then you just merge the object's data with what is in
  the data store and show it back to the user for them to confirm it.

 In an application where the user can spend 20 minutes completing the
 information
 in a row, they are not going to be happy when they find out somebody else
 has
 been updating this same row and the information has all been merged.  They
 then
 spend another 10 minutes cleaning up all of the duplicated changes.

 Even pessimistic locking is not sufficient.

 I need guaranteed write-exclusive locking for the duration of the request.
 ie
 when I read-for-update the record should be locked against all other
 read-for-update requests until I save my changes and release the lock.

 It sounds as though I'm going to have to write my own...again.

 Cheers
 mc





 -
 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]



Re: Record locking

2007-02-19 Thread Luis Rodrigo Gallardo Cruz
On Mon, Feb 19, 2007 at 08:17:02PM -0500, James Carman wrote:
 I would say just put a property on the object that says that it has
 been checked out or something.  That way, you can tell a user that
 tries to edit it that they can't because so and so has this record
 checked out and is editing it.

One has to be careful with this approach, because the checkout must,
somehow, expire, otherwise you risk leaving an object permanently
uneditable if a client gets disconected/forgotten/whatever.

Just throwing random ideas about: How about making the 'checked-out'
property a weak hash, pointing to the editing user's session (or some
attribute within)? I assume the J2EE container will GC expired sessions,
thus automatically expiring the object's check-out.

-- 
Rodrigo Gallardo
GPG-Fingerprint: 7C81 E60C 442E 8FBC D975  2F49 0199 8318 ADC9 BC28
Zenophobia: the irrational fear of convergent sequences.


signature.asc
Description: Digital signature


Re: Record locking

2007-02-19 Thread James Carman

Just use the session id and set up an HttpSessionListener to remove
user's locks when their session expires.


On 2/19/07, Luis Rodrigo Gallardo Cruz [EMAIL PROTECTED] wrote:

On Mon, Feb 19, 2007 at 08:17:02PM -0500, James Carman wrote:
 I would say just put a property on the object that says that it has
 been checked out or something.  That way, you can tell a user that
 tries to edit it that they can't because so and so has this record
 checked out and is editing it.

One has to be careful with this approach, because the checkout must,
somehow, expire, otherwise you risk leaving an object permanently
uneditable if a client gets disconected/forgotten/whatever.

Just throwing random ideas about: How about making the 'checked-out'
property a weak hash, pointing to the editing user's session (or some
attribute within)? I assume the J2EE container will GC expired sessions,
thus automatically expiring the object's check-out.

--
Rodrigo Gallardo
GPG-Fingerprint: 7C81 E60C 442E 8FBC D975  2F49 0199 8318 ADC9 BC28
Zenophobia: the irrational fear of convergent sequences.

-BEGIN PGP SIGNATURE-
Version: GnuPG v1.4.6 (GNU/Linux)

iD8DBQFF2k6xAZmDGK3JvCgRAnMJAJ9TFHFOmAlciwoY2kQO+rYdMBcvxgCffRk0
tl1+WX/ZP82yNXrwuELwhcA=
=x6eX
-END PGP SIGNATURE-




-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



Re: Record locking

2007-02-19 Thread Jesse Kuhnert

Of course this all assumes that locking something is a good idea at
all from a usability / scalability pov. There are rare occasions where
it's needed but I'm skeptical nonetheless...

At the very best you could do some kind of comet approach to letting
the user know someone else is beginning (or is) also editing
something. (like gmail showing that yellow box when someone else is
replying to the same email thread) It's a big can of worms.

On 2/19/07, James Carman [EMAIL PROTECTED] wrote:

Just use the session id and set up an HttpSessionListener to remove
user's locks when their session expires.


On 2/19/07, Luis Rodrigo Gallardo Cruz [EMAIL PROTECTED] wrote:
 On Mon, Feb 19, 2007 at 08:17:02PM -0500, James Carman wrote:
  I would say just put a property on the object that says that it has
  been checked out or something.  That way, you can tell a user that
  tries to edit it that they can't because so and so has this record
  checked out and is editing it.

 One has to be careful with this approach, because the checkout must,
 somehow, expire, otherwise you risk leaving an object permanently
 uneditable if a client gets disconected/forgotten/whatever.

 Just throwing random ideas about: How about making the 'checked-out'
 property a weak hash, pointing to the editing user's session (or some
 attribute within)? I assume the J2EE container will GC expired sessions,
 thus automatically expiring the object's check-out.

 --
 Rodrigo Gallardo
 GPG-Fingerprint: 7C81 E60C 442E 8FBC D975  2F49 0199 8318 ADC9 BC28
 Zenophobia: the irrational fear of convergent sequences.

 -BEGIN PGP SIGNATURE-
 Version: GnuPG v1.4.6 (GNU/Linux)

 iD8DBQFF2k6xAZmDGK3JvCgRAnMJAJ9TFHFOmAlciwoY2kQO+rYdMBcvxgCffRk0
 tl1+WX/ZP82yNXrwuELwhcA=
 =x6eX
 -END PGP SIGNATURE-



-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]





--
Jesse Kuhnert
Tapestry/Dojo team member/developer

Open source based consulting work centered around
dojo/tapestry/tacos/hivemind. http://blog.opencomponentry.com

-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



Re: Record locking

2007-02-19 Thread RWinter
How about using  a SELECT  . . . FOR UPDATE statement to select the record
being edited.  Once you read the record it will be locked, and as long as
you keep the transaction open for the duration of the edit then no other
transaction will be able to select the same record for update.  If the
transaction times out the DB management system will release the record for
someone else to work with.

Roland.

If you stand up and be counted, from time to time you may get yourself
knocked down. But remember this: A man flattened by an opponent can get up
again. A man flattened by conformity stays down for good. - Thomas J.
Watson, Jr.

Fred Janon [EMAIL PROTECTED] wrote on 20/02/2007 10:44:20:

 Interesting question! I don't have any experience in doing this but it
made
 me search in one of my Websphere book. Not sure if that would fulfill
your
 requirements but TRANSACTION_SERIALIZABLE and PessimisticUpdate-Exclusive
 might be worth investigating. I am not sure what container you use and if
 JTA is available to you. I would check the JDBC driver as well, it might
 have some extra transaction support. Writing your own is probably pretty
 tempting when the answer is not obvious and you would know how it works.
On
 the other side you have an extra write (at least) each time and need to
 manage the lock if the transaction is abandoned.

 If you have the time to investigate more, you'll probably a transaction
guru
 soon. We, developers, have a tendency to avoid transactions and isolation
 levels like plague... Not easy development and test subjects as the lack
of
 answers indicates...

 Good luck and let us know what solution you end up with, I am curious.

 Fred

 On 2/20/07, Murray Collingwood [EMAIL PROTECTED] wrote:
 
  James Carman james at carmanconsulting.com writes:
   You can use optimistic locking.  When the user submits and they have
   outdated data, then you just merge the object's data with what is in
   the data store and show it back to the user for them to confirm it.
 
  In an application where the user can spend 20 minutes completing the
  information
  in a row, they are not going to be happy when they find out somebody
else
  has
  been updating this same row and the information has all been merged.
They
  then
  spend another 10 minutes cleaning up all of the duplicated changes.
 
  Even pessimistic locking is not sufficient.
 
  I need guaranteed write-exclusive locking for the duration of the
request.
  ie
  when I read-for-update the record should be locked against all other
  read-for-update requests until I save my changes and release the lock.
 
  It sounds as though I'm going to have to write my own...again.
 
  Cheers
  mc
 
 
 
 
 
  -
  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]



Re: Record locking

2007-02-19 Thread Fred Janon

Yep, SELECT for UPDATE is what's behind TRANSACTION_SERIALIZABLE...

On 2/20/07, [EMAIL PROTECTED] [EMAIL PROTECTED] wrote:


How about using  a SELECT  . . . FOR UPDATE statement to select the record
being edited.  Once you read the record it will be locked, and as long as
you keep the transaction open for the duration of the edit then no other
transaction will be able to select the same record for update.  If the
transaction times out the DB management system will release the record for
someone else to work with.

Roland.


If you stand up and be counted, from time to time you may get yourself
knocked down. But remember this: A man flattened by an opponent can get up
again. A man flattened by conformity stays down for good. - Thomas J.
Watson, Jr.

Fred Janon [EMAIL PROTECTED] wrote on 20/02/2007 10:44:20:

 Interesting question! I don't have any experience in doing this but it
made
 me search in one of my Websphere book. Not sure if that would fulfill
your
 requirements but TRANSACTION_SERIALIZABLE and
PessimisticUpdate-Exclusive
 might be worth investigating. I am not sure what container you use and
if
 JTA is available to you. I would check the JDBC driver as well, it might
 have some extra transaction support. Writing your own is probably pretty
 tempting when the answer is not obvious and you would know how it works.
On
 the other side you have an extra write (at least) each time and need to
 manage the lock if the transaction is abandoned.

 If you have the time to investigate more, you'll probably a transaction
guru
 soon. We, developers, have a tendency to avoid transactions and
isolation
 levels like plague... Not easy development and test subjects as the lack
of
 answers indicates...

 Good luck and let us know what solution you end up with, I am curious.

 Fred

 On 2/20/07, Murray Collingwood [EMAIL PROTECTED] wrote:
 
  James Carman james at carmanconsulting.com writes:
   You can use optimistic locking.  When the user submits and they have
   outdated data, then you just merge the object's data with what is in
   the data store and show it back to the user for them to confirm it.
 
  In an application where the user can spend 20 minutes completing the
  information
  in a row, they are not going to be happy when they find out somebody
else
  has
  been updating this same row and the information has all been merged.
They
  then
  spend another 10 minutes cleaning up all of the duplicated changes.
 
  Even pessimistic locking is not sufficient.
 
  I need guaranteed write-exclusive locking for the duration of the
request.
  ie
  when I read-for-update the record should be locked against all other
  read-for-update requests until I save my changes and release the lock.
 
  It sounds as though I'm going to have to write my own...again.
 
  Cheers
  mc
 
 
 
 
 
  -
  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]




Record locking

2007-02-18 Thread Murray Collingwood
Hi all

Many years ago I wrote a web application that utilitised a proprietary database.
 The database supported record locking however it was not suitable for a web
application.  So, I wrote a facility I called 'Long Locks'.  It required a
timestamp field be added to each table.  When a web user wanted to edit a record
they would check if the timestamp field was null, if so they wrote a timestamp
into the record and sent this along with the data to the user (the timestamp was
not visible by the user).  After they had completed updating the details (which
could take upto 20 minutes) they could then save the record, the timestamp would
be compared with the entry on the record and if they matched the update would be
committed.

This enabled a number of key features:

1. I was able to guarantee write access for a user when they requested a record
for update.  (If the record was already long-locked I would inform the user the
record was locked by another user).

2. I was always able to read the record

3. If a user abandoned a long-locked record the lock would eventually expire (we
set this to 20 minutes for our application)

I have been reading through a number of record-locking strategies but it seems
most of them are optimistic in that they hope nobody else has updated the record
since it was read, and in the event that it was all of your changes are lost. 
This is very frustrating for the user has just spent 20 minutes entering data!

I'm happy to write my own locking system again.  I was just wondering if anybody
knew of a better way - something to save me writing my own system again?

Cheers
mc



-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



Re: Record locking

2007-02-18 Thread Jesse Kuhnert

hibernate.org

On 2/18/07, Murray Collingwood [EMAIL PROTECTED] wrote:

Hi all

Many years ago I wrote a web application that utilitised a proprietary database.
 The database supported record locking however it was not suitable for a web
application.  So, I wrote a facility I called 'Long Locks'.  It required a
timestamp field be added to each table.  When a web user wanted to edit a record
they would check if the timestamp field was null, if so they wrote a timestamp
into the record and sent this along with the data to the user (the timestamp was
not visible by the user).  After they had completed updating the details (which
could take upto 20 minutes) they could then save the record, the timestamp would
be compared with the entry on the record and if they matched the update would be
committed.

This enabled a number of key features:

1. I was able to guarantee write access for a user when they requested a record
for update.  (If the record was already long-locked I would inform the user the
record was locked by another user).

2. I was always able to read the record

3. If a user abandoned a long-locked record the lock would eventually expire (we
set this to 20 minutes for our application)

I have been reading through a number of record-locking strategies but it seems
most of them are optimistic in that they hope nobody else has updated the record
since it was read, and in the event that it was all of your changes are lost.
This is very frustrating for the user has just spent 20 minutes entering data!

I'm happy to write my own locking system again.  I was just wondering if anybody
knew of a better way - something to save me writing my own system again?

Cheers
mc



-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]





--
Jesse Kuhnert
Tapestry/Dojo team member/developer

Open source based consulting work centered around
dojo/tapestry/tacos/hivemind. http://blog.opencomponentry.com

-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



Re: Record locking

2007-02-18 Thread Murray Collingwood
Hi

Jesse Kuhnert jkuhnert at gmail.com writes:
 hibernate.org

This is a rather simplistic answer, however I have been away and read the
documentation and am not convinced that this is providing a method that will
warn a user if somebody else if already updating a record.

Even this example of pessimistic locking appears to allow for previous data
changes to be overwritten:
http://forum.springframework.org/archive/index.php/t-10188.html

What would convince me?

An example of a read-for-update operation that returned a condition (or
exception) indicating that the requested object was currently locked by another
user.  I'm yet to find that in Hibernate.

Cheers
mc



-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]