Re: Synchronized "session bean"?
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"?
** 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"?
> > 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"?
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