Discussions

EJB programming & troubleshooting: Transactions: Aaarrghhh!

  1. Transactions: Aaarrghhh! (6 messages)

    After writing an entire chapter in "Mastering EJB II" about transactions, specifically, about transaction isolation levels, the author lightly notes "Unfortunately, there is no way to specify isolation for container-managed transactional beans...".

    That, to me, is the same as saying: "forget about this whole CMP deal, in reality it is unusable!".

    The author offers two solutions:

    1. Use resource manager APIs (such as JDBC)
    2. Rely on your container's tools or database's tools

    What does solution 1 mean? Is he saying: "don't use CMP, use BMP"? That's not a solution, that's an entirely different approach!

    And solution 2 is counting on features outside of the Enterprise JAVA framework, read: non-standard features. What good are they!? It means your application will run on EJB container brand X with database brand Y, instead of ANY EJB container and ANY database (which is, simply put, what JAVA is all about, choice). If you're FORCED to focus on one app server and one database brand, you might as well go to Microsoft .NET route!

    Threaded Messages (6)

  2. Transactions: Aaarrghhh![ Go to top ]

    I've never figured out why EJB 1.1 undid declarative isolation levels. The only aspect I can see is mixing isolation levels across beans in the same tx causes uglyness, so they wanted to prevent that. However, doing it in code doesnt totally solve that scenario.

    In any case, you and the author are correct, you cannot control the isolation level used in a CMP bean, but thats not all bad. Realize the entire CMP model is that you dont care about the persistance of that data. Rather what you care about is that the data is indeed persisted. What this has lead to is that CMP vendors are free to do alot of cute trickery to tune their CMP engines for a component based programming model. Switching the isolation levels around would put a serious hamper on the CMP vendors ability to innovate their trickey.

    Honestly, alot could be argued in pure client/server RDBMS systems you should avoid mucking around with isolation levels, and simply redesign you system to work within a single isolation level which provides the least concurrent overhead while still protecting the integrity of your data. Thats why most RDBMS systems default to level 1.

    Do you have a specific problem you need to overcome? I saw your thread on PK values, and using that as an example I can show you a very powerful way to do what you want, without ever needing to muck with isolation levels.

    Dave Wolf
    The Scupper Group
    dave at scuppergroup dot com
  3. Transactions: Aaarrghhh![ Go to top ]

    Do you have a specific problem you need to overcome?

    > I saw your thread on PK values, and using that as an
    > example I can show you a very powerful way to do what
    > you want, without ever needing to muck with isolation
    > levels.

    Yes, indeed, that is currently my main concern, finding a way to get the next sequential ID (e.g. getNextID() first returns 1, then 2, then 3, etc.).

    Both books I've read "cheat" by always using String ID's.
  4. Transactions: Aaarrghhh![ Go to top ]

    You can do this very simply, safely, and portably using a stateless session bean and a single table with a single row.

    create table KEYGENERATOR
    (
    seed int not null
    );
    insert into KEYGENERATOR select 1;

    The stateless session bean marked a transaction required and using an isolation level of at least 1 has psuedo code like

    // assuming an instance member called _current and
    // and environment variable storing a _blocksize

    if(_current == null)
    {
        update key generator set seed = seed + _blocksize
        select seed from key generator
        _current = seed - _blocksize
        return _current;
    }
    else // assuming not our first time being called
    {
       if(current % _blocksize == 0) // need a new seed
       {
         update keygenerator set seed = seed + _blocksize
         select seed from key generator
         _current = seed - _blocksize
       }
       else
       {
         return _current
       }
    }

    Advantages

    1) Portable
    2) Needs only one table with one row
    3) Guranteed unique to all cluster members sharing a database
    4) Small bit size number easier to index
    5) By basically grabbing "blocks" of ids from the key gernator table we only ping the database when we need a new block. This is tuned by setting the block size. There is then almost no contention on the table

    Simple, easy, handles 95% of the things you need to do.

    Would something like this work?

    Dave Wolf
    The Scupper Group
    dave at scuppergroup dot com

  5. Transactions: Aaarrghhh![ Go to top ]

    My current attempt:

    1. A stateless session bean KeyGenBean with a method:

        public int getNextKey(String keyname) { ... }

    2. This method reads an environment entry KeyGen/database.

    3. Depending on the value of this entry, a database specific algorithm is called, e.g.:

        public int getNextKey_PostgreSQL(String keyname)
        { // use PostgreSQL sequences }

        public int getNextKey_MSSQL(String keyname)
        { // use stored procedure }

    4. The getNextKey method has transaction type Required.

    However, I have NO idea if this will work, e.g. will this approach guarantee UNIQUE, SEQUENTIAL keys (gaps are no problem)? My current understanding is that with EJB's, any EJB container will guarantee to sequence/synchronize calls to the getNextKey method, so things should work out just fine.
  6. Transactions: Aaarrghhh![ Go to top ]

    The system I describe above will give you what you want.

    Dave Wolf
    The Scupper Group
    dave at scuppergroup dot com
  7. Transactions: Aaarrghhh![ Go to top ]

    Hi,

    Open Symphony also implement a bean in the oscore product.
    Have used it and work well.

    Owen