public String updateKeyValueDatabase(String key, String value) {
    EntityManager entityManager = entityManagerFactory.createEntityManager();

    try {
      userTransaction.begin();

      /*
       * Since the Entity Manager (EM) is not managed by the container the developer must explicitly tell the EM
       * to join the transaction. Compare this with ManagedComponent where the container automatically
       * enlists the EM with the transaction. The persistence context managed by the EM will then be scoped
       * to the JTA transaction which means that all entities will be detached when the transaction commits.
       */
      entityManager.joinTransaction();

      // make some transactional changes
      String result = updateKeyValueDatabase(entityManager, key, value);

      /*
       * Note that the default scope of entities managed by the EM is transaction. Thus once the transaction
       * commits the entity will be detached from the EM. See also the comment in the finally block below.
       */
      userTransaction.commit();

      return result;
    } catch (RollbackException e) {
      // We tried to commit the transaction but it has already been rolled back (adding duplicate
      // keys would
      // generate this condition although the example does check for duplicates).
      Throwable t = e.getCause();

      return t != null ? t.getMessage() : e.getMessage();
    } catch (Exception e) {
      /*
       * An application cannot handle any of the other exceptions raised by begin and commit so we just
       * catch the generic exception. The meaning of the other exceptions is:
       *
       * NotSupportedException - the thread is already associated with a transaction
       * HeuristicRollbackException - should not happen since the example is interacting with a single database
       * HeuristicMixedException -  should not happen since the example is interacting with a single database
       * SystemException - the TM raised an unexpected error. There is no standard way of handling this error
       *  (another reason why CMT are preferable to managing them ourselves)
       */
      return e.getMessage();
    } finally {
      /*
       * Since the EM is transaction scoped it will not detach its objects even when calling close on it
       * until the transaction completes. Therefore we must roll back any active transaction before returning.
       */
      try {
        if (userTransaction.getStatus() == Status.STATUS_ACTIVE) userTransaction.rollback();
      } catch (Throwable e) {
        // ignore
      }

      entityManager.close();
    }
  }