To simplify the problem let's assume we are using BMP.

If you obtain a lock in ejbLoad it will apply to every method invocation that is 
transaction required.  So all
method invocations will block others.  Seems to me that does not provide a practical 
granularity.

I think your answer seems to validate my remarks.  The simple requirements are not 
easily met in EJB!



Assaf Arkin wrote:

> [EMAIL PROTECTED] wrote:
> >
> > I understand that ejbLoad will occur but Oracle will doesn't lock the row
> > when reading.  Also are you saying that the container obtains a read lock
> > in an ejbLoad?  How does it do that?
>
> Container only obtains a lock in CMP, in BMP you have to do it youself.
>
> In CMP that would happen through SELECT ... FOR UPDATE (Oracle) or
> SELECT ... HOLDLOCK or SERIALIZABLE (Sybase). You can do the same in BMP
> if you need to synchronize access.
>
> Alternatively, you might want to open up a cursor in BMP with ejbLoad
> and use it for ejbStore. (Not that I would recommend that with the
> current state of EJB containers and JDBC drivers :-) )
>
> The guidelines for BMP would be:
>
> * If only one entity can access the data at a given time then:
>
>    ejbLoad must do a FOR UPDATE (or anything equivalent)
>
>    The server guarantees to do ejbLoad at least once in the transaction
> and ejbStore when the transaction commits (not before)
>
> * Or, if the server is smarter, you might declare the entity bean as
> exclusive access and the EJB server will serialize method calls across
> transactions
>
> * If you want two entity beans to access the data at a given time, then:
>
>     Your business methods must do UPDATE, not count on the information
> you loaded in ejbLoad
>
>     Or, your ejbStore must do the UPDATE smartly
>
> * One possibility is to have:
>
>     int getBalance() but not setBalance()
>
>     have a field called increment which is not persistence, so
> setIncrement() getIncremenet()
>
>     in ejbStore you would do an UPDATE balance += incremenet;
>
> arkin
>
> >
> > dan
> >
> >
> >                     Assaf Arkin
> >                     <arkin@exoffic        To:     dan benanav 
><[EMAIL PROTECTED]>
> >                     e.com>                cc:     [EMAIL PROTECTED], 
>[EMAIL PROTECTED]
> >                     Sent by:              Subject:     Re: [EJB-INT] This should 
>be easy an obvious, but it's
> >                     [EMAIL PROTECTED]        not.
> >                     office.com
> >
> >
> >                     02/09/00 03:15
> >                     PM
> >
> >
> >
> > > I dont think that is correct.  Oracle provides for row level
> > > locking.   There is no update in ejbLoad so no locking occurs.
> > > Locking only occurs when you update a row.  See the following from the
> > > Oracle site:
> >
> > You do need ejbLoad to occur. If it doesn't then someone else might
> > update the database from outside the server, and your problem will not
> > be just two beans racing to get the update first. So by definition, you
> > need to synchronize first, which means an ejbLoad, which means you get a
> > read lock on the row, which means serializable access.
> >
> > Excatly how you get that done is up to the EJB container.
> >
> > >
> > > Row-Level Locking
> >
> > <snip>
> > I know, I wrote code like that for the CMP engine.
> > </snip>
> >
> > arkin
> >
> > > >
> > > >
> > > > But, if you opened a connection from a session bean with read
> > > > committed,
> > > > then ran the entity bean from it, you're still in read committed, so
> > > > the
> > > > serializable doesn't work for you.
> > > >
> > > > This is where the EJB server should allow you to mark the entity
> > > > bean as
> > > > exclusive access and maintain a lock, blocking B until A finishes
> > > > the
> > > > transaction. I'm working on code that does just that right now, and
> > > > it's
> > > > not that hard.
> > > >
> > > > Once again, lock contention.
> > > >
> > > > If you're looking for performance (and scalability and everything
> > > > else)
> > > > you should consider either:
> > > >
> > > > 1. Doing no 2) (in UPDATE from the entity bean), or
> > > >
> > > > 2. Using a stateless session bean (my favorite)
> > > >
> > > > You must always assume the EJB entity bean mantra of
> > > > load-modify-commit,
> > > > which either gets you into trouble if you don't pay attention to
> > > > locking, or slows down your application if you do too much locking.
> > > >
> > > > arkin
> > > >
> > > > dan benanav wrote:
> > > > >
> > > > > I have a question about how to implement something using EJB.  I
> > > > am sure
> > > > > that this problem is very common and that it has come up in
> > > > discussions
> > > > > in various forms on this list, but I don't think the right
> > > > approach has
> > > > > been clarified.  This is surprising since the spec should be able
> > > > to
> > > > > handle such a situation rather easily.  It appears to me that many
> > > >
> > > > > people have a misunderstanding about EJB that leads to an
> > > > incorrect way
> > > > > to solve this problem.  Including in that misunderstanding is the
> > > > Sun
> > > > > BluePrints guide.  In the following I will assume we are talking
> > > > EJB 1.1
> > > > > spec and I am interested in a solution that conforms to that spec.
> > > >
> > > > >
> > > > > Problem:  Suppose you have an Account class that is the remote
> > > > interface
> > > > > to an Account bean.  AccountBean is the entity bean implementation
> > > >
> > > > > class.  You want to write a method increment(int x) that adds x to
> > > > the
> > > > > balance on the account represented by the Account instance.  There
> > > > are 2
> > > > > approaches that come to mind about how to do this.  The first is
> > > > the
> > > > > most obvious but I believe there are problems with it.
> > > > >
> > > > > 1)  public void increment(int x) {balance += x;};
> > > > >
> > > > > 2) public void increment(int x) { //use jdbc to increment the
> > > > balance in
> > > > > the db using sql like "updateaccount_table set balance = balance +
> > > > ?
> > > > > where account_key = ?".  The first question mark is set to x and
> > > > the
> > > > > second question mark is set to the primary key of the bean.}
> > > > >
> > > > > Why isn't 1) good?  Containers are free to use multiple bean
> > > > instances
> > > > > to handle concurrent calls to an entity object as long as those
> > > > calls
> > > > > are occurring under a different transaction.  This means that you
> > > > can
> > > > > have bean instance A and bean instance B both handling calls to
> > > > > increment x, where both A and B represent the same entity object
> > > > (same
> > > > > primary key).  Some containers my choose not to do this, however
> > > > there
> > > > > is no guarantee that the container provider won't change their
> > > > approach
> > > > > in the future.  Furthermore if you rely on the container not doing
> > > > that
> > > > > your code will not work on any EJB server.  This would make it
> > > > difficult
> > > > > for EJB bean providers (like the Theory Center) for providing
> > > > server or
> > > > > container independent beans.  So if you agree now that your code
> > > > should
> > > > > work if the Container provider uses multiple bean instances then I
> > > > think
> > > > > there is a problem.   Suppose that in two separate threads calls
> > > > are
> > > > > made to an entity object.  One thread calls increment(1) and the
> > > > other
> > > > > increment(2).  These calls occur concurrently.  Assume also that
> > > > the
> > > > > initial balance before the calls is 3.  After the call the new
> > > > balance
> > > > > should be 6.  Here is what can occur:
> > > > >
> > > > > T1:Container calls ejbLoad on Bean A: Balance gets set to 3.
> > > > > T2:Container calls ejbLoad on Bean B: Balance still is 3.
> > > > (This
> > > > > happens in a separate thread and  separate transaction context).
> > > > > T3:Container calls increment(1) on Bean A: Balance gets set to 4
> > > > in Bean
> > > > > A.
> > > > > T4:Container calls increment(2) on Bean B: Balance gets set to 5
> > > > in Bean
> > > > > B.
> > > > > T5:Container calls ejbStore on Bean A: balance in database is
> > > > updates to
> > > > > 4.
> > > > > T6:Container calls ejbStore on Bean B:  what happens??
> > > > >
> > > > > What happens may depend on what the Transaction isolation level is
> > > > and
> > > > > perhaps on the underlying database.  If you use Oracle and the
> > > > default
> > > > > transaction isolation level (read committed) then the balance gets
> > > > set
> > > > > to 5 in the database. (The wrong answer!).  If you use
> > > > serializable
> > > > > transaction isolation level then an exception is thrown and the
> > > > client
> > > > > will have to react appropriately to the exception.  So it would
> > > > appear
> > > > > that the only way 1) could possibly work (in some sense)  is to
> > > > use
> > > > > transaction level serializable.   So 1) with transaction
> > > > serializable is
> > > > > an approach but it is incompletely specified since we haven't said
> > > > how
> > > > > the client should handle this.  I imagine there are ways to handle
> > > > it.
> > > > > (Catch the exception and try again for example).   Furthermore I
> > > > have
> > > > > been told by WLS not to use transaction serializable due to a bug
> > > > in
> > > > > Oracle so 1) does not currently work for Oracle.   Even if this
> > > > would
> > > > > work it seems like it would be better to just force the container
> > > > or to
> > > > > specify in the deployment descriptor that calls to increment
> > > > should be
> > > > > serialized.  Currently there is no way to do that in the spec.
> > > > >
> > > > > The second solution would work however there are also problems
> > > > with it.
> > > > > You need to be careful to make sure that when ejbStore is called
> > > > the
> > > > > correct value is stored in the database.  For example, you cannot
> > > > just
> > > > > increment the value in the db. You would also need to set balance
> > > > in the
> > > > > bean appropriately.
> > > > >
> > > > >
> > > > > dan
> > > > >
> > > > >
> > > >
> > ===========================================================================
> > > >
> > > > > To unsubscribe, send email to [EMAIL PROTECTED] and include in
> > > > the body
> > > > > of the message "signoff EJB-INTEREST".  For general help, send
> > > > email to
> > > > > [EMAIL PROTECTED] and include in the body of the message
> > > > "help".
> > > >
> > > > --
> > > > --
> > > > -------------------------------------------------------------------
> > > > Assaf Arkin
> > > > www.exoffice.com
> > > > CTO, Exoffice Technologies, Inc.
> > > > www.exolab.org
> >
> > --
> > ----------------------------------------------------------------------
> > Assaf Arkin                                           www.exoffice.com
> > CTO, Exoffice Technologies, Inc.                        www.exolab.org
>
> --
> ----------------------------------------------------------------------
> Assaf Arkin                                           www.exoffice.com
> CTO, Exoffice Technologies, Inc.                        www.exolab.org

===========================================================================
To unsubscribe, send email to [EMAIL PROTECTED] and include in the body
of the message "signoff EJB-INTEREST".  For general help, send email to
[EMAIL PROTECTED] and include in the body of the message "help".

Reply via email to