code: public static String obtainLock(EntityManager em, long expiration, long type, String note) {
          EntityTransaction tx = null;
  
          /* remove the existing lock if it's expired */
          try {
              long now = System.currentTimeMillis();
  
              tx = em.getTransaction();
              tx.begin();
  
              GlobalInterlock lock = _findAndRefreshLock(em, type);
  
              if (lock != null && now - lock.lockTime > expiration) {
                  em.remove(lock);
                  em.flush();
              }
              tx.commit();
          } catch (Exception ex) {
              LOGGER.warn("An error occurred trying to refresh the type {} lock: {}", type, ex.getMessage());
              LOGGER.debug(ex.getMessage(), ex);
              if (tx != null && tx.isActive()) {
                  tx.rollback();
              }
          }
  
          /* attempt to obtain a lock */
          try {
              tx = em.getTransaction();
              tx.begin();
  
              GlobalInterlock lock = em.merge(new GlobalInterlock(type, note));
  
              em.flush();
              tx.commit();
              return Long.toHexString(lock.lockTime);
          } catch (Exception ex) {
              throw new GlobalInterlockException("Could not obtain " + type + " lock", ex);
          } finally {
              if (tx != null && tx.isActive()) {
                  tx.rollback();
              }
          }
      }
docs: Obtains a global lock of a given type.
  
  @param   em          The entity manager to use. Cannot be null.
  @param   expiration  The time in milliseconds after which an existing lock may be clobbered and re-acquired.
  @param   type        The application specific lock type represented as a long value.
  @param   note        A descriptive note about the lock context.
  
  @return  The unique key to be used from clients when releasing the lock.
  
  @throws  GlobalInterlockException  If the lock cannot be obtained.