Optimistic Locking pattern for EJBs

Home

News: Optimistic Locking pattern for EJBs

  1. Optimistic Locking pattern for EJBs (14 messages)

    Yasmin Akbar-Husain and Eoin Lane show how to construct an optimistic locking solution that produces transactionally safe EJB code, portable across all application servers. The authors implement the solution in a versioned entity bean for fail-safe concurrent updates. The Optimistic Locking pattern encourages short commit cycles, thus increasing throughput and improving performance.

    The pattern is at:
    http://www.javaworld.com/javaworld/jw-07-2001/jw-0713-optimism.html.

    What do you guys think of this pattern?
  2. I think it looks suspiciously like a pattern that was posted by Doug Bateman here on TheServerSide, way back in October 27, 2000:

    Long-Lived Optimistic PseudoTransactions (Version Numbering).

  3. Optimistic Locking pattern for EJBs[ Go to top ]

    Timestamps, Version count, and State comparison describe in the article is inadequate in in a cluster environment. To adequately handle optimistic locking you need a database solution combine with Version count. Specifically, you need a version field in the database table and basically follow the instruction in the article. ATG's Repository implement this pattern perfectly with their version property.
  4. Optimistic Locking pattern for EJBs[ Go to top ]

    [Quote]
    Timestamps, Version count, and State comparison describe in the article is inadequate in in a cluster environment.
    [end quote]

    Hi

    Would you be willing to touch on this a bit more. I'm not quite clear why you feel it's inadequete in a cluster environment. Do you feel it's just not a reliable enoguh solutions or that it 'plain doesn't work'?

    Thanks.
  5. Optimistic Locking pattern for EJBs[ Go to top ]

    Basically, If you attempt to update the item from a transaction whose version does not match the current version number in the bean, an Exception is thrown to abort that update. In the clustered environment, you have multiple servers and each server will have it own bean and version number. Therefore, how do you know that you've the latest data? With the version field in the database table, you should be able to tell this if you've the same version number.
  6. Optimistic Locking pattern for EJBs[ Go to top ]

    I am not sure that this is true. Every instance of application server in the cluster is supposed to sync its bean's state at transaction boundaries. Therefore if transactions are handled correctly then the solution shall work in cluster just fine.
  7. Optimistic Locking pattern for EJBs[ Go to top ]

    Hi

    To me this is always a great topic to dicsuss as technologies change while trying to solve this in the present day "web environment".

    [I've left out comments on state comparison as I feel that as much as it's a 'solution', the memory overhead of comparing 'original' objects to 'new' objects doesn't usually make it past the 'brainstorming' phase of our projects.]

    My problem with it (the solution of versioning and timestamping) are as follows. It seems you really only need to implement a locking pattern when using BMP. I"ve noticed that some/most people pick BMP over CMP because of the performance drawbacks to CMP and the tough time involved in mapping complex relationships.

    How much performace gain are you getting if you forgo CMP for BMP and a custom Optimistic locking pattern? Add this to the situation where you have a complex heavy weight object that has multiple levels of object isolation. (ObjectA has ObjectB which has ObjectC etc etc). If each Object maps nicely to a row in a database you've pretty much almost home free, but if it doesn't, the additional checks and balances to take into consideration all the timestamping, versioning etc can be hell in a a handbasket.

    After all that work you've just put in to handle all this locking, aren't you pretty much just recreating what the application server was meant to do anyway?

    My other problem is that being relatively new to EJB's and the inherited problems with state data and it's staleness is that I haven't found a clear cut solution to yet.

    I am still searching, and continue to await comments to topics such as this.

  8. Hi,

    Another writer has pointed out that this solution wouldn't work in a clustered environment where each app server is handing out its own version numbers. (Unless you create a networked RMI Singleton to issue version numbers, but that might have worse performance than pessimistic locking)

    But this problem wont go away with CMP. This isn't a BMP/CMP issue.

    It's a problem with the Value Object pattern.
    Sending a copy of data out to a client which can become stale if another client makes an update first. Version checking would have to be made in the setValueObject() method regardless of the persistence mechanism.
  9. This article shows a technique very similar to one showed on the patterns section a long while ago. I have commented there that this pattern won't work even in a single server environment unless the container uses commit option A exclusively. Otherwise multiple instances representing the same entity would lead to corruption.
    If for any reason this has become incorrect in EJB2.0 (which I doubt), could you please post here?

    Gal
  10. I have not read the article on the JavaWorld website but based on the summary provided above this is not a new pattern and has been used in other distributed and client/server architectures/solutions.

    In fact I used state and versioning solutions in an EJB 1.1 project at AT&T in 1999, yes 1999, with CMP entity beans. This project was probably one of the first to use CMP entity beans on a major J2EE project. The project is documented in the J2EE in Pratice book which can be read online at:

    http://java.sun.com/j2ee/inpractice/pdf/att.pdf

    It should be noted that this pattern works across transactions but still requires similar support within a transaction if optimistic concurrency at the database is in use. So yes in a clustered environment or where another process updates the database between the read and update in the final transaction this pattern DOES NOT WORK.

    The AT&T project did not suffer from this failing since support for optimistic concurrency was built into the Borland cmp engine. I believe the only other appserver supporting this is Sybase EAServer, which has just come out with it.

    William Louth
  11. There are a number of points worth making here:

    a) William is correct in that the pattern will not work for CMP unless the CMP engine supports optimistic locking and yes, Sybase EA Server does support this.

    b) The check for version changes has to be at the point that the row is about to be updated on the database. This is because it is possible that an update could occur between the reading of the row and the update of the row. Clustered environments are an obvious case here. The simplest way to avoid this problem is to perform an ""Update EntityBeanTable e .... Where e.id ="myPrimaryKey" and e.version=4" (to quote Doug Bateman's article of Sept 2000). The update will fail if the version has changed. The only downside to this is if the row is not found we don't know if it is because the row has been deleted by another process or whether the version is different. The other alternative which would fix this last problem is to perform a 'SELECT..FOR UPDATE' which would allow you to check the version prior to performing the update without losing the (intent to be update/exclusive)lock but this is another SQL statement across the wire. Furthermore we could just send back a message 'instance/row state has changed' message back to the caller in the first case and let them sort out the reason it failed.

    Oh yeah, the version number must be updated to 1 more than what it is currently..none of this keeping a version count per server (which is obviously flawed).

    So in the case of CMP, the CMP engine has to support optimistic locking. For BMP, you have have do the check and lock the row AT THE SAME TIME.
  12. Optimistic Locking pattern for EJBs[ Go to top ]

    I'm curious, with the introduction of local interfaces, co-located clients and EJB can accessed by using pass-by-reference, then why do we still need value-object?
  13. Why the need for value-objects? Two reasons pop to mind.

    1. From a design perspective, it is good practice for clients to access the system through a Session Bean layer that abstracts the business logic/rules/workflow and Data Layer (Entity Beans, or some other persistence mechanism). In this case, the Session Bean would return value objects rather than handles to the persistence layer (Entity Beans).

    2. Because Entity Beans have been architected for poor performance. To me, this is the show stopper that leads me to avoid using Entity Beans.

    eg. For each of 100 customers you wish to update 10 attributes.

    What is the rough cost of doing this?

    ** Case #1: Entity Bean impl.

    - 100 remote calls for home lookup.
    - 100 database queries for home lookup (primary key).
    - for each Customer Entity Bean.
       - for each of 10 attributes,
          - 1 remote call to set the attribute.
          - 1 or more database queries to load the Entity Bean.
          - 1 or more database updates to store the Entity Bean.

    Lets total that up,
    total remote calls == 100 + (100*10) == 1100
    total database transactions ~= 100 + (100*10*2) >= 2100


    ** Case #2: Value Object through a Session Bean Facade. To simplify the case I will omit the Entity Bean.

    - one remote call to send the Session Bean an array of 100 Customer value objects.
    - for each Customer value object,
       - 1 database transaction to update the Customer data.

    total remote calls == 1
    total database transactions ~= 100

    Case #2 could be further optimized by doing the updates in batch, or using a stored procedure.

    Case #1 could also be partially optimized by using local interfaces, smart containers, etc. It would be interesting to try and speculate what the theoretical minimum cost of case #1 is, but I suspect it could never approach the performance, and simplicity, of case #2.

  14. I've a One-to-many bidirectional relationships between the PERSON and PHONE tables could be manifested in a relational database in a variety of ways. For this example, we chose to have the PHONE table include a foreign key to the PERSON table. My question is should I included the Person field, which is cmr field, in my value object (keep in mind that these are local interface entity bean)

    CREATE TABLE PHONE
    (
     PHONE_ID INT PRIMARY KEY,
     NUMBER CHAR(20),
     TYPE INT,
     PERSON_ID INT
    }


    // The local interface for the Phone EJB
    public interface PhoneLocal extends javax.ejb.EJBLocalObject {
       public void setPhoneId(Long phoneId);
       public Long getPhoneId();
       public String getNumber();
       public void setNumber(String number);
       public byte getType();
       public void setType(byte type);
       public PersonLocal getPerson();
       public void setPerson(PersonLocal person);
    }

    // The bean class for the Phone EJB
    public class PhoneBean implements javax.ejb.EntityBean {

       public Integer ejbCreate(LongId, String number, byte type, PersonLocal
    person){
            setPhoneId(id);
             setNumber(number);
             setType(type);
       }
       public void ejbPostCreate(LongId, String number,byte type, PersonLocal
    person) {
            setPerson(person);
       }

       // persistent fields
       public abstract void setPhoneId(Long phoneId);
       public abstract Long getPhoneId();
       public abstract String getNumber();
       public abstract void setNumber(String number);
       public abstract byte getType();
       public abstract void setType(byte type);
       public abstract PersonLocal getPerson();
       public abstract void setPerson(PersonLocal person);

       // standard callback methods
       .
    }


    Should I include a person, which is cmr field the value object for the Phone
    EJB?

    public class PhoneValue implements java.io.Serializable {

        private Long _phoneId;
        private String _number;
        private String _type;

        public PhoneValue() {
        }

        public void setPhoneId(Long phoneId){
            _phoneId = phoneId;
        }

        public Long getPhoneId(){
            return _phoneId;
        }

        public void setNumber(String number){
            _number = number;
        }

        public String getNumber(){
            return _number;
        }

        public void setType(String type){
            _type = type;
        }

        public String getType(){
            return _type;
        }
    }

  15. Hello,
    I'd like to make a summary of many message posted about this pattern to make clear things for myself and for others.

    1) If you choose to implement your beans as BMP then you can achieve data-consistency with some patterns like timestamp or versioning pattern, checking the timestamp after reading and just before updating (as an alternative using an UPDATE ... set field A = ... WHERE timestamp = ..)

    2) If you choose to implement your beans as CMP then the Container will care for proper locking of data

    3) I don't understand well the question with the cluster environment: if I read a timestamp that is persistent on the DB -and check it to see if the data has been altered- what is the difference if the environment is clustered or not?

    Hope to receive some answers
    Thanks
    Francesco