public WorkItemInfo merge(WorkItemInfo workItemInfo) {
   if (this.pessimisticLocking) {
     if (em.contains(workItemInfo)) {
       em.lock(workItemInfo, LockModeType.PESSIMISTIC_FORCE_INCREMENT);
     } else {
       // Yes, this is a hack, but for detached entities, it's the only way to lock before merging
       WorkItemInfo dbWorkItemInfo =
           em.find(
               WorkItemInfo.class, workItemInfo.getId(), LockModeType.PESSIMISTIC_FORCE_INCREMENT);
       for (Field field : WorkItemInfo.class.getDeclaredFields()) {
         boolean access = field.isAccessible();
         field.setAccessible(true);
         try {
           field.set(dbWorkItemInfo, field.get(workItemInfo));
         } catch (Exception e) {
           logger.error(
               "Unable to set field " + field.getName() + " of unmerged WorkItemInfo instance!",
               e);
         }
         field.setAccessible(access);
       }
     }
   }
   return em.merge(workItemInfo);
 }
 public WorkItemInfo persist(WorkItemInfo workItemInfo) {
   em.persist(workItemInfo);
   if (this.pessimisticLocking) {
     return em.find(
         WorkItemInfo.class, workItemInfo.getId(), LockModeType.PESSIMISTIC_FORCE_INCREMENT);
   }
   return workItemInfo;
 }
  public void commit(boolean transactionOwner) {
    // Do not check if the caller is the transactionOwner
    //  because there's no need to "wait" for a commit
    try {
      for (SessionInfo sessionInfo : session.getStoredKnowledgeSessions()) {
        sessionInfo.transform();
        storage.saveOrUpdate(sessionInfo);
      }

      for (WorkItemInfo workItemInfo : session.getStoredWorkItems()) {
        workItemInfo.transform();
        storage.saveOrUpdate(workItemInfo);
      }
      try {
        transactionSynchronization.afterCompletion(TransactionManager.STATUS_COMMITTED);
      } catch (RuntimeException re) {
        logger.warn("Unable to synchronize transaction after commit, see cause.", re);
      }
    } catch (RuntimeException re) {
      transactionSynchronization.afterCompletion(TransactionManager.STATUS_ROLLEDBACK);
    }
    // We shouldn't clear session here because by doing so
    //  we lose track of this objects on successive interactions
  }
 public void remove(WorkItemInfo workItemInfo) {
   workItems.remove(workItemInfo.getId());
 }
 public void saveOrUpdate(WorkItemInfo workItemInfo) {
   workItems.put(workItemInfo.getId(), workItemInfo);
 }