This is a design issue, really, and the important question is :-
"Is it okay for client C2 to delete entity bean B in which client C1 is interested ?"
If the answer is yes, then the client code must cope with trying to access an object that may have vanished. That will probably involve the client keeping state so that the client can distinguish between "Object does not exist" and "Object that did exist has disappeared".
If the answer is no, then client C1 must register an interest in entity bean B by some means. And client C2 must check whether C1 (or other clients) are interested before deleting entity bean B.
This is a well known problem in relational database design.
You are right to reject a design that locks the entity bean through transactions between method calls. Transactions should never be extended over a time interval that includes user think time (which includes coffee breaks, etc.).
What is needed is to mark entity bean B to show that client C1 has an interest.
There are two simple methods.
You can use an attribute of entity bean B "userLock" to hold the name of client C1. If "userLock" is null, other users can change the bean. If it is not null, other users cannot change the bean. Your code must check "userLock" and prevent illegal operations - J2EE cannot do this for you.
This strategy has the disadvantage that, if things go wrong, client C1 disappears without unsetting the attribute "userLock". The system admistrator must unset the lock by some manual method.
The alternative is to lock entity bean B by using a timestamp. Client C1 sets a timestamp attribute named, say, "keepUntil" to half an hour after each access. Your code must check that the time stamp has not expired before modifying or deleting the bean. Using this strategy, locks will expire automatically without work by the administrator.
You can obviously think of more complex solutions where multiple users register an interest until various expiry times. But it is usually a bad idea to make the solution more complex than the problem.
I normally stamp an object with the username of the interested user. This allows me to produce error messages such as :-
Order H0013 is locked by user jamesstrachan
The users involved can then sort it out among themselves instead of troubling the support staff.
by 'clients' I meant other beans. We have quite a number of SLSB's that collect data across several entity beans and sometimes hold some complex business logic. So C1 and C2 are just session beans and creating own locks won't work for at least 2 reasons:
1. when C1 calls B.setUserLock, B can be alredy removed by C2, setUserLock doesn't have any better position than foo() from my original example
2. logic is sometimes complex and invovles several entity beans. Do you imagine what a mess we will have with locking/unclocking B1,B2,..Bn ?
Again, 'session facade' is a common pattern. Do people really catch NoSuchEntityException or make all implementations transactionable? Or they, as we did, don't mind until it crashes? :)
So we are envisaging a posdition where SLSB C1 calls in turn A, B, C, D and then calls B again.
Meanwhile SLSB C2 has deleted B.
You can do one of several things :-
1. By locking A,B,C and D in a transaction you can prevent C2 deleting B.
2. Your code can anticipate and recover from NoSuchEntityExceptions.
3. You can leave the Entity Bean in place but delete all data within the Bean.
You don't want to take the first option as it will slow the system down.
The third option may not be practical - depending on your business logic.
So it looks as though you are left with the second option.
Well, yes, this is one of the ways I was thinking to finally implement. Another interesting solution was found during discussion on TSS http://www.theserverside.com/discussions/thread.tss?thread_id=29180