I found several resources to help me with this issue, but I can't seem to mix all the ingredients in order to suit my needs.
I want to "lock" a Cat
(or even several) from being petted by other users, if a petting of it (or them) is already in progress. I also want to provide a feedback to the caller, telling him who called the API before him.
@Local
@Singleton // or @Stateful?
public class CatPetterBean_Local implements CatBean_Facade
{
/**
* Key - The ID of the Cat
*/
final private ConcurrentHashMap<Integer, User> pettingState = new ConcurrentHashMap<>();
@TransactionAttribute(TransactionAttributeType.REQUIRED)
@Override
public GzipROWithMsg<Object> pet(final ImmutableSet<Integer> catIds)
{
checkIfTheyAreBeingPetted_AndThrowRuntimeExec(catIds);
<...>
// After petting, they will be saved by the caller bean (e.g. CatPetterBeanImpl)
}
<...>
}
- Petting takes a while
Cat
s retain a state in the DB:ALREADY_PETTED
andNOT_PETTED
. Once it is already pat, it cannot be petted again. I even thought of loading theCat
from the DB and checking its state on-the-fly, but I think it's more network traffic that way.- How can I take advantage of notions like
synchronized
keywords,@Lock
annotations - No, I am not using Spring
- No, This isn't a webapp
- Yes, I do lack EE knowledge. I'm asking this question in a process of fast learning.
EJB Singletons have under the hood a locking mechanism, by default, all bean methods are serialized via write locks. The default concurrency model on EJB Singletons is: @ConcurrencyManagement(ConcurrencyManagementType.CONTAINER), this is the default, no need to annotate the singleton with this. When Container Concurrency Management is in play as I said before every method is write locked. If you want finer control over singleton methods you can annotate them with @Lock(LockType.READ) which means that the method can be accessed concurrently while no one holds a write lock on the bean, or @Lock(LockType.WRITE) giving exclusive access to the current thread.
Alternatively, you can use Bean concurrency management. In this case, you should annotate your singleton class with: @ConcurrencyManagement(ConcurrencyManagementType.BEAN). In this case, you use synchronized and other Java concurrency goodies. For most of my needs Container Managed concurrency was more than enough.
Another remark to the above code fragment is that @Local doesn't seem appropriate, my guess is that CatBean_Facade should be annotated with @Local.