Jon Swinth wrote:

>Sorry for the length of this post, but it is a complicated issue.
>
>The application we are working on is a shopping cart that reserves the inventory as
>soon as it is put in the cart.  This is due to the fact that there are scarce 
>quantities of
>items and they come and go (rental business).  In my understanding of beans and JBoss
>I have come upon a conflict that I can't resolve.
>
>I want to support multiple JBoss servers against the same DB.  The conflict arises 
>when
>a new item hits the front page.  There are two kinds of things happening.  First off, 
>because
>of constantly changing values, the inventory of an item is checked before each page 
>view,
>while other data about the item is cached in memory (in Tomcat).  The second is when 
>a user
>adds or removes an item from there cart.  This updates the inventory record.
>
>The main difficulty I have is that for a popular item, there may be multiple people 
>that try to
>add it to their cart at the same time (race to see who gets the limited supply).  As 
>I understand
>it, JBoss will check at the end of a transaction during ejbStore wether the state of 
>the DB record
>has been changed and throws an error if this occurs.  If multiple people are trying 
>to reserve the
>limited inventory then the first guy will have things work fine and anybody else that 
>started their
>transaction before the commit of the first guy will get an error even if there is 
>more inventory available.
>That is, anybody else who's request was sent through a different JBoss server.  
>Requests on the same
>JBoss server would que for a bean lock.  The solution to this problem as near as I 
>can tell is to set
>row-locking true on the bean.  The various JBoss servers would block while waiting 
>for the DB to fetch
>the lock.  After the lock is retrieved, the code checks to make sure there is still 
>available inventory.
>
>However, this brings up another problem for me.  It is OK and quite necessary to have 
>requests
>to add/remove items from the cart to wait for a lock.  When all that is needed is to 
>determine if there
>is inventory currently available, locking is not required and waiting for a lock 
>would be bad.  This is
>especially true when a new product is on the front page.  The two or three people 
>trying to put it in
>their cart would make a hundred front page views wait for a lock.  Now, I can get 
>around this by
>writting a direct SQL query that doesn't impact transactions, but is there a proper 
>EJB way to do this?
>
>I thought of defining the same bean class twice, once with row-locking and once with 
>read-only.  The 
>problem I see is that the changes that the row-locking bean was making would cause 
>exceptions in
>the read-only bean when the transaction finished and JBoss checked to make sure 
>things had not changed.
>Would calling setRollbackOnly just before returning the value from the read-only bean 
>work?  Would a 
>NotSupported transaction attribute on a session bean method allow the cached entity 
>bean to skip the safety
>check?  Is there something else I am not taking into account?
>
>
>-------------------------------------------------------
>Sponsored by:
>ThinkGeek at http://www.ThinkGeek.com/
>_______________________________________________
>JBoss-user mailing list
>[EMAIL PROTECTED]
>https://lists.sourceforge.net/lists/listinfo/jboss-user
>  
>
I think you are over-thinking the problem. All you need to do is have a 
Session Bean method that performs the inventory check, and mark the 
method as Requires Transaction (or Requires New). Then, when you check 
the inventory, reserve a copy at that time. Thus, the check is the 
reserve, and either it works, or it doesn't. If it works, you have the 
copy reserved, and it doesn't, you know that it is not avaiable, and can 
display the appropriate message to the user. The DB locking should 
ensure that multile jBoss servers can't be caught in a race condiction. 
On the db side, you would do something like this:

begin tran

update table, reduce inventory by 1

select info back that you need.

commit transaction.

The update will reduce the eventory, and hold a lock on the page or row 
(depending upon the db setup). Then your select will return the info you 
need to determine if the inventory was still available.

If you are using an Entity Bean, then the ejbLoad should be called when 
the transaction starts. I'm not sure how jBoss does it, but you would 
want to set the isolation level to REPEATABLE_READ, which basically 
locks the db page or row with the select and holds it. In this case, you 
must make sure that the entity is releases quickly, otherwise you are 
holding locks in the database for a long time, which will grind your 
system to a halt.

-- 

Marc Zampetti






-------------------------------------------------------
Sponsored by:
ThinkGeek at http://www.ThinkGeek.com/
_______________________________________________
JBoss-user mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/jboss-user

Reply via email to