title: Conditionally locking method of a stateless EJB
body: <p>A method of a stateless EJB have to do a read-and-insert operation in transaction. First step is a complex check to test if the insert operation is allowed with the given parameters.</p>
  
  <pre><code>public boolean DoCheckThanCreateAndAddItemToGroup(Item newItem, Group group) {
       // STEP 1: checks if newItem can be created and added to group
       // This is a complex operation with database reading and some logic
       // using the current items of the group
       if (!DoesNewItemFitInGroup(newItem, group)) {
           return false;
       }
  
       // STEP 2: creates (persists) Item and adds it to Group
       em.persist(newItem);
       newItem.setGroup(group);
       return true;
  }
  </code></pre>
  
  <p>It is obvious that the whole method should be locked to prevent concurrent execution in order not to add two or more items that don't fit together in the group. Default container managed JTA transaction handling does not provide this. The method can run parallel with the same group.</p>
  
  <p>Currently, when running parallel, both clients can pass the check before any of them made the insert operation, so both clients insert its new item. But these items are not fit together in the group: after one is added, other should fail the check and mustn't be added.</p>
  
  <p>Even if I can set transaction-isolation to SERIALIZABLE level (but I don't know how), it won't be a perfect solution because when the method is running concurrently with different groups, locking is needless and would slow down the system unnecessarily.</p>
  
  <p>Other solution would be to put the method into a singleton EJB with @Lock(LockType.WRITE). But the problem is the same: for different Groups locking is unnecessary.</p>
  
  <p>Something like this would solve the problem:</p>
  
  <pre><code>public boolean DoCheckThanCreateAndAddItemToGroup(Item newItem, Group group) {
      lock(group) {
          // STEP 1
  
          // STEP 2
      }
  }
  </code></pre>
  
  <p>How to achieve this behaviour in a suitable way in the EJB environment? (Maybe in distributed environment, as well.)</p>
  
  <p>Or any other idea, how to correctly handle this problem?</p>