Code pour la méthode deposer du bean CDI (rappel : commit à la fin de la méthode) :

  /**
   * Déposer un montant sur un compte. Version qui tient compte de la
   * concurrence.
   */
  @Transactional (dontRollbackOn = { ConcurrentAccessException })
  public void deposer(CompteBancaire compte, int montant) {
    int solde = compte.getSolde();
    boolean concurrence = false;
    // Le compte est relu pour avoir la dernière valeur du solde.
    // (le compte a pu être modifié depuis son affichage dans la page JSF)
    // Il est bloqué pour empêcher d'autres éventuelles modifications.
    // Déblocage à la fin de l'exécution de la méthode (au commit).
    compte = em.find(CompteBancaire.class, compte.getId(),
            LockModeType.PESSIMISTIC_WRITE);
    if (solde != compte.getSolde()) {
      // le solde a été modifié ; il faut avertir l'utilisateur.
      concurrence = true;
    }
    compte.deposer(montant);
    update(compte);
    if (concurrence) {
      // le solde a été modifié ; il faut avertir l'utilisateur
      throw new ConcurrentAccessException("Le solde a été modifié concurremment. Le dépôt a été effectué en tenant compte du solde réel.");
    }
  }

Code similaire pour la méthode retirer.

Code pour le backing bean :

  public String enregistrerMouvement() {
    try {
      if (typeMouvement.equals("ajout")) {
        try {
        gestionnaireCompte.deposer(compte, montant);
        } catch(ConcurrentAccessException ex) {
          Util.addFlashErrorMessage(ex.getMessage());
        }
      ...

La classe d'exception (très simplifiée) :

/**
 * Exception lancée en cas d'accès concurrent sans gravité.
 */
public class ConcurrentAccessException extends RuntimeException {

  public ConcurrentAccessException(String message) {
    super(message);
  }
}