There is a good design pattern for this standard problem. It has been
published by Jonathan K. Weedon in the inprise.public.appserver newsgroup
2000-05-30 and I successfully adopted it for Jonas.
However there is a big problem with using it in Jonas, because for
performance reasons it depends on reuse of pooled stateless session beans, a
feature that is currently not supported by Jonas (as they told me it will be
supported in the next release - end of September 2000).
I have added the original posting as a binary attachment. Works great (if
you have reusable session beans), otherwise its inefficient, as it creates a
new session bean and updates one entity bean for every newKey() operation.
But it's thread-safe and completely independent of the database product. So
I would recommend adapting it and wait for September :-)

If you obtain a sequence from Oracle (or use any other db-specific key
generation facility), you have to make one additional query or update on the
database, which can be some performance drain if you create many beans at
once.

Best regards

Nikolaus Rumm


----- Original Message -----
From: "Phil Windley" <[EMAIL PROTECTED]>
To: <[EMAIL PROTECTED]>
Cc: <[EMAIL PROTECTED]>
Sent: Tuesday, June 27, 2000 1:34 AM
Subject: Re: Automatic counter


>
> Its faster to write, to be sure, but seems like its going to establish a
> new connection for every creation event.  If those events are a small
> percentage of overall operations, it wouldn't be a problem, but I'm
> envisioning a system that has large numbers of creations, so this would be
> pretty expensive.
>
> Anyone else have ideas on getting a serial type (preferably from
> Postgresql) to work with in CMP to automatically create the PK for the
> bean?
>
> --phil--
>
> On Fri, 23 Jun 2000 11:16:16 -0600 [EMAIL PROTECTED] writes
> +--------------------
> | I couldn't get the serial type to work with CMP either.  We added a
function
> like the following in each of our entity beans to use automatically
generated i
> d's from postgres (mytable_id_seq is a SEQUENCE):
> |
> | private Integer _getNewID()
> | throws SQLException
> | {
> | Connection conn=_dsource_.getConnection();
> | String sql="select nextval('mytable_id_seq')";
> | Statement stmt=conn.createStatement();
> | ResultSet rs=stmt.executeQuery(sql);
> | if(!rs.next())
> | throw new SQLException("Unable to get next sequence.");
> | Integer newid=new Integer(rs.getInt(1));
> | stmt.close();
> | conn.close();
> | return newid;
> | }
> |
> | I know this isn't an ideal solution, but it is faster than two beans..
> |
> | -Erik
> |
> |
> | At 09:55 AM 6/23/00 -0600, you wrote:
> | >
> | >I use Postgresql as well, but I couldn't figure out how to get
container
> | >managed entity beans to automatically set the primary key from the
SEQUENCE
> | >data type.  I ended up creating a session bean to grab sequence numbers
> | >from the database each time I created an entity bean.
> | >
> | >Is there a better way?  I'm all for it---creating two beans every time
I nee
> d
> | >one is not my idea of a good way to spend time.
> | >
> | >--phil--
> | >
> | >On Thu, 15 Jun 2000 08:33:58 -0400 "John M. Jones" writes
> | >+--------------------
> | >| Does your database support serial fields? These fields generate a
counter
> | >| for each record added. There's a trick to getting the next id when
calling
> | >| create(), but it eliviates coding a unique id generator. I use
PostgreSQL,
> | >| and it has a serial data type.
> | >|
> | >| Hope this helps,
> | >| John
> | >|
> | >| -----Original Message-----
> | >| From: [EMAIL PROTECTED]
> | >| [mailto:[EMAIL PROTECTED]]On Behalf Of Blasius Lofi
> | >| Dewanto
> | >| Sent: Thursday, June 15, 2000 5:13 AM
> | >| To: [EMAIL PROTECTED]
> | >| Subject: Automatic counter
> | >|
> | >|
> | >| Hi all,
> | >|
> | >| I just wonder, whether someone can help me...
> | >|
> | >| How can I implement a counter or a unique id
> | >| for my PrimaryKey in EJB? Because I don't want
> | >| to take care about it in my EJB.
> | >|
> | >| Another question:
> | >| When I quit from the EJBServer through the JonasAdmin,
> | >| I always get this exception:
> | >| Cannot unbind Datasources: java.lang.ClassCastException
> | >| Is this normal?
> | >|
> | >| Thank's a lot!
> | >| --
> | >| ---------------------------------------------------
> | >| Blasius Lofi Dewanto
> | >| ---------------------------------------------------
> | >| OpenUSS - Open Source University Support System
> | >|           http://openuss.sourceforge.net
> | >| ---------------------------------------------------
> | >|
> | >|
> | >| __________________________________________________________________
> | >| Do You Yahoo!?
> | >| Gesendet von Yahoo! Mail - http://mail.yahoo.de
> | >| Yahoo! Auktionen - gleich ausprobieren - http://auktionen.yahoo.de
> | >|
> | >| ----
> | >| To unsubscribe, send email to [EMAIL PROTECTED] and
> | >| include in the body of the message "unsubscribe jonas-users".
> | >| For general help, send email to [EMAIL PROTECTED] and
> | >| include in the body of the message "help".
> | >|
> | >| ----
> | >| To unsubscribe, send email to [EMAIL PROTECTED] and
> | >| include in the body of the message "unsubscribe jonas-users".
> | >| For general help, send email to [EMAIL PROTECTED] and
> | >| include in the body of the message "help".
> | >|
> | >
> | >----
> | >To unsubscribe, send email to [EMAIL PROTECTED] and
> | >include in the body of the message "unsubscribe jonas-users".
> | >For general help, send email to [EMAIL PROTECTED] and
> | >include in the body of the message "help".
> | >
> | >
> |
> |
>
> ----
> To unsubscribe, send email to [EMAIL PROTECTED] and
> include in the body of the message "unsubscribe jonas-users".
> For general help, send email to [EMAIL PROTECTED] and
> include in the body of the message "help".

instructors_with_sequences.jar

Instructors with Sequences
--------------------------

This example modifies the EJB example "instructors" to use primary key
generation.  The original instructors example required that the client
fabricate the primary keys in order to construct the instructor
instances.  In this version, the client simply creates instructor
entities, and the server takes care of fabricating a unique primary
key.

There are two EJBs which cooperate to provide unique primary keys.
The first class is the "Sequence" entity bean.  This class is simply a
name/value pair, where the "value" indicates the current minimum
non-allocated primary key value.  The "name" is the name of the given
sequence.  Any number of uniquely named sequences may be stored in the
same table.

The Sequence entity bean is accessed via the SequenceGenerator
stateless session bean.  This session bean provides "block-oriented"
access to the underlying entity bean (and thus to the underlying
database).  The first time a client asks for a unique primary key from
the SequenceGenerator, the underlying Sequence is found or created,
and its current minimum non-allocated primary key is atomically read
and incremented by a specified block size.  The SequenceGenerator then
hands out incremental primary keys directly until the block size is
reached, at which point it goes back to the Sequence to get the next
block of numbers.

There are a number of subtleties to this code:

The method Sequence.getValueAfterIncrementingBy runs in its own
transaction (e.g., its transaction-attribute is RequiresNew).  Also
the Sequence bean uses VerifyModifiedFields optimistic concurrency
mode.  These two settings ensure that getting the next block of
sequence numbers is both fast (due to the fact that the method runs in
its own transaction) and serialized (due to the fact that the
transaction will fail to commit if the sequence was updated
concurrently in a different transaction).  Note that the serialization
of the update could also be achieved by specifying the SERIALIZABLE
isolation level on the JDBC connection.  If this is done, this should
probably be on a different JDB connection than the main work, since
the SERIALIZABLE isolation level has a significant performance
overhead if not needed.

The SequenceGenerator is a stateless session bean which has state.
Note that this is not a contradiction: in EJB, whether a session bean
is stateful or stateless depends on whether the bean has
"conversational" state, or has state relative to a particular client
(or caller).  In this case, the state of the stateless session bean is
not dependent on the client (or caller).  Thus, this is a valid use of
a stateless session bean.  

Another peculiarity of the SequenceGenerator is its dependence on the
fact that the EJB container does in fact pool stateless session beans.
Note that in the EJB specification, it is not technically required
that a stateless session bean be reused for sequential calls; it is
legal to implement stateful session beans by instantiating a new
object for every call.  Were a container to do this, the performance
of the SequenceGenerator would be unacceptable, because it would have
to go back to the database for every primary key fabrication.  It is
likely that any viable EJB container will implement stateless session
bean pooling, in which case the SequenceGenerator will have good
performance.

Configuration of the SequenceGenerator is done in the deployment
descriptor. Two EJB environment variables are used to configure the
bean:

blockSize: The number of primary keys to allocate before going back to
the database.

retryCount: The call from the SequenceGenerator to the Sequence can
fail, due to a concurrency collision.  If a collision occurs, the
SequenceGenerator will receive a TransactionRolledbackException from
the call to Sequence.getValueAfterIncrementingBy.  The retry count
indicates how many times to try to access the Sequence before finally
giving up.

To run the example, see the readme for the "instructors" example.

Reply via email to