My concern is to implement a lock on an Entity EJB across a client session.
The idea is to create a single CMP EJB responsible for providing an applicative lock on the EJB (as we cannot use the DB locking, because of short transaction in J2EE). So any time a client wants to access an Entity bean, it would request the lock manager for the lock on this specific bean. The lock manager would register the Entity primary key, and the client session.
The problem I have is when the lock manager fonds a lock on an entity, how can it validates the lock. I mean, is client session that registered the lock still exists (in order not to implement timeout).
Is there a way to retrieve a handle on the client session (I may use a Statefull Session bean)? And how can I check that the session is still alive?
May be my design is not right and there is a "standard" way to implement this. So if you have any suggestion ...
One relatively standard way to do this is 'optimistic locking', but this may have different semantics to what you want.
Optimistic locking puts a version number column in every table in your DB. The version number gets incremented every time a row is updated. At the start of a long lived transaction (i.e. a transaction managed by optimistic locking rather than DB locking) the client reads the version number of a row along with the data in the row. When the time comes to update the row the update fails if the version number has changed (i.e. another session has updated the row)
This scheme means that the first session to do an update wins, and other sessions will only find out when they try to commit. They won't be blocked when they 'acquire' the lock, because locks are not really being aquired.
This scheme can work well, as long as conflicts can be discovered later rather than sooner.
Actually, we have to implement a pessimistic lock, as we do not want the finally user able to do some changes and not being able to save them.
I doubt you can do what you want with a CMP entity bean. It may be possible with BMP, but it will require a very deep understanding of the EJB spec to implement this in a way that is portable. A couple of months ago two patterns were posted in this direction and both were flawed. These kinds of solutions usually fail when the app server uses commit options B or C (listed in EJB spec).
IMHO, the clearest solution (and least error prone) is this:
Make a stateful session bean LockManager which manages locks. Have it record every lock it aquires in some central table. Accesses to this table should be very strongly synchronized. Better use READ_SERIALIZABLE and "SELECT ... FOR UPDATE" (or it's equivalent in non-Oracle DBs).
If a record of the lock exists, you can't aquire the lock. The session bean should also keep track of the locks it aquired. On session bean destruction clear up the locks. You should watch out from throwing runtime exceptions from session bean methods (destroys bean without calling usual destruction methods). You should also have something clean up old locks once in a while, because catastrophic errors (container crush) may leave the locks up.
If this is all too complicated for your case, I'd suggest you just use the DB transaction mechanisms to enforce pessimistic locking. This has some design problems, but it's far easier.