Update view of database on multiple web clients

D

David Segall

I have been asked to build a collaborative web application. It is
basically equivalent to having multiple web browsers accessing a
record in a database and, when one user alters the record then all the
browsers that are viewing the record should immediately see the
altered record. The problem is simplified because the users log into
my application and all the users in one group want the same record
although there can be many groups logged in.

I think I would like to use JSF for the application and use
XMLHttpRequest to update the database. My current thought is for all
the browsers to issue an XMLHttpRequest when the page is loaded and
for the server to reply to it with the new data and the new data's
location when an update request is received from a client. Each
browser would then issue the same request as the one they issued on
load.

Does the above sound as though it could work? Do you have a better
idea? Is there are a "standard" way of doing this? TIA
 
R

Rhino

David Segall said:
I have been asked to build a collaborative web application. It is
basically equivalent to having multiple web browsers accessing a
record in a database and, when one user alters the record then all the
browsers that are viewing the record should immediately see the
altered record. The problem is simplified because the users log into
my application and all the users in one group want the same record
although there can be many groups logged in.

I think I would like to use JSF for the application and use
XMLHttpRequest to update the database. My current thought is for all
the browsers to issue an XMLHttpRequest when the page is loaded and
for the server to reply to it with the new data and the new data's
location when an update request is received from a client. Each
browser would then issue the same request as the one they issued on
load.

Does the above sound as though it could work? Do you have a better
idea? Is there are a "standard" way of doing this? TIA

I'm not sure if what I'm about to say will be relevant to you but the
situation you describe is a well-known issue in the database world. In a
database environment, potentially hundreds or thousands of users could be
trying to access the same piece of data.

Database people long ago agreed that it was a very bad idea (in most cases)
for anyone but the updater of a piece of data to see the update until it had
been committed, i.e. the updater is satisfied that the update has worked and
that it really ought to be made. At that point, the updater's application
issues a commit, which works something like a save and writes the update to
the database, and then the data becomes available for the rest of the world
to see. In the meantime, anyone else who wanted to see the data would have
to wait until the lock was released and could potentially time out waiting.

Now, the actual details are somewhat more complicated and vary from one
database vendor to another, but that is the gist of it. That brings me to my
suggestion: since this problem has already been well thought out in the
database world and solutions have been worked out that are generally
satisfactory for most circumstances, maybe you should put your data in a
database and let each of the various users of the data access it via the
standard locking mechanism provided by the database? That relieves your
application of most of the work and leaves it in the very capable hands of
the database.

That, in my opinion, would be the "standard" way of handling the problem. In
fact, I'd be extremely reluctant to do it any other way unless you are
prepared to write your own code that does all the same things the database
does anyway. And if you did _that_ I would question why you wanted to
reinvent the wheel by re-writing all sorts of code that already been
thoroughly tested and well-proven in the database.

Just my two cents worth,
 
D

David Segall

Rhino said:
I'm not sure if what I'm about to say will be relevant to you but the
situation you describe is a well-known issue in the database world. In a
database environment, potentially hundreds or thousands of users could be
trying to access the same piece of data.

Database people long ago agreed that it was a very bad idea (in most cases)
for anyone but the updater of a piece of data to see the update until it had
been committed, i.e. the updater is satisfied that the update has worked and
that it really ought to be made. At that point, the updater's application
issues a commit, which works something like a save and writes the update to
the database, and then the data becomes available for the rest of the world
to see. In the meantime, anyone else who wanted to see the data would have
to wait until the lock was released and could potentially time out waiting.

Now, the actual details are somewhat more complicated and vary from one
database vendor to another, but that is the gist of it. That brings me to my
suggestion: since this problem has already been well thought out in the
database world and solutions have been worked out that are generally
satisfactory for most circumstances, maybe you should put your data in a
database and let each of the various users of the data access it via the
standard locking mechanism provided by the database? That relieves your
application of most of the work and leaves it in the very capable hands of
the database.

That, in my opinion, would be the "standard" way of handling the problem. In
fact, I'd be extremely reluctant to do it any other way unless you are
prepared to write your own code that does all the same things the database
does anyway. And if you did _that_ I would question why you wanted to
reinvent the wheel by re-writing all sorts of code that already been
thoroughly tested and well-proven in the database.
You are absolutely right. The standard way of handling the problem in
the database world is to pretend that it does not exist. If two users
try to alter the same field in a database at about the same time the
second user's version will prevail and neither user will be informed
of the other's attempt to alter the field. This is usually acceptable
because the users are considered to be independent and it is not
possible to decide which of them has the correct value.

In my application the users are collaborating to update the record and
they all need to discuss if the latest change is an improvement or if
the old, or some other, value for a field is "better". If two users
happen to update the field at the same time the second users version
will also prevail but the first user must be given the chance to see
it and complain about it. Of course, the integrity of the database
needs to be preserved and my application will use the standard
facilities of the database to ensure that it is.
 
R

Roedy Green

Does the above sound as though it could work? Do you have a better
idea? Is there are a "standard" way of doing this? TIA

You are going to need some smarts in the client to handle this without
driving your users insane, e.g. Applet or JAWS.

The Applet either has to poll for things if finds of interest with a
request of the form"if X has changed since T, please send a copy.".
The problem here is slow response.

or the server has to send them unrequested when it determines that
info is of interest to that client. The server then maintains the
state of what he client SHOULD have, which of course may not match
what it DOES have. The problems here are fragility and complexity. You
can create a huge amount of server disk I/O obsessively tracking who
is currently looking at which bytes in the database.

A third approach is a combination. The server sends short "this
information has changed" invalidation notices to any client vaguely
interested (who may or may not have the item in its cache). The
client background thread marks it invalid in their caches, and may or
may not request an update. The advantage of this approach is you don't
have to micro manage what each client is caching from the server; you
need keep only a rough idea what they want to be notified of. A
background thread in each Applet does most of the work of state
tracking.

The third approach is how the CSL School system worked, giving high
performance on klunky hardware.
 
R

Roedy Green

That relieves your
application of most of the work and leaves it in the very capable hands of
the database.

But it does not touch the problem of updating the client's display if
somebody else changes the backing value.
 
R

Roedy Green

If two users
happen to update the field at the same time the second users version
will also prevail but the first user must be given the chance to see
it and complain about it.

Given subnanosecond clocks in CPUs, there is no chance of two updates
being simultaneous. You have to define a band of time by which YOU
means simultaneous, for which this evasive action gets invoked.

It would work like this. When you update, you timestamp with the
update. Before you update you look at the timestamp. if it was > X
seconds ago, you go ahead with the update. Otherwise do your evasion
thing, letting a user update his own change without debate, if there
has not been recent debate.
 
R

Rhino

You are absolutely right. The standard way of handling the problem in
the database world is to pretend that it does not exist. If two users
try to alter the same field in a database at about the same time the
second user's version will prevail and neither user will be informed
of the other's attempt to alter the field. This is usually acceptable
because the users are considered to be independent and it is not
possible to decide which of them has the correct value.
I'm not sure which databases you have used but your description does NOT
match the database I know best, DB2. In DB2, the lock manager ensures that
two users could never simultaneously hold the update lock for the row
containing the data value; only the user with the update lock can update a
given row. Period. A row held with an update lock would never be seen by any
other user except in the special case of binding with the UR isolation
level; if the second user's program is bound with UR (uncommitted read) he
can _read_ [but NOT UPDATE] any row of any table, even a row that is
currently locked for update whose update has not been committed yet. [Using
UR is risky: the second user might see the row after it has been updated but
not committed, make a decision based on the value in that row, and then find
that the update has been rolled back because the first user chose not to
commit it; that could render the second user's decision inappropriate if the
data value that was the basis of that decision was inappropriate.] In DB2,
the second user [and any subsequent users] could not see an uncommitted
update except with the UR option: if they weren't using UR, they would have
to wait until the first user committed the update before they could see the
updated row and they could time out waiting for that to happen.

I don't know how locking works on any of the other databases but this is the
way DB2 works, in a nutshell. (It's actually a good bit more complicated
than I've described if you consider "real" locks and "intent" locks,
tablespace locks, etc. but I've given you the gist of it.)
In my application the users are collaborating to update the record and
they all need to discuss if the latest change is an improvement or if
the old, or some other, value for a field is "better". If two users
happen to update the field at the same time the second users version
will also prevail but the first user must be given the chance to see
it and complain about it. Of course, the integrity of the database
needs to be preserved and my application will use the standard
facilities of the database to ensure that it is.

So, each collaborator works in lockstep with the others, reviewing the same
rows more or less simultaneously and you don't commit the update until there
is a unanimous vote by all collaborators that the update is correct?
 
J

Jon Martin Solaas

David Segall wrote:

I think I would like to use JSF for the application and use
XMLHttpRequest to update the database. My current thought is for all
the browsers to issue an XMLHttpRequest when the page is loaded and
for the server to reply to it with the new data and the new data's
location when an update request is received from a client. Each
browser would then issue the same request as the one they issued on
load.

That is pretty much the normal way of doing things. The actual means of
retrieving data is not important, jdbc, XMLHttpRequest, EJB-calls or
whatever.

But the clients view will only get updated when the client pulls data.
If that's acceptable your approach will work just fine. This is however
not the same as having all the clients "immediately see the altered
record".
 
D

David Segall

Rhino said:
You are absolutely right. The standard way of handling the problem in
the database world is to pretend that it does not exist. If two users
try to alter the same field in a database at about the same time the
second user's version will prevail and neither user will be informed
of the other's attempt to alter the field. This is usually acceptable
because the users are considered to be independent and it is not
possible to decide which of them has the correct value.
I'm not sure which databases you have used but your description does NOT
match the database I know best, DB2. In DB2, the lock manager ensures that
two users could never simultaneously hold the update lock for the row
containing the data value; only the user with the update lock can update a
given row. Period. A row held with an update lock would never be seen by any
other user except in the special case of binding with the UR isolation
level; if the second user's program is bound with UR (uncommitted read) he
can _read_ [but NOT UPDATE] any row of any table, even a row that is
currently locked for update whose update has not been committed yet. [Using
UR is risky: the second user might see the row after it has been updated but
not committed, make a decision based on the value in that row, and then find
that the update has been rolled back because the first user chose not to
commit it; that could render the second user's decision inappropriate if the
data value that was the basis of that decision was inappropriate.] In DB2,
the second user [and any subsequent users] could not see an uncommitted
update except with the UR option: if they weren't using UR, they would have
to wait until the first user committed the update before they could see the
updated row and they could time out waiting for that to happen.

I don't know how locking works on any of the other databases but this is the
way DB2 works, in a nutshell. (It's actually a good bit more complicated
than I've described if you consider "real" locks and "intent" locks,
tablespace locks, etc. but I've given you the gist of it.)
In my application the users are collaborating to update the record and
they all need to discuss if the latest change is an improvement or if
the old, or some other, value for a field is "better". If two users
happen to update the field at the same time the second users version
will also prevail but the first user must be given the chance to see
it and complain about it. Of course, the integrity of the database
needs to be preserved and my application will use the standard
facilities of the database to ensure that it is.

So, each collaborator works in lockstep with the others, reviewing the same
rows more or less simultaneously and you don't commit the update until there
is a unanimous vote by all collaborators that the update is correct?
 
D

David Segall

Rhino said:
I'm not sure which databases you have used but your description does NOT
match the database I know best, DB2. In DB2, the lock manager ensures that
two users could never simultaneously hold the update lock for the row
containing the data value; only the user with the update lock can update a
given row.
This is the routine method of protecting the _database_. It does
nothing for the user. I prefer interactive applications that allow any
user to read the database and only obtain an update lock in response
to a "Save" from the user. The alternative is to risk a user going off
to lunch leaving a database record locked.
So, each collaborator works in lockstep with the others, reviewing the same
rows more or less simultaneously and you don't commit the update until there
is a unanimous vote by all collaborators that the update is correct?
That is the idea but, in practice, it is much easier to allow any user
to actually perform an update to show the others what the effect would
be. There are some fields displayed that the users need to consider,
which are derived from the changed data. A combination of Undo/Redo
and Restore will be used to minimise the amount of data users need to
enter.
 
D

David Segall

Jon Martin Solaas said:
David Segall wrote:



That is pretty much the normal way of doing things. The actual means of
retrieving data is not important, jdbc, XMLHttpRequest, EJB-calls or
whatever.
I believed that the only way of making an asynchronous request is by
using XMLHttpRequest. Is that not so?
But the clients view will only get updated when the client pulls data.
If that's acceptable your approach will work just fine. This is however
not the same as having all the clients "immediately see the altered
record".
I thought my proposed method effectively resulted in the server
pushing data because the client had requested the data when it was
loaded and the server responded when it had changed data. Have I
misunderstood XMLHttpRequest?
 
D

David Segall

Roedy Green said:
You are going to need some smarts in the client to handle this without
driving your users insane, e.g. Applet or JAWS.

The Applet either has to poll for things if finds of interest with a
request of the form"if X has changed since T, please send a copy.".
The problem here is slow response.

or the server has to send them unrequested when it determines that
info is of interest to that client. The server then maintains the
state of what he client SHOULD have, which of course may not match
what it DOES have. The problems here are fragility and complexity. You
can create a huge amount of server disk I/O obsessively tracking who
is currently looking at which bytes in the database.

A third approach is a combination. The server sends short "this
information has changed" invalidation notices to any client vaguely
interested (who may or may not have the item in its cache). The
client background thread marks it invalid in their caches, and may or
may not request an update. The advantage of this approach is you don't
have to micro manage what each client is caching from the server; you
need keep only a rough idea what they want to be notified of. A
background thread in each Applet does most of the work of state
tracking.

The third approach is how the CSL School system worked, giving high
performance on klunky hardware.
 
D

David Segall

Roedy Green said:
You are going to need some smarts in the client to handle this without
driving your users insane, e.g. Applet or JAWS.
Agreed. Did you omit Javascript because it won't work or because you
don't like Javascript?
the server has to send them unrequested when it determines that
info is of interest to that client. The server then maintains the
state of what he client SHOULD have, which of course may not match
what it DOES have. The problems here are fragility and complexity. You
can create a huge amount of server disk I/O obsessively tracking who
is currently looking at which bytes in the database.
Thanks, I will have a look at using an Applet. The tracking problem is
not severe because the server knows by the login which database record
the client is looking at.

I have probably been swayed by the current Ajax hype but it seems that
Applets are "deprecated". Is there any truth to that?
 
R

Roedy Green

Agreed. Did you omit Javascript because it won't work or because you
don't like Javascript?

I think it should be not be used for several reasons. The main one is
I predict will be banned overnight from corporate desktops after a
particularly bad security scare.

Then what do you do?
 
S

steve

Given subnanosecond clocks in CPUs, there is no chance of two updates
being simultaneous. You have to define a band of time by which YOU
means simultaneous, for which this evasive action gets invoked.

It would work like this. When you update, you timestamp with the
update. Before you update you look at the timestamp. if it was > X
seconds ago, you go ahead with the update. Otherwise do your evasion
thing, letting a user update his own change without debate, if there
has not been recent debate.

no that would be very dangerous, basically when you want to edit a record the
editing user MUST obtain a lock, you do not /cannot save the record data ,
edit it then put it back, without some sort of locking system.

in the case of oracle that would be "select for update"

because there is every chance a user may start an edit then take several
minutes to change the data ,
( some of my users excel at this action, taking more than 5-10 minutes),
throw into that mix multi-site replication, and things get interesting.


Therefore whilst the user has a lock on the record, other users can only see
it, any attempt to edit it, should return "record locked please try again
later"


I would do it with a small applet.
 
S

steve

This is the routine method of protecting the _database_. It does
nothing for the user. I prefer interactive applications that allow any
user to read the database and only obtain an update lock in response
to a "Save" from the user. The alternative is to risk a user going off
to lunch leaving a database record locked.

you implement a timer thread , that gives the user a particular amount of
time, if they do not complete, then the mods are thrown away.
That is the idea but, in practice, it is much easier to allow any user
to actually perform an update to show the others what the effect would
be. There are some fields displayed that the users need to consider,
which are derived from the changed data. A combination of Undo/Redo
and Restore will be used to minimise the amount of data users need to
enter.

yes it is very easy, but it ultimately leads to serious data corruption, and
cannot be scaled.
It is also the sign of a very badly coded/implemented system.

Steve
 
J

Jon Martin Solaas

David said:
I believed that the only way of making an asynchronous request is by
using XMLHttpRequest. Is that not so?

I wasn't aware that you were talking about javascript on the browser, I
thought you were talking about making the request in your java/jsp code.
What I *do* think is that support for other data than text/xml should be
supported as well.
I thought my proposed method effectively resulted in the server
pushing data because the client had requested the data when it was
loaded and the server responded when it had changed data. Have I
misunderstood XMLHttpRequest?

No, I think you got it :)
 
J

Jon Martin Solaas

Roedy said:
I think it should be not be used for several reasons. The main one is
I predict will be banned overnight from corporate desktops after a
particularly bad security scare.

Then what do you do?

Does it make sense to ban applets and not javascript? Well, in the
corporate world thinks doesn't have to make sense ... I know ... :-/
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top