Hi, we faced the same problem (excessive concurrent entity create -
see http://www.jboss.org/modules/bb/index.html?module=bb&op=viewtopic&t=forums/ have three options:
1. Running the create() within a tx you can catch DuplicateKeyException
thrown by the second create(). (If you run outside a tx - you get some
SQLException "PK-constraint violated...".)
Retry findByPrimaryKey() once upon DuplicateKeyException will get you
the valid instance. This works in a cluster. And it´s easy.
2. This is the option we choose (for performance - we do not want to call
findByPrimaryKey() twice since it´s a database call):
Create and maintain a lock on the primary key of an entity type.
I wrote an interceptor that catches a registerLock(PrimaryKey) method
via home interface. This interceptor creates a lock for each PK.
All subsequent threads requesting for this PK will be blocked until
the first caller frees the lock.
(Beware this lock must block all threads before any JBoss resources are
involved; i.e. it´s the first interceptor in the chain.)
3. Serialize access to your entity create via "Synchronized Singleton Stateless
SessionBean" container configuration. Do not use any synchronize-code
in your session bean - it won´t help anyway (you probably have two instances
of that session bean accessing your entity concurrently).
I´d choose the first option if you´re for a cluster (else you would need to
distribute the lock).
The second option is very efficient on a single node and more generic
(you can have the lock spanning multiple method invocations/tx independently
from JBoss resource/tx management). But this should be a rare requirement...
The third option is easy but introduces a bottleneck with the singleton - and we
really do want to scale with J2EE?