RE: Synchronized session bean?

2001-10-11 Thread Curt Smith


  Simply put if there's $5 left in the bank, you wouldn't want to have
  a user withdraw $5 with two different web browsers if they hit
  submit at the same time... so we kinda want it to be like there's
  only one teller window, and the servlets have to wait their
  turn.

A poster already mentioned that simplistic solutions might not work
in a clustered environment.  I agree that designs that work due
to timing or happen stance that may not remain constant are weak 
designs bound to have problems in deployment.

This problem is the the classic stale update scenario.  Multiple
clients show $5 available to with draw.  They all hit submit
at once.  How to guard against an over draft in a robust and 
repeatable in all scenarios way??

The most offered solution that I've heard and I've implemented uses
optimistic concurrancy guarded with a row version number;

- add a version number or modification date to your data base tables.
  I use a sequence number that trigger auto-increaments on update.

- Your Model class (represents a data base table row) returned by 
  DAO's and Entities include the sequence number.

- Your presentation tier has a reference of the model (including the 
  row version number)  and all display $5 and internally held in
  the session is an instance of the Model used to generate the 
  dynamic data by your View (MVC) component.

- All users hit submit.

- The Controller (MVC) processing this event fetches the Model from
  the session and calls the setter to modify withdraw ammount, passes
  this Model to the Business Deligate to access your transactional layer
  (mediated by a Session bean calling Entities).

- The Model instance is serialized and passed as an argument to the
  layers of business components down to the Entity responsible for
  updating the AccountBalance table row for this account.

- I used BMP and DAO objects to package the SQL logic.  My DAO fetches
  the sequence number from the Model and account new balance from the
  model and builds the SQL prepared statement:

  UPDATE account set balance = ? where column_version_num = ? ;

  I call stment.setString (1, model.getNewBalance());
 stment.setString (2, model.getVersionNumber());

  If I get a SQLException on this update, then I know that someone else
  beat me to the $5.

  The key concept is the WHERE clause will only update the row IFF
  the sequence number has not been changed by someone else (meaning
  I had stale data).


This will work in clustered environments at all times and does not
depend on synchronized business delegate methods or any other design
that is likely to be defeated by appserver servlet or object pooling
or use of multiple VMs to host your application. 

Good luck,

curt






Re: Synchronized session bean?

2001-10-11 Thread El Jeffo

** Okay guys, I've updated this email with a decent example I hope **

 Access to each session bean instance is serialized, but the spec
 doesn't specifically allow you to say there may only be one instance
 of a particular session bean class.  

** so in otherwords, pretty much it achieves the effect I wanted with
little effort... that's kinda nice... and it does this no matter what
isolation/transaction level I request or would you recommend a few 
settings?

 Access to entity beans is also
 serialized and you can be certain that, in a a given app server
 instance (neglecting clustering issues), there's only one instance of a
 particular entity bean class + primary key.  

okay, so if I have two servlets, if I change the value of say foo of
an entity, the other servlet upon say reading the value foo will
see the new value automagically?  Even if I don't do another finder
call?  


 It sounds to me like your
 talking about something much more like an entity.  You can still get
 the guarantee you're looking for if you access the entity through a
 session bean, but the guarantee comes from the properties of the
 entity bean, not the session bean.

Well I thought of using the session bean because I'm kinda trying to
perform an action that has three steps:
1) check balance
2) deduct from account 
3) credit new account

But the problem comes not from making sure there's only one copy, but
the (I think you call it) a race condition.

Say $5 in bank account A, and we want to pay account B $4 and account C
$3.

Servlet 1:
Task: Pay Account B $4 from Account A
Servlet 2: 
Task: Pay Account C $3 from Account A

Servlet 1: 
1) Check account balance
Yup $5 is more than $4
Servlet 2:
1) Check account balance
Yup $5 is more than 3
Servlet 1:
2) Deduct $4 from Acct A
Servlet 2: 
2) Deduct $3 from Account A (must be okay since the check was okay in
step 1)

Servlet 1:
3) Credit Acct B $4
Servlet 2:
3) Credit Acct C $3

End result, balance on Acct A is -$2 even though we checked to make sure
the
entity had the correct balance.  Yes the ending balance is correct too! 
But
the end result is _undesirable_ since we should have prevented Servlet 2
from
completing execution and throw an exception.

So I hope to make the task Synchronized such that Servlet 2 is Blocked
until
Servlet 1's transfer task is complete such that the following is
observed

Servlet 1:
Task: $4 from A to B
Servlet 2:
Task: $3 From A to C
Servlet 1:
Call Session Bean to Xfer funds
stuff happens
1) ... ok
Servlet 2:
Call Session Bean to Xfer Funds
1) ... can't check yet, the Session bean is busy
with session 1's request
-- Blocked --
Servlet 1:
.. more stuff happens...
2) ... deduct
3) ... deposit
-- Finish --
Servlet 2:
-- Unblocked --
1) .. continue... check... too little money
** Throw Exception
-- Finish --

So yes in both cases the Entity reacts as programmed, but it's the
Session Bean I hope to change the behavior of.  Is the desired
behavior the default way of execution or do I have to do something
special?

 Does that help any?
yes it does, and don't get me wrong, I trust what you're saying, but
I just ask a little more to make sure I understand all the little
unsaid details ;)  

Thanks again!

Jeff


smime.p7s
Description: S/MIME Cryptographic Signature


Re: Synchronized session bean?

2001-10-11 Thread El Jeffo

Ah... this is very interesting!  Much thanks, and if you know
of a good book that might address many of these problems with
other alternate solutions, please, do let me know.

Jeff

   UPDATE account set balance = ? where column_version_num = ? ;
 
   I call stment.setString (1, model.getNewBalance());
  stment.setString (2, model.getVersionNumber());
 
   If I get a SQLException on this update, then I know that someone else
   beat me to the $5.
 
   The key concept is the WHERE clause will only update the row IFF
   the sequence number has not been changed by someone else (meaning
   I had stale data).


smime.p7s
Description: S/MIME Cryptographic Signature


Re: Synchronized session bean?

2001-10-10 Thread Gary Shea

El Jeffo ([EMAIL PROTECTED]) wrote:
 Hi everyone...

 I thought there was a way to synchonize a session bean such that
 I suppose you could say that only one user or servlet could
 use it at a time.

 Simply put if there's $5 left in the bank, you wouldn't want to have
 a user withdraw $5 with two different web browsers if they hit
 submit at the same time... so we kinda want it to be like there's
 only one teller window, and the servlets have to wait their
 turn.

 How to do it kinda escapes me, but let me know if there was
 something I missed.  It would be most appreciated.   No need to write
 volumes of code if you know of a good web site reference for example.
 Just sent the URL, I'll do the reading from there.

 Jeff

Access to each session bean instance is serialized, but the spec
doesn't specifically allow you to say there may only be one instance
of a particular session bean class.  Access to entity beans is also
serialized and you can be certain that, in a a given app server
instance (neglecting clustering issues), there's only one instance of a
particular entity bean class + primary key.  It sounds to me like your
talking about something much more like an entity.  You can still get
the guarantee you're looking for if you access the entity through a
session bean, but the guarantee comes from the properties of the
entity bean, not the session bean.

Does that help any?

Gary