Discussions

J2EE patterns: Sequence and CMP

  1. Sequence and CMP (19 messages)



     Regarding using Sequence with CMP I would prefer follow the following way:

    * Create a statless session bean with one remote method which return sequence.nextval.
    * In ejbCreate call the stateless session bean to generate the value required.

    The Implementation of remote method of StateLess Session Bean looks like:

    public long getNextSequence ()throws CannotGetSequenceException{

    long nextseq=0;

    try{

    Connection con = getConnection();
    Statement stmt = con.createStatement();

    ResultSet rs= stmt.executeQuery("select contactstatesequence.nextval from dual");

    if(rs.next())
    nextseq= rs.getLong(1);

    }catch(Exception e){

    System.out.println("Exception :" + e);
    throw new CannotGetSequenceException();

    }

    return nextseq;

      }


    And The create Method of entity bean looks like:

      public void ejbCreate(String interfacename, long regionid, long contactid,
         Date creationdate, Date updateddate,long timestamp){


    this.interfacename=interfacename;
    this.regionid=regionid;
    this.contactid=contactid;
    this.creationdate=creationdate;
    this.updateddate=updateddate;
    this.timestamp=timestamp;

    try{


    InitialContext ic = new InitialContext();
    SequenceHome home = (SequenceHome)ic.lookup("sequence");

    Sequence sequence = home.create();

    contactstateid = sequence.getNextSequence();

    }catch(Exception e){

    System.out.println(e);

    }


      }


    Any suggestions?

     

    Threaded Messages (19)

  2. Sequence and CMP[ Go to top ]

    In general this looks good. However, unless you need your items generated in order, it is probably better to fetch several id's, maybe 100 or so, at one time and buffer them. This way, you only need to make one call to the database per every 100 records you need created. This usually works pretty well, as you only need to insure uniqueness of pk's, and don't care about the order they are written in.

    -Jake
  3. Sequence and CMP[ Go to top ]

    I would rather prefer not to for storing 100 next sequence numbers.I guess there couple of issue:

    * The method which returns next number from 100 need to be made static and which raises other issues.
    * In any reasonable big project there exists more than one table for which sequence number generation is required. I would like to have a common stateless session bean which takes sequence name as input and return nextval of the sequence as o/p. Hence the code for stateless session bean becomes completed if wer go for local Caching.


    -- Mettu.
  4. Sequence and CMP[ Go to top ]

    Make both methods possible. One method for a single ID fetch, and one method for fetching a group of IDs (say 6 for instance because you have 6 OrderDetails that need Object IDs).
  5. static methods and caching[ Go to top ]

    I would rather prefer not to for storing 100 next sequence numbers.I guess there couple of issue:

    >
    > * The method which returns next number from 100 need to be made static and which raises other issues.

    The method which returns next number from 100 need to be made static and which raises other issues...

    -->>
    What are the issues with static methods.. can u please explain this..
    I was thinking to store all fetched values as static vector field in some class and use some static method to return values in this vector..

    Eg. static Vector someTableSequences;

    static long getNextVal(String tableName)
    {
          // if tablename equals someTable
          // begin - if someTableSequences is not empty
          // get value at index 0
          // remove value at index 0
          // return value fetched
          // Else
          // fetch 100 values from sequence table and store
          // them in vector someTableSequences
          // return value at index 0 now
    }

    Is there anything wrong in this ??



      
    > -- Mettu.
  6. Sequence and CMP[ Go to top ]

    Make your design a two level approach:

    * OneValueSessionBean
    * CachedValueSessionBean

    Several CachedValueSessionBeans get a basic ID
    from the OneValueSessionBean which generates one
    ID (from the DBMS like your example) at a time.
    For example OneValueSessionBean
    supplies 1,2,3,4,....
    The CachedValueSessionBeans will now get one ID
    e.g. 3 and then generate ID on its own 301,302,303,304,...
    for all Beans who needs unique IDs. When reaching
    399 it will get a new ID from OneValueSessionBean.
    (another CachedValueSessionBean will generate 501,502,...,599).

    (Real world values could be 24bit for the OneVSB counter and
    8bit for the CachedVSB counters).

    This saves lots of accesses to the DBMS and the CachedValueSessionBeans are no longer a bottleneck because they can generate IDs at the same time and OneVSB will
    only be asked when the CacheVSB runs out of IDs)

    -stephan
  7. Sequence and CMP[ Go to top ]

    All these Caching xTechniques has a problem. When the server crashes the Primary which is generated from sequence shows a disorder.

    For Ex:

     I want to Cache 100 numbers. After using 50 numbers server crashes next sequence numbers will be 101, 102 .... instead of 51, 52...

      This gives a puzzle to DB Admin !!!!!

    Regards,
    Mettu.
  8. Sequence and CMP[ Go to top ]

    Normally the only thing you want to get from
    IDs is that they are unique. It doesn't matter
    whether your server crashes or not.
    1. If you delete Objects, there will be missing
    some numbers in your database
    2. Real World Numbers (if you have lots of objects)
    are more like A12D78413CD29F rather than 501,502,...
    So you can't count them and you don't realize that
    there are numbers missing.

    All you want is that the ObjectID is unique.

    -stephan
  9. Sequence and CMP[ Go to top ]

    You'll get the same holes in the primary key if the database server crashes. You need to work out if you can have holes or not, but life is much simpler if you can tolerate the occasional hole in the sequence.
  10. Sequence and CMP[ Go to top ]

    Since the sequence generation is controlled by a session bean, why can't we avoid using database sequence and use cashed numbers to generate the sequences? The session bean, during it's creation time can read the last ids from each of the tables for which we want to generate sequences and put them in a hashtable as <table_id, last_sequence> pair. The remote method getNextSequence(tableIdentifier) can fetch the sequence number from the hashtable for that particular table, increment that number and return it. This way, the accessing of the database can be limitted only to the bean creation time.
  11. Sequence and CMP[ Go to top ]

    You cannot count on all databases supporting DUAL (select counter from dual); or having any other type of sequences.

    To me it would be better to create entity bean(s) for generated IDs mapped to a table in the database. You do not have to worry about caching it, the EJB server will do that for you. True you built in a dependency but it this solution is truly portable.
  12. Sequence and CMP[ Go to top ]

    I would not recommend using an entity bean to manage primary key values. This seems to go against the basic design of an entity, an object that models business data and logic for a logical entity in your system.

    A primary key is not really "business data" and generation of a unique identifier is not part of "business logic". It is really support for that data and logic.

    I that that the right solution for this would be a stateles session bean that can access the values of sequences.

    It is true that you can not count on all database supporting
    a DUAL table. To solve this problem and avoid other database dependant sequence access problems I would suggest putting RDBMS specific code into a DAO (data access object), then loading the specific DAO at runtime based on environment properties for the session bean.

    This is basically what I did for my SequenceManager. SequenceManager is a stateless session bean with two methods:

     public long getCurrentValue(String seqName)
     public long getNextValue(String seqName)

    I do not currently cache sequence values, but that is planned to support a more scalable solution in the future.

    Calls to either of the above create an instance of a SequenceDA0, which is an interface with the following methods:

     public void setName(String seqName)
     public String getName()
     public long getCurrentValue(Connection con)
     public long getNextValue(Connection con)

    When the object is created (currently I do this by reading an enviroment property to get the class name of the DAO), I assign the sequence name via setName(), then call the corresponding get*Value() with a connection gotten from a javax.sql.DataSource.

    To furthur make life easier for me I also created an SequencedEntityBean, which is an abstract class implementing
    javax.ejb.EntityBean that contains a generatePrimaryKey() method, which takes care of all of the details of generating the primary key object for the entity.

    Note that it is probably not needed to have access to the current value of a seqence, but I thought that I would drop that in to make the SequenceManager manager a bit more about sequences than just their next values.

    --jason
  13. Sequence and CMP[ Go to top ]

    Hi Jason,

    I'm interested in your pattern. Do you provide one SequenceDAO per Entity Bean that needs a sequence number as primary key (or as part of the primary key)? If so, why do you need a SequenceManager - the entity bean is explicitly tied to its SequenceDAO.

    Why is your SequencedEntityBean an entity bean?

    Also, there has been much talk of caching sequences in session beans - the concept of caching data seems to go against the purpose of session beans, especially stateless ones.


    Regards,

    Don

  14. Sequence and CMP[ Go to top ]

    Suggestion: Don't waste your time with this, there are "ready to use" products which do a good job and are fully tested.
    You can take a look at X-Steps' UIDGenerator (an evaluation version is also available) which easily generates lots of IDs very fast and thus scales very well.
    http://www.xsteps.com/english/products/ejbs/uidGenerator.shtml, an evaluation version is also available there

    Greetings

    Messi
  15. Sequence and CMP[ Go to top ]

    There is only one SequenceDAO for each RDBMS, such as OracleSDAO or PostgresSDAO. This just provides an abstract of the sequence (getCurrentValue(), getNextValue()) so that it can be plugged in to the SequenceManager.

    The current design only allows for one SequenceDAO to be configured per SequenceManager, thus only one type of RDBMS sequence is supported.

    SequencedEntityBean is an abstract class which provides a getPrimaryKey() method that can be called in postCreate() to get the PK for the bean. It also provides the basic support for the rest of the Entity bean contract (EntityContext and such).

    As for caching of sequence values, unless you want to ensure that each entity has a contiguous id, you can efficently cache 100 or so values and hand them out as requested. This will speed things up as you will not have to hit the DB every time you create an entity, just every 100.
  16. Sequence and CMP[ Go to top ]

    How would you actually cache those IDs? A statless session bean could have a Vector reference, which will be shared among all accesses (if the Session Bean is able to be used concurrent). But I am not sure if that is actually allowed by the specification.

    Personally I prefer true UUIDs. Those are statless generatable and can be more meaningfull even after dump/restore.
  17. Sequence and CMP[ Go to top ]

    Anyone know how to use sequences in DB2?
  18. Sequence and CMP[ Go to top ]

    I have used sequences for CMP and want to make some comments:

    1 Why use session beans as generators? Use a simple utility method that takes the sequence name as parameter and returns the new unique id. Call the method from within the ejbCreate method. This will make the utility method reusable for all entity CMP beans.

    2 You may have the sequence name configurable. That means mapped in the .xml deployment files.

    3 For performance reasons you may have to cache id's with one cache per sequence.
  19. Sequence and CMP[ Go to top ]

    I'am using an Oracle DB and want to generate primarky keys from sequences.
    My idea was to get the sequence on the ejbCreate(int arg) method of the CMP, or to call a simple method within the ejbCreate method that returns the unique id.
    The problem I have is that I do not know how to get a connection object from the container, do fetch the new sequence.
    Do you have any example for documentation for that issue.
  20. Same problem[ Go to top ]

    I have the same problem now. Do you know how to solve it?

    Cheers,
    George

    > I'am using an Oracle DB and want to generate primarky keys from sequences.
    > My idea was to get the sequence on the ejbCreate(int arg) method of the CMP, or to call a simple method within the ejbCreate method that returns the unique id.
    > The problem I have is that I do not know how to get a connection object from the container, do fetch the new sequence.
    > Do you have any example for documentation for that issue.
    >