title: Java EE concurrency & locking
body: <p>I have a MDB (Message driven bean) that receives messages with String which represent a word. Also I have a table in the database. The MDB should store in the table, the words and the number of times each word was received (counter).</p>
  
  <p>The problem is that to get better performance the MDB started in many instances and when the same new word is received by different instances they both create the same row with count of 1.</p>
  
  <p>To solve this I should make the word field unique and then the second instance will fail on commit, retransmitting the message, which will work, but may be problematic. Is it a good practice ?</p>
  
  <p>Another solution is to merge these lines afterwards summing the counter. But what if another instance will increase the counter in the middle of the update.</p>
  
  <p>What if two instances try to increase the counter ? <code>@Version</code> should be enough?</p>
  
  <p>I'm not sure what is the proper solution here. How would you handle such cases ?</p>
  
  <p>Also can you suggest some books about concurrency practices (not about the use of <code>synchronized</code> as I need to support Java EE and may run a cluster of application servers)?</p>
  
  <hr>
  
  <p><strong>Update:</strong>
  After reading more about EJB and JPA I suppose I want something like an locking entity. For example I can create a new table with only id and key columns and data like this:</p>
  
  <pre><code>ID | KEY
  1  | WORDS_CREATE_LOCK
  </code></pre>
  
  <p>So that when I need to handle a new word I will do something like this (not exact code, not sure it will even compile):</p>
  
  <pre><code>// MAIN FUNCTION
  public void handleWord(String wordStr) {
    Word w = getWord(wordStr);
  
    if (w == null)
      w = getNewOrSychronizedWord(wordStr);
  
    em.lock(w);
    w.setCounter(w.getCounter() + 1);
    em.unlock(w);
  }
  
  // Returns Word instance or null if not found
  private Word getWord(String wordStr) {
    Word w = null;
  
    Query query = em.createQuery("select w from words as w where w.string = :wordStr order by w.id asc");
    query.setParameter("wordStr", wordStr);
    List&lt;Word&gt; words = query.getResultList();
  
    if (words.getSize() &gt; 0)
      w = words.get(0);
  
    return w;
  }
  
  // Handles locking to prevent duplicate word creation
  private Word getNewOrSynchronizedWord(String wordStr) {
    Word w = null;
    Locks l = em.find(WORDS_CREATE_LOCK_ID, Locks.class);
    em.lock(l);
  
    Word w = getWord(wordStr);
  
    if (w == null) {
      w = new Word(wordStr);
      em.persist(w);
    }
  
    em.unlock(l);
    return w;
  }
  </code></pre>
  
  <p><strong>So the question is will it work that way? And can I do the same without maintaining a DB Table with locking rows? May be some Java EE container locking mechanism ?</strong></p>
  
  <p>If it helps I'm using JBoss 4.2.</p>
  
  <hr>
  
  <p>I have a new idea for this. I can create two MDBs:</p>
  
  <p>1st MDB with many instances allowed, that will handle all the messages and if the word is not found will send the word to the second MDB</p>
  
  <p>2nd MDB with only one instance allowed, will handle the messages serially and will allow creation of new word</p>
  
  <p>The best part: no entire table/method/process locking, only row locking on counter update</p>
  
  <p>How good is that ?</p>
  
  <p>Thanks.</p>