private void preprocessBatchOfDevices(String alertMessage, String cursorString) {
    EntityManager mgr = null;
    Cursor cursor = null;

    try {
      mgr = getEntityManager();

      // Retrieve entities (and not just deviceToken property) in order to paginate using cursor
      Query query = mgr.createQuery("select from DeviceRegistration as DeviceRegistration");
      if (cursorString != null && cursorString != "") {
        cursor = Cursor.fromWebSafeString(cursorString);
        query.setHint(JPACursorHelper.CURSOR_HINT, cursor);
      }

      query.setMaxResults(BATCH_SIZE);

      @SuppressWarnings("unchecked")
      List<DeviceRegistration> deviceRegistrations = query.getResultList();
      cursor = JPACursorHelper.getCursor(deviceRegistrations);
      if (cursor != null) {
        cursorString = cursor.toWebSafeString();
      }

      List<String> deviceTokens = new ArrayList<String>();
      for (DeviceRegistration deviceRegistartion : deviceRegistrations) {
        deviceTokens.add(deviceRegistartion.getDeviceToken());
      }

      if (deviceTokens.isEmpty()) {
        // no more matching device tokens matching this query.
        return;
      }

      mgr.getTransaction().begin();

      try {
        PushNotificationUtility.enqueuePushAlert(alertMessage, deviceTokens);

        if (deviceRegistrations.size() == BATCH_SIZE) {
          PushNotificationUtility.continueEnqueueingPushAlertToAllDevices(
              alertMessage, cursorString);
        }

        mgr.getTransaction().commit();
      } catch (RuntimeException e) {
        if (mgr.getTransaction().isActive()) {
          mgr.getTransaction().rollback();
        }
        throw e;
      }

    } finally {
      mgr.close();
    }
  }