@Subscribe
  @AllowConcurrentEvents
  @RequiresSession
  public void onAlertEvent(AlertReceivedEvent event) throws AmbariException {
    if (LOG.isDebugEnabled()) {
      LOG.debug(event.toString());
    }

    // process the list of alerts inside of a single transaction to prevent too
    // many transactions/commits
    List<Alert> alerts = event.getAlerts();

    // these can be wrapped in their own transaction
    List<AlertCurrentEntity> toMerge = new ArrayList<>();
    List<AlertCurrentEntity> toCreateHistoryAndMerge = new ArrayList<>();

    List<AlertEvent> alertEvents = new ArrayList<>(20);
    Map<Long, Map<String, AlertSummaryGroupedRenderer.AlertDefinitionSummary>> alertUpdates = new HashMap<>();

    for (Alert alert : alerts) {
      Long clusterId = alert.getClusterId();
      if (clusterId == null) {
        // check event
        clusterId = event.getClusterId();
      }

      AlertDefinitionEntity definition = m_definitionDao.findByName(clusterId, alert.getName());

      if (null == definition) {
        LOG.warn(
          "Received an alert for {} which is a definition that does not exist in cluster id={}",
          alert.getName(), clusterId);

        continue;
      }

      alert.setComponent(definition.getComponentName());
      alert.setLabel(definition.getComponentName());
      alert.setService(definition.getServiceName());

      // jobs that were running when a service/component/host was changed
      // which invalidate the alert should not be reported
      if (!isValid(alert)) {
        continue;
      }
      // it's possible that a definition which is disabled will still have a
      // running alert returned; this will ensure we don't record it
      if (!definition.getEnabled()) {
        LOG.debug(
          "Received an alert for {} which is disabled. No more alerts should be received for this definition.",
          alert.getName());

        continue;
      }

      updateAlertDetails(alert, definition);

      // jobs that were running when a service/component/host was changed
      // which invalidate the alert should not be reported
      if (!isValid(alert)) {
        continue;
      }

      AlertCurrentEntity current;
      AlertState alertState = alert.getState();

      // attempt to lookup the current alert
      current = getCurrentEntity(clusterId, alert, definition);

      // if it doesn't exist then we must create it, ensuring that two or more
      // aren't created from other threads
      if( null == current ){

        // if there is no current alert and the state is skipped, then simply
        // skip over this one as there is nothing to update in the databse
        if (alertState == AlertState.SKIPPED) {
          continue;
        }

        // create a key out of the cluster/definition name/host (possibly null)
        int key = Objects.hash(clusterId, alert.getName(), alert.getHostName());
        Lock lock = creationLocks.get(key);
        lock.lock();

        // attempt to lookup the current alert again to ensure that a previous
        // thread didn't already create it
        try {
          // if it's not null anymore, then there's no work to do here
          current = getCurrentEntity(clusterId, alert, definition);
          if( null != current ) {
            continue;
          }

          // the current alert is still null, so go through and create it
          AlertHistoryEntity history = createHistory(clusterId, definition, alert);

          // this new alert must reflect the correct MM state for the
          // service/component/host
          MaintenanceState maintenanceState = getMaintenanceState(alert, clusterId);

          current = new AlertCurrentEntity();
          current.setMaintenanceState(maintenanceState);
          current.setAlertHistory(history);
          current.setLatestTimestamp(alert.getTimestamp());
          current.setOriginalTimestamp(alert.getTimestamp());
          clearStaleAlerts(alert.getHostName(), definition.getDefinitionId());

          // brand new alert instances being received are always HARD
          current.setFirmness(AlertFirmness.HARD);

          m_alertsDao.create(current);

          // create the event to fire later
          alertEvents.add(new InitialAlertEvent(clusterId, alert, current));

          if (!alertUpdates.containsKey(clusterId)) {
            alertUpdates.put(clusterId, new HashMap<>());
          }
          Map<String, AlertSummaryGroupedRenderer.AlertDefinitionSummary> summaries = alertUpdates.get(clusterId);

          AlertSummaryGroupedRenderer.updateSummary(summaries, definition.getDefinitionId(),
              definition.getDefinitionName(), alertState, alert.getTimestamp(), maintenanceState, alert.getText());
        } finally {
          // release the lock for this alert
          lock.unlock();
        }
      } else if (alertState == current.getAlertHistory().getAlertState()
          || alertState == AlertState.SKIPPED) {

        // update the timestamp no matter what
        current.setLatestTimestamp(alert.getTimestamp());
        clearStaleAlerts(alert.getHostName(), definition.getDefinitionId());

        // only update some fields if the alert isn't SKIPPED
        if (alertState != AlertState.SKIPPED) {
          current.setLatestText(alert.getText());

          // ++ the occurrences (should be safe enough since we should ever only
          // be handling unique alert events concurrently
          long occurrences = current.getOccurrences() + 1;
          current.setOccurrences(occurrences);

          // ensure that if we've met the repeat tolerance and the alert is
          // still SOFT, then we transition it to HARD - we also need to fire an
          // event
          AlertFirmness firmness = current.getFirmness();
          int repeatTolerance = getRepeatTolerance(definition, clusterId);
          if (firmness == AlertFirmness.SOFT && occurrences >= repeatTolerance) {
            current.setFirmness(AlertFirmness.HARD);

            // create the event to fire later
            AlertStateChangeEvent stateChangedEvent = new AlertStateChangeEvent(clusterId, alert,
                current, alertState, firmness);

            alertEvents.add(stateChangedEvent);
          }
        }

        // some special cases for SKIPPED alerts
        if (alertState == AlertState.SKIPPED) {
          // set the text on a SKIPPED alert IFF it's not blank; a blank text
          // field means that the alert doesn't want to change the existing text
          String alertText = alert.getText();
          if (StringUtils.isNotBlank(alertText)) {
            current.setLatestText(alertText);
          }
        }

        // store the entity for merging later
        toMerge.add(current);
      } else {
        if (LOG.isDebugEnabled()) {
          LOG.debug(
            "Alert State Changed: CurrentId {}, CurrentTimestamp {}, HistoryId {}, HistoryState {}",
            current.getAlertId(), current.getLatestTimestamp(),
            current.getAlertHistory().getAlertId(),
            current.getAlertHistory().getAlertState());
        }

        AlertHistoryEntity oldHistory = current.getAlertHistory();
        AlertState oldState = oldHistory.getAlertState();
        AlertFirmness oldFirmness = current.getFirmness();

        // insert history, update current
        AlertHistoryEntity history = createHistory(clusterId,
          oldHistory.getAlertDefinition(), alert);

        current.setLatestTimestamp(alert.getTimestamp());
        current.setOriginalTimestamp(alert.getTimestamp());
        current.setLatestText(alert.getText());

        clearStaleAlerts(alert.getHostName(), definition.getDefinitionId());

        current.setAlertHistory(history);

        // figure out how to set the occurrences correctly
        switch (alertState) {
          // an OK state always resets, regardless of what the old one was
          case OK:
            current.setOccurrences(1);
            break;
          case CRITICAL:
          case SKIPPED:
          case UNKNOWN:
          case WARNING:
            // OK -> non-OK is a reset
            if (oldState == AlertState.OK) {
              current.setOccurrences(1);
            } else {
              // non-OK -> non-OK is a continuation
              current.setOccurrences(current.getOccurrences() + 1);
            }
            break;
          default:
            break;
        }

        // set the firmness of the new alert state based on the state, type,
        // occurrences, and repeat tolerance
        AlertFirmness firmness = calculateFirmnessForStateChange(clusterId, definition,
            alertState, current.getOccurrences());

        current.setFirmness(firmness);

        // store the entity for merging later
        toCreateHistoryAndMerge.add(current);

        // create the event to fire later
        alertEvents.add(new AlertStateChangeEvent(clusterId, alert, current, oldState, oldFirmness));

        // create alert update to fire event to UI
        MaintenanceState maintenanceState = getMaintenanceState(alert, clusterId);

        if (!alertUpdates.containsKey(clusterId)) {
          alertUpdates.put(clusterId, new HashMap<>());
        }
        Map<String, AlertSummaryGroupedRenderer.AlertDefinitionSummary> summaries = alertUpdates.get(clusterId);

        AlertSummaryGroupedRenderer.updateSummary(summaries, definition.getDefinitionId(),
            definition.getDefinitionName(), alertState, alert.getTimestamp(), maintenanceState, alert.getText());
      }
    }

    // invokes the EntityManager create/merge on various entities in a single
    // transaction
    m_alertsDao.saveEntities(toMerge, toCreateHistoryAndMerge);

    // broadcast events
    for (AlertEvent eventToFire : alertEvents) {
      m_alertEventPublisher.publish(eventToFire);
    }
    if (!alertUpdates.isEmpty()) {
      STOMPUpdatePublisher.publish(new AlertUpdateEvent(alertUpdates));
    }
  }
Adds an alert. Checks for a new state before creating a new history record.

@param event
         the event to handle.
ambari-server/src/main/java/org/apache/ambari/server/events/listeners/alerts/AlertReceivedListener.java