You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by nc...@apache.org on 2014/07/25 22:25:39 UTC

git commit: AMBARI-6620. Alerts: DAO Relationships and Cascading (Jonathan Hurley via ncole)

Repository: ambari
Updated Branches:
  refs/heads/trunk d4b0b2f6f -> 7602acae4


AMBARI-6620. Alerts: DAO Relationships and Cascading (Jonathan Hurley via ncole)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/7602acae
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/7602acae
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/7602acae

Branch: refs/heads/trunk
Commit: 7602acae48d1c6b6369574f53bef552258b5ef21
Parents: d4b0b2f
Author: Nate Cole <nc...@hortonworks.com>
Authored: Fri Jul 25 16:24:30 2014 -0400
Committer: Nate Cole <nc...@hortonworks.com>
Committed: Fri Jul 25 16:24:30 2014 -0400

----------------------------------------------------------------------
 .../AlertDefinitionResourceProvider.java        |  33 ++-
 .../server/orm/dao/AlertDefinitionDAO.java      |  30 ++-
 .../ambari/server/orm/dao/AlertDispatchDAO.java |  98 ++++++-
 .../apache/ambari/server/orm/dao/AlertsDAO.java |  61 ++++-
 .../server/orm/entities/AlertCurrentEntity.java |  21 +-
 .../orm/entities/AlertDefinitionEntity.java     |  44 ++-
 .../server/orm/entities/AlertGroupEntity.java   |  16 +-
 .../server/orm/entities/AlertHistoryEntity.java |  33 +--
 .../server/orm/entities/AlertNoticeEntity.java  |   5 +-
 .../server/orm/entities/AlertTargetEntity.java  |  26 +-
 .../resources/Ambari-DDL-Postgres-CREATE.sql    |  15 +-
 .../Ambari-DDL-Postgres-EMBEDDED-CREATE.sql     |  20 +-
 .../AlertDefinitionResourceProviderTest.java    |   4 +-
 .../apache/ambari/server/orm/OrmTestHelper.java |  76 ++++++
 .../server/orm/dao/AlertDefinitionDAOTest.java  | 148 +++++++---
 .../server/orm/dao/AlertDispatchDAOTest.java    | 270 +++++++++++++++++--
 .../ambari/server/orm/dao/AlertsDAOTest.java    |  58 ++--
 17 files changed, 788 insertions(+), 170 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/7602acae/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AlertDefinitionResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AlertDefinitionResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AlertDefinitionResourceProvider.java
index 966d8b5..6f00c27 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AlertDefinitionResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AlertDefinitionResourceProvider.java
@@ -42,6 +42,7 @@ import org.apache.ambari.server.controller.utilities.PropertyHelper;
 import org.apache.ambari.server.orm.dao.AlertDefinitionDAO;
 import org.apache.ambari.server.orm.entities.AlertDefinitionEntity;
 import org.apache.ambari.server.state.Cluster;
+import org.apache.ambari.server.state.alert.Scope;
 import org.apache.ambari.server.state.alert.SourceType;
 
 import com.google.gson.Gson;
@@ -129,8 +130,9 @@ public class AlertDefinitionResourceProvider extends AbstractControllerResourceP
     
     if (!requestMap.containsKey(ALERT_DEF_INTERVAL))
       throw new IllegalArgumentException("Check interval must be specified");
-    Long interval = Long.valueOf((String) requestMap.get(ALERT_DEF_INTERVAL));
     
+    Integer interval = Integer.valueOf((String) requestMap.get(ALERT_DEF_INTERVAL));
+
     if (!requestMap.containsKey(ALERT_DEF_NAME))
       throw new IllegalArgumentException("Definition name must be specified");
     
@@ -159,22 +161,28 @@ public class AlertDefinitionResourceProvider extends AbstractControllerResourceP
     Cluster cluster = getManagementController().getClusters().getCluster(clusterName);
     
     AlertDefinitionEntity entity = new AlertDefinitionEntity();
-    
     entity.setClusterId(Long.valueOf(cluster.getClusterId()));
     entity.setComponentName((String) requestMap.get(ALERT_DEF_COMPONENT_NAME));
     entity.setDefinitionName((String) requestMap.get(ALERT_DEF_NAME));
 
-    boolean b = requestMap.containsKey(ALERT_DEF_ENABLED) ?
+    boolean enabled = requestMap.containsKey(ALERT_DEF_ENABLED) ?
         Boolean.parseBoolean((String)requestMap.get(ALERT_DEF_ENABLED)) : true;
-    entity.setEnabled(b);
     
+    entity.setEnabled(enabled);
     entity.setHash(UUID.randomUUID().toString());
     entity.setScheduleInterval(interval);
-    entity.setScope((String) requestMap.get(ALERT_DEF_SCOPE));
     entity.setServiceName((String) requestMap.get(ALERT_DEF_SERVICE_NAME));
     entity.setSourceType((String) requestMap.get(ALERT_DEF_SOURCE_TYPE));
     entity.setSource(jsonObj.toString());
     
+    Scope scope = null;
+    String desiredScope = (String) requestMap.get(ALERT_DEF_SCOPE);
+    if (null != desiredScope && desiredScope.length() > 0) {
+      scope = Scope.valueOf(desiredScope);
+    }
+
+    entity.setScope(scope);
+
     return entity;
   }
 
@@ -242,12 +250,19 @@ public class AlertDefinitionResourceProvider extends AbstractControllerResourceP
         }
         
         if (propertyMap.containsKey(ALERT_DEF_INTERVAL)) {
-          entity.setScheduleInterval(Long.valueOf(
+          entity.setScheduleInterval(Integer.valueOf(
               (String) propertyMap.get(ALERT_DEF_INTERVAL)));
         }
-        
-        if (propertyMap.containsKey(ALERT_DEF_SCOPE))
-          entity.setScope((String) propertyMap.get(ALERT_DEF_SCOPE));
+                
+        if (propertyMap.containsKey(ALERT_DEF_SCOPE)){
+          Scope scope = null;
+          String desiredScope = (String) propertyMap.get(ALERT_DEF_SCOPE);
+              
+          if (null != desiredScope && desiredScope.length() > 0)
+            scope = Scope.valueOf((desiredScope));
+         
+          entity.setScope(scope);
+        }
         
 
         if (propertyMap.containsKey(ALERT_DEF_SOURCE_TYPE))

http://git-wip-us.apache.org/repos/asf/ambari/blob/7602acae/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/AlertDefinitionDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/AlertDefinitionDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/AlertDefinitionDAO.java
index 9163d6e..05881e4 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/AlertDefinitionDAO.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/AlertDefinitionDAO.java
@@ -22,7 +22,6 @@ import java.util.List;
 import javax.persistence.EntityManager;
 import javax.persistence.TypedQuery;
 
-import org.apache.ambari.server.orm.RequiresSession;
 import org.apache.ambari.server.orm.entities.AlertDefinitionEntity;
 
 import com.google.inject.Inject;
@@ -49,13 +48,24 @@ public class AlertDefinitionDAO {
   DaoUtils daoUtils;
 
   /**
+   * Alert history DAO.
+   */
+  @Inject
+  AlertsDAO alertsDao;
+
+  /**
+   * Alert dispatch DAO.
+   */
+  @Inject
+  AlertDispatchDAO dispatchDao;
+
+  /**
    * Gets an alert definition with the specified ID.
    * 
    * @param definitionId
    *          the ID of the definition to retrieve.
    * @return the alert definition or {@code null} if none exists.
    */
-  @RequiresSession
   public AlertDefinitionEntity findById(long definitionId) {
     return entityManagerProvider.get().find(AlertDefinitionEntity.class,
         definitionId);
@@ -71,7 +81,6 @@ public class AlertDefinitionDAO {
    *          the name of the definition (not {@code null}).
    * @return the alert definition or {@code null} if none exists.
    */
-  @RequiresSession
   public AlertDefinitionEntity findByName(long clusterId, String definitionName) {
     TypedQuery<AlertDefinitionEntity> query = entityManagerProvider.get().createNamedQuery(
         "AlertDefinitionEntity.findByName", AlertDefinitionEntity.class);
@@ -88,7 +97,6 @@ public class AlertDefinitionDAO {
    * @return all alert definitions or an empty list if none exist (never
    *         {@code null}).
    */
-  @RequiresSession
   public List<AlertDefinitionEntity> findAll() {
     TypedQuery<AlertDefinitionEntity> query = entityManagerProvider.get().createNamedQuery(
         "AlertDefinitionEntity.findAll", AlertDefinitionEntity.class);
@@ -102,7 +110,6 @@ public class AlertDefinitionDAO {
    * @return all alert definitions or empty list if none exist (never
    *         {@code null}).
    */
-  @RequiresSession
   public List<AlertDefinitionEntity> findAll(long clusterId) {
     TypedQuery<AlertDefinitionEntity> query = entityManagerProvider.get().createNamedQuery(
         "AlertDefinitionEntity.findAllInCluster", AlertDefinitionEntity.class);
@@ -148,13 +155,22 @@ public class AlertDefinitionDAO {
   }
 
   /**
-   * Removes the specified alert definition from the database.
+   * Removes the specified alert definition and all related history and
+   * associations from the database.
    * 
    * @param alertDefinition
    *          the definition to remove.
    */
   @Transactional
   public void remove(AlertDefinitionEntity alertDefinition) {
-    entityManagerProvider.get().remove(merge(alertDefinition));
+    alertDefinition = merge(alertDefinition);
+    dispatchDao.removeNoticeByDefinitionId(alertDefinition.getDefinitionId());
+    alertsDao.removeByDefinitionId(alertDefinition.getDefinitionId());
+
+    EntityManager entityManager = entityManagerProvider.get();
+
+    alertDefinition = findById(alertDefinition.getDefinitionId());
+    if (null != alertDefinition)
+      entityManager.remove(alertDefinition);
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/7602acae/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/AlertDispatchDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/AlertDispatchDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/AlertDispatchDAO.java
index 08c49d8..2871e62 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/AlertDispatchDAO.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/AlertDispatchDAO.java
@@ -22,8 +22,8 @@ import java.util.List;
 import javax.persistence.EntityManager;
 import javax.persistence.TypedQuery;
 
-import org.apache.ambari.server.orm.RequiresSession;
 import org.apache.ambari.server.orm.entities.AlertGroupEntity;
+import org.apache.ambari.server.orm.entities.AlertNoticeEntity;
 import org.apache.ambari.server.orm.entities.AlertTargetEntity;
 
 import com.google.inject.Inject;
@@ -56,7 +56,6 @@ public class AlertDispatchDAO {
    *          the ID of the group to retrieve.
    * @return the group or {@code null} if none exists.
    */
-  @RequiresSession
   public AlertGroupEntity findGroupById(long groupId) {
     return entityManagerProvider.get().find(AlertGroupEntity.class, groupId);
   }
@@ -68,12 +67,22 @@ public class AlertDispatchDAO {
    *          the ID of the target to retrieve.
    * @return the target or {@code null} if none exists.
    */
-  @RequiresSession
   public AlertTargetEntity findTargetById(long targetId) {
     return entityManagerProvider.get().find(AlertTargetEntity.class, targetId);
   }
 
   /**
+   * Gets a notification with the specified ID.
+   * 
+   * @param noticeId
+   *          the ID of the notification to retrieve.
+   * @return the notification or {@code null} if none exists.
+   */
+  public AlertNoticeEntity findNoticeById(long noticeId) {
+    return entityManagerProvider.get().find(AlertNoticeEntity.class, noticeId);
+  }
+
+  /**
    * Gets an alert group with the specified name across all clusters. Alert
    * group names are unique within a cluster.
    * 
@@ -81,7 +90,6 @@ public class AlertDispatchDAO {
    *          the name of the group (not {@code null}).
    * @return the alert group or {@code null} if none exists.
    */
-  @RequiresSession
   public AlertGroupEntity findGroupByName(String groupName) {
     TypedQuery<AlertGroupEntity> query = entityManagerProvider.get().createNamedQuery(
         "AlertGroupEntity.findByName", AlertGroupEntity.class);
@@ -101,7 +109,6 @@ public class AlertDispatchDAO {
    *          the name of the group (not {@code null}).
    * @return the alert group or {@code null} if none exists.
    */
-  @RequiresSession
   public AlertGroupEntity findGroupByName(long clusterId, String groupName) {
     TypedQuery<AlertGroupEntity> query = entityManagerProvider.get().createNamedQuery(
         "AlertGroupEntity.findByNameInCluster", AlertGroupEntity.class);
@@ -120,7 +127,6 @@ public class AlertDispatchDAO {
    *          the name of the target (not {@code null}).
    * @return the alert target or {@code null} if none exists.
    */
-  @RequiresSession
   public AlertTargetEntity findTargetByName(String targetName) {
     TypedQuery<AlertTargetEntity> query = entityManagerProvider.get().createNamedQuery(
         "AlertTargetEntity.findByName", AlertTargetEntity.class);
@@ -135,7 +141,6 @@ public class AlertDispatchDAO {
    * 
    * @return all alert groups or empty list if none exist (never {@code null}).
    */
-  @RequiresSession
   public List<AlertGroupEntity> findAllGroups() {
     TypedQuery<AlertGroupEntity> query = entityManagerProvider.get().createNamedQuery(
         "AlertGroupEntity.findAll", AlertGroupEntity.class);
@@ -149,7 +154,6 @@ public class AlertDispatchDAO {
    * @return all alert groups in the specified cluster or empty list if none
    *         exist (never {@code null}).
    */
-  @RequiresSession
   public List<AlertGroupEntity> findAllGroups(long clusterId) {
     TypedQuery<AlertGroupEntity> query = entityManagerProvider.get().createNamedQuery(
         "AlertGroupEntity.findAllInCluster", AlertGroupEntity.class);
@@ -164,7 +168,6 @@ public class AlertDispatchDAO {
    * 
    * @return all alert targets or empty list if none exist (never {@code null}).
    */
-  @RequiresSession
   public List<AlertTargetEntity> findAllTargets() {
     TypedQuery<AlertTargetEntity> query = entityManagerProvider.get().createNamedQuery(
         "AlertTargetEntity.findAll", AlertTargetEntity.class);
@@ -173,6 +176,19 @@ public class AlertDispatchDAO {
   }
 
   /**
+   * Gets all alert notifications stored in the database.
+   * 
+   * @return all alert notifications or empty list if none exist (never
+   *         {@code null}).
+   */
+  public List<AlertNoticeEntity> findAllNotices() {
+    TypedQuery<AlertNoticeEntity> query = entityManagerProvider.get().createNamedQuery(
+        "AlertNoticeEntity.findAll", AlertNoticeEntity.class);
+
+    return daoUtils.selectList(query);
+  }
+
+  /**
    * Persists a new alert group.
    * 
    * @param alertGroup
@@ -261,4 +277,68 @@ public class AlertDispatchDAO {
   public void remove(AlertTargetEntity alertTarget) {
     entityManagerProvider.get().remove(merge(alertTarget));
   }
+
+  /**
+   * Persists a new notification.
+   * 
+   * @param alertNotice
+   *          the notification to persist (not {@code null}).
+   */
+  @Transactional
+  public void create(AlertNoticeEntity alertNotice) {
+    entityManagerProvider.get().persist(alertNotice);
+  }
+
+  /**
+   * Refresh the state of the notification from the database.
+   * 
+   * @param alertNotice
+   *          the notification to refresh (not {@code null}).
+   */
+  @Transactional
+  public void refresh(AlertNoticeEntity alertNotice) {
+    entityManagerProvider.get().refresh(alertNotice);
+  }
+
+  /**
+   * Merge the specified notification with the existing target in the database.
+   * 
+   * @param alertNotice
+   *          the notification to merge (not {@code null}).
+   * @return the updated notification with merged content (never {@code null}).
+   */
+  @Transactional
+  public AlertNoticeEntity merge(AlertNoticeEntity alertNotice) {
+    return entityManagerProvider.get().merge(alertNotice);
+  }
+
+  /**
+   * Removes the specified notification from the database.
+   * 
+   * @param alertNotice
+   *          the notification to remove.
+   */
+  @Transactional
+  public void remove(AlertNoticeEntity alertNotice) {
+    entityManagerProvider.get().remove(merge(alertNotice));
+  }
+
+  /**
+   * Removes notifications for the specified alert definition ID. This will
+   * invoke {@link EntityManager#clear()} when completed since the JPQL
+   * statement will remove entries without going through the EM.
+   * 
+   * @param definitionId
+   *          the ID of the definition to remove.
+   */
+  @Transactional
+  public void removeNoticeByDefinitionId(long definitionId) {
+    EntityManager entityManager = entityManagerProvider.get();
+    TypedQuery<AlertNoticeEntity> currentQuery = entityManager.createNamedQuery(
+        "AlertNoticeEntity.removeByDefinitionId", AlertNoticeEntity.class);
+
+    currentQuery.setParameter("definitionId", definitionId);
+    currentQuery.executeUpdate();
+    entityManager.clear();
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/7602acae/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/AlertsDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/AlertsDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/AlertsDAO.java
index a1257a2..f2a5886 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/AlertsDAO.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/AlertsDAO.java
@@ -60,7 +60,6 @@ public class AlertsDAO {
    *          the ID of the alert to retrieve.
    * @return the alert or {@code null} if none exists.
    */
-  @RequiresSession
   public AlertHistoryEntity findById(long alertId) {
     return entityManagerProvider.get().find(AlertHistoryEntity.class, alertId);
   }
@@ -70,7 +69,6 @@ public class AlertsDAO {
    * 
    * @return all alerts or an empty list if none exist (never {@code null}).
    */
-  @RequiresSession
   public List<AlertHistoryEntity> findAll() {
     TypedQuery<AlertHistoryEntity> query = entityManagerProvider.get().createNamedQuery(
         "AlertHistoryEntity.findAll", AlertHistoryEntity.class);
@@ -86,7 +84,6 @@ public class AlertsDAO {
    * @return all alerts in the specified cluster or an empty list if none exist
    *         (never {@code null}).
    */
-  @RequiresSession
   public List<AlertHistoryEntity> findAll(long clusterId) {
     TypedQuery<AlertHistoryEntity> query = entityManagerProvider.get().createNamedQuery(
         "AlertHistoryEntity.findAllInCluster", AlertHistoryEntity.class);
@@ -196,6 +193,18 @@ public class AlertsDAO {
   }
 
   /**
+   * Gets a current alert with the specified ID.
+   * 
+   * @param alertId
+   *          the ID of the alert to retrieve.
+   * @return the alert or {@code null} if none exists.
+   */
+  @RequiresSession
+  public AlertCurrentEntity findCurrentById(long alertId) {
+    return entityManagerProvider.get().find(AlertCurrentEntity.class, alertId);
+  }
+
+  /**
    * Gets the current alerts for a given service.
    * 
    * @return the current alerts for the given service or an empty list if none
@@ -232,6 +241,47 @@ public class AlertsDAO {
   }
 
   /**
+   * Removes alert history and current alerts for the specified alert defintiion
+   * ID. This will invoke {@link EntityManager#clear()} when completed since the
+   * JPQL statement will remove entries without going through the EM.
+   * 
+   * @param definitionId
+   *          the ID of the definition to remove.
+   */
+  @Transactional
+  public void removeByDefinitionId(long definitionId) {
+    EntityManager entityManager = entityManagerProvider.get();
+    TypedQuery<AlertCurrentEntity> currentQuery = entityManager.createNamedQuery(
+        "AlertCurrentEntity.removeByDefinitionId", AlertCurrentEntity.class);
+
+    currentQuery.setParameter("definitionId", definitionId);
+    currentQuery.executeUpdate();
+
+    TypedQuery<AlertHistoryEntity> historyQuery = entityManager.createNamedQuery(
+        "AlertHistoryEntity.removeByDefinitionId", AlertHistoryEntity.class);
+
+    historyQuery.setParameter("definitionId", definitionId);
+    historyQuery.executeUpdate();
+
+    entityManager.clear();
+  }
+
+  /**
+   * Remove a current alert whose history entry matches the specfied ID.
+   * 
+   * @param   historyId the ID of the history entry.
+   * @return  the number of alerts removed.
+   */
+  @Transactional
+  public int removeCurrentByHistoryId(long historyId) {
+    TypedQuery<AlertCurrentEntity> query = entityManagerProvider.get().createNamedQuery(
+        "AlertCurrentEntity.removeByHistoryId", AlertCurrentEntity.class);
+
+    query.setParameter("historyId", historyId);
+    return query.executeUpdate();
+  }
+
+  /**
    * Persists a new alert.
    * 
    * @param alert
@@ -273,7 +323,10 @@ public class AlertsDAO {
    */
   @Transactional
   public void remove(AlertHistoryEntity alert) {
-    entityManagerProvider.get().remove(merge(alert));
+    alert = merge(alert);
+
+    removeCurrentByHistoryId(alert.getAlertId());
+    entityManagerProvider.get().remove(alert);
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/7602acae/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertCurrentEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertCurrentEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertCurrentEntity.java
index 6da5723..d00cbc7 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertCurrentEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertCurrentEntity.java
@@ -21,12 +21,15 @@ import javax.persistence.Column;
 import javax.persistence.Entity;
 import javax.persistence.EnumType;
 import javax.persistence.Enumerated;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
 import javax.persistence.Id;
 import javax.persistence.JoinColumn;
 import javax.persistence.NamedQueries;
 import javax.persistence.NamedQuery;
 import javax.persistence.OneToOne;
 import javax.persistence.Table;
+import javax.persistence.TableGenerator;
 
 import org.apache.ambari.server.state.MaintenanceState;
 
@@ -40,13 +43,17 @@ import org.apache.ambari.server.state.MaintenanceState;
  */
 @Entity
 @Table(name = "alert_current")
+@TableGenerator(name = "alert_current_id_generator", table = "ambari_sequences", pkColumnName = "sequence_name", valueColumnName = "value", pkColumnValue = "alert_current_id_seq", initialValue = 0, allocationSize = 1)
 @NamedQueries({
     @NamedQuery(name = "AlertCurrentEntity.findAll", query = "SELECT alert FROM AlertCurrentEntity alert"),
     @NamedQuery(name = "AlertCurrentEntity.findByService", query = "SELECT alert FROM AlertCurrentEntity alert JOIN alert.alertHistory history WHERE history.clusterId = :clusterId AND history.serviceName = :serviceName"),
-    @NamedQuery(name = "AlertCurrentEntity.findByHost", query = "SELECT alert FROM AlertCurrentEntity alert JOIN alert.alertHistory history WHERE history.clusterId = :clusterId AND history.hostName = :hostName") })
+    @NamedQuery(name = "AlertCurrentEntity.findByHost", query = "SELECT alert FROM AlertCurrentEntity alert JOIN alert.alertHistory history WHERE history.clusterId = :clusterId AND history.hostName = :hostName"),
+    @NamedQuery(name = "AlertCurrentEntity.removeByHistoryId", query = "DELETE FROM AlertCurrentEntity alert WHERE alert.alertHistory.alertId = :historyId"),
+    @NamedQuery(name = "AlertCurrentEntity.removeByDefinitionId", query = "DELETE FROM AlertCurrentEntity alert WHERE alert.alertDefinition.definitionId = :definitionId") })
 public class AlertCurrentEntity {
 
   @Id
+  @GeneratedValue(strategy = GenerationType.TABLE, generator = "alert_current_id_generator")
   @Column(name = "alert_id", nullable = false, updatable = false)
   private Long alertId;
 
@@ -61,13 +68,20 @@ public class AlertCurrentEntity {
   private Long originalTimestamp;
 
   /**
-   * Bi-directional one-to-one association to {@link AlertHistoryEntity}
+   * Unidirectional one-to-one association to {@link AlertHistoryEntity}
    */
   @OneToOne
-  @JoinColumn(name = "alert_id", nullable = false, insertable = false, updatable = false)
+  @JoinColumn(name = "history_id", unique = true, nullable = false)
   private AlertHistoryEntity alertHistory;
 
   /**
+   * Unidirectional one-to-one association to {@link AlertDefinitionEntity}
+   */
+  @OneToOne
+  @JoinColumn(name = "definition_id", unique = false, nullable = false)
+  private AlertDefinitionEntity alertDefinition;
+
+  /**
    * Constructor.
    */
   public AlertCurrentEntity() {
@@ -174,6 +188,7 @@ public class AlertCurrentEntity {
    */
   public void setAlertHistory(AlertHistoryEntity alertHistory) {
     this.alertHistory = alertHistory;
+    alertDefinition = alertHistory.getAlertDefinition();
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/7602acae/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertDefinitionEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertDefinitionEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertDefinitionEntity.java
index 9c2d5a2..3aa0e62 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertDefinitionEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertDefinitionEntity.java
@@ -19,18 +19,25 @@ package org.apache.ambari.server.orm.entities;
 
 import java.util.Set;
 
+import javax.persistence.CascadeType;
 import javax.persistence.Column;
 import javax.persistence.Entity;
+import javax.persistence.EntityManager;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
 import javax.persistence.GeneratedValue;
 import javax.persistence.GenerationType;
 import javax.persistence.Id;
 import javax.persistence.ManyToMany;
 import javax.persistence.NamedQueries;
 import javax.persistence.NamedQuery;
+import javax.persistence.PreRemove;
 import javax.persistence.Table;
 import javax.persistence.TableGenerator;
 import javax.persistence.UniqueConstraint;
 
+import org.apache.ambari.server.state.alert.Scope;
+
 /**
  * The {@link AlertDefinitionEntity} class is used to model an alert that needs
  * to run in the system. Each received alert from an agent will essentially be
@@ -64,7 +71,8 @@ public class AlertDefinitionEntity {
   private String definitionName;
   
   @Column(name = "scope", length = 255)
-  private String scope;
+  @Enumerated(value = EnumType.STRING)
+  private Scope scope;
 
   @Column(nullable = false)
   private Integer enabled = Integer.valueOf(1);
@@ -73,7 +81,7 @@ public class AlertDefinitionEntity {
   private String hash;
 
   @Column(name = "schedule_interval", nullable = false)
-  private Long scheduleInterval;
+  private Integer scheduleInterval;
 
   @Column(name = "service_name", nullable = false, length = 255)
   private String serviceName;
@@ -84,7 +92,8 @@ public class AlertDefinitionEntity {
   /**
    * Bi-directional many-to-many association to {@link AlertGroupEntity}
    */
-  @ManyToMany(mappedBy = "alertDefinitions")
+  @ManyToMany(mappedBy = "alertDefinitions", cascade = { CascadeType.PERSIST,
+      CascadeType.MERGE, CascadeType.REFRESH })
   private Set<AlertGroupEntity> alertGroups;
 
   /**
@@ -180,22 +189,22 @@ public class AlertDefinitionEntity {
 
   /**
    * Gets the scope of the alert definition. The scope is defined as either
-   * being for a SERVICE or a HOST.
+   * being for a {@link Scope#SERVICE} or {@link Scope#HOST}.
    * 
    * @return the scope, or {@code null} if not defined.
    */
-  public String getScope() {
+  public Scope getScope() {
     return scope;
   }
 
   /**
    * Sets the scope of the alert definition. The scope is defined as either
-   * being for a SERVICE or a HOST.
+   * being for a {@link Scope#SERVICE} or {@link Scope#HOST}.
    * 
    * @param scope
    *          the scope to set, or {@code null} for none.
    */
-  public void setScope(String scope) {
+  public void setScope(Scope scope) {
     this.scope = scope;
   }
 
@@ -269,7 +278,7 @@ public class AlertDefinitionEntity {
    * 
    * @return the interval, in seconds.
    */
-  public Long getScheduleInterval() {
+  public Integer getScheduleInterval() {
     return scheduleInterval;
   }
 
@@ -279,7 +288,7 @@ public class AlertDefinitionEntity {
    * @param scheduleInterval
    *          the interval, in seconds.
    */
-  public void setScheduleInterval(Long scheduleInterval) {
+  public void setScheduleInterval(Integer scheduleInterval) {
     this.scheduleInterval = scheduleInterval;
   }
 
@@ -340,6 +349,23 @@ public class AlertDefinitionEntity {
   }
 
   /**
+   * Called before {@link EntityManager#remove(Object)} for this entity, removes
+   * the non-owning relationship between definitions and groups.
+   */
+  @PreRemove
+  public void preRemove() {
+    Set<AlertGroupEntity> groups = getAlertGroups();
+    if (null == groups || groups.size() == 0)
+      return;
+
+    for (AlertGroupEntity group : groups) {
+      Set<AlertDefinitionEntity> definitions = group.getAlertDefinitions();
+      if (null != definitions)
+        definitions.remove(this);
+    }
+  }
+
+  /**
    *
    */
   @Override

http://git-wip-us.apache.org/repos/asf/ambari/blob/7602acae/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertGroupEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertGroupEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertGroupEntity.java
index 6e67214..4da552f 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertGroupEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertGroupEntity.java
@@ -17,6 +17,7 @@
  */
 package org.apache.ambari.server.orm.entities;
 
+import java.util.HashSet;
 import java.util.Set;
 
 import javax.persistence.Column;
@@ -71,9 +72,10 @@ public class AlertGroupEntity {
   private Set<AlertDefinitionEntity> alertDefinitions;
 
   /**
-   * Bi-directional many-to-many association to {@link AlertTargetEntity}
+   * Unidirectional many-to-many association to {@link AlertTargetEntity}
    */
-  @ManyToMany(mappedBy = "alertGroups")
+  @ManyToMany
+  @JoinTable(name = "alert_group_target", joinColumns = { @JoinColumn(name = "group_id", nullable = false) }, inverseJoinColumns = { @JoinColumn(name = "target_id", nullable = false) })
   private Set<AlertTargetEntity> alertTargets;
 
   /**
@@ -201,6 +203,16 @@ public class AlertGroupEntity {
    */
   public void setAlertTargets(Set<AlertTargetEntity> alertTargets) {
     this.alertTargets = alertTargets;
+
+    if (null != alertTargets) {
+      for (AlertTargetEntity target : alertTargets) {
+        Set<AlertGroupEntity> groups = target.getAlertGroups();
+        if (null == groups)
+          groups = new HashSet<AlertGroupEntity>();
+
+        groups.add(this);
+      }
+    }
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/7602acae/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertHistoryEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertHistoryEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertHistoryEntity.java
index 4b0d39c..3e8b15b 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertHistoryEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertHistoryEntity.java
@@ -28,7 +28,6 @@ import javax.persistence.JoinColumn;
 import javax.persistence.ManyToOne;
 import javax.persistence.NamedQueries;
 import javax.persistence.NamedQuery;
-import javax.persistence.OneToOne;
 import javax.persistence.Table;
 import javax.persistence.TableGenerator;
 
@@ -50,7 +49,8 @@ import org.apache.ambari.server.state.AlertState;
     @NamedQuery(name = "AlertHistoryEntity.findAllInClusterWithState", query = "SELECT alertHistory FROM AlertHistoryEntity alertHistory WHERE alertHistory.clusterId = :clusterId AND alertHistory.alertState IN :alertStates"),
     @NamedQuery(name = "AlertHistoryEntity.findAllInClusterBetweenDates", query = "SELECT alertHistory FROM AlertHistoryEntity alertHistory WHERE alertHistory.clusterId = :clusterId AND alertHistory.alertTimestamp BETWEEN :startDate AND :endDate"),
     @NamedQuery(name = "AlertHistoryEntity.findAllInClusterBeforeDate", query = "SELECT alertHistory FROM AlertHistoryEntity alertHistory WHERE alertHistory.clusterId = :clusterId AND alertHistory.alertTimestamp <= :beforeDate"),
-    @NamedQuery(name = "AlertHistoryEntity.findAllInClusterAfterDate", query = "SELECT alertHistory FROM AlertHistoryEntity alertHistory WHERE alertHistory.clusterId = :clusterId AND alertHistory.alertTimestamp >= :afterDate") })
+    @NamedQuery(name = "AlertHistoryEntity.findAllInClusterAfterDate", query = "SELECT alertHistory FROM AlertHistoryEntity alertHistory WHERE alertHistory.clusterId = :clusterId AND alertHistory.alertTimestamp >= :afterDate"),
+    @NamedQuery(name = "AlertHistoryEntity.removeByDefinitionId", query = "DELETE FROM AlertHistoryEntity alertHistory WHERE alertHistory.alertDefinition.definitionId = :definitionId") })
 public class AlertHistoryEntity {
 
   @Id
@@ -87,12 +87,6 @@ public class AlertHistoryEntity {
   private String serviceName;
 
   /**
-   * Bi-directional one-to-one association to {@link AlertCurrentEntity}.
-   */
-  @OneToOne(mappedBy = "alertHistory", orphanRemoval = true)
-  private AlertCurrentEntity alertCurrent;
-
-  /**
    * Unidirectional many-to-one association to {@link AlertDefinitionEntity}
    */
   @ManyToOne
@@ -310,29 +304,6 @@ public class AlertHistoryEntity {
   }
 
   /**
-   * Gets the current, active alert that is associated with this historical
-   * instance, if any. Once an alert state changes, the association between
-   * current and historical will be removed in favor of the newly received alert
-   * instance.
-   * 
-   * @return the associated current alert or {@code null} if this historical
-   *         item is not the most recent.
-   */
-  public AlertCurrentEntity getAlertCurrent() {
-    return alertCurrent;
-  }
-
-  /**
-   * Sets the associated current active alert with this historical instance.
-   * 
-   * @param alertCurrent
-   *          the current alert or {@code null} for none.
-   */
-  public void setAlertCurrent(AlertCurrentEntity alertCurrent) {
-    this.alertCurrent = alertCurrent;
-  }
-
-  /**
    * Gets the associated alert definition for this alert instance. The alert
    * definition can be used to retrieve global information about an alert such
    * as the interval and the name.

http://git-wip-us.apache.org/repos/asf/ambari/blob/7602acae/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertNoticeEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertNoticeEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertNoticeEntity.java
index 9fe1c88..41bc1d8 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertNoticeEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertNoticeEntity.java
@@ -26,6 +26,7 @@ import javax.persistence.GenerationType;
 import javax.persistence.Id;
 import javax.persistence.JoinColumn;
 import javax.persistence.ManyToOne;
+import javax.persistence.NamedQueries;
 import javax.persistence.NamedQuery;
 import javax.persistence.Table;
 import javax.persistence.TableGenerator;
@@ -42,7 +43,9 @@ import org.apache.ambari.server.state.NotificationState;
 @Entity
 @Table(name = "alert_notice")
 @TableGenerator(name = "alert_notice_id_generator", table = "ambari_sequences", pkColumnName = "sequence_name", valueColumnName = "value", pkColumnValue = "alert_notice_id_seq", initialValue = 0, allocationSize = 1)
-@NamedQuery(name = "AlertNoticeEntity.findAll", query = "SELECT alertNotice FROM AlertNoticeEntity alertNotice")
+@NamedQueries({
+    @NamedQuery(name = "AlertNoticeEntity.findAll", query = "SELECT notice FROM AlertNoticeEntity notice"),
+    @NamedQuery(name = "AlertNoticeEntity.removeByDefinitionId", query = "DELETE FROM AlertNoticeEntity notice WHERE notice.alertHistory.alertDefinition.definitionId = :definitionId") })
 public class AlertNoticeEntity {
 
   @Id

http://git-wip-us.apache.org/repos/asf/ambari/blob/7602acae/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertTargetEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertTargetEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertTargetEntity.java
index 3cd444e..91624f2 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertTargetEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertTargetEntity.java
@@ -19,16 +19,17 @@ package org.apache.ambari.server.orm.entities;
 
 import java.util.Set;
 
+import javax.persistence.CascadeType;
 import javax.persistence.Column;
 import javax.persistence.Entity;
+import javax.persistence.EntityManager;
 import javax.persistence.GeneratedValue;
 import javax.persistence.GenerationType;
 import javax.persistence.Id;
-import javax.persistence.JoinColumn;
-import javax.persistence.JoinTable;
 import javax.persistence.ManyToMany;
 import javax.persistence.NamedQueries;
 import javax.persistence.NamedQuery;
+import javax.persistence.PreRemove;
 import javax.persistence.Table;
 import javax.persistence.TableGenerator;
 
@@ -64,8 +65,8 @@ public class AlertTargetEntity {
   /**
    * Bi-directional many-to-many association to {@link AlertGroupEntity}
    */
-  @ManyToMany
-  @JoinTable(name = "alert_group_target", joinColumns = { @JoinColumn(name = "target_id", nullable = false) }, inverseJoinColumns = { @JoinColumn(name = "group_id", nullable = false) })
+  @ManyToMany(mappedBy = "alertTargets", cascade = { CascadeType.PERSIST,
+      CascadeType.MERGE })
   private Set<AlertGroupEntity> alertGroups;
 
   /**
@@ -181,6 +182,23 @@ public class AlertTargetEntity {
   }
 
   /**
+   * Called before {@link EntityManager#remove(Object)} for this entity, removes
+   * the non-owning relationship between targets and groups.
+   */
+  @PreRemove
+  public void preRemove() {
+    Set<AlertGroupEntity> groups = getAlertGroups();
+    if (null == groups || groups.size() == 0)
+      return;
+
+    for (AlertGroupEntity group : groups) {
+      Set<AlertTargetEntity> targets = group.getAlertTargets();
+      if (null != targets)
+        targets.remove(this);
+    }
+  }
+
+  /**
    *
    */
   @Override

http://git-wip-us.apache.org/repos/asf/ambari/blob/7602acae/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
index 73bf442..f43190d 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
@@ -169,7 +169,7 @@ CREATE TABLE alert_definition (
   component_name VARCHAR(255),
   scope VARCHAR(255),
   enabled SMALLINT DEFAULT 1 NOT NULL,
-  schedule_interval BIGINT NOT NULL,
+  schedule_interval INTEGER NOT NULL,
   source_type VARCHAR(255) NOT NULL,
   alert_source TEXT NOT NULL,
   hash VARCHAR(64) NOT NULL,
@@ -197,11 +197,14 @@ CREATE TABLE alert_history (
 
 CREATE TABLE alert_current (
   alert_id BIGINT NOT NULL,
+  definition_id BIGINT NOT NULL,
+  history_id BIGINT NOT NULL UNIQUE,
   maintenance_state VARCHAR(255),
   original_timestamp BIGINT NOT NULL,
   latest_timestamp BIGINT NOT NULL,
   PRIMARY KEY (alert_id),
-  FOREIGN KEY (alert_id) REFERENCES alert_history(alert_id)
+  FOREIGN KEY (definition_id) REFERENCES alert_definition(definition_id),
+  FOREIGN KEY (history_id) REFERENCES alert_history(alert_id)
 );
 
 CREATE TABLE alert_group (
@@ -225,6 +228,7 @@ CREATE TABLE alert_target (
 CREATE TABLE alert_group_target (
   group_id BIGINT NOT NULL,
   target_id BIGINT NOT NULL,
+  PRIMARY KEY (group_id, target_id),
   FOREIGN KEY (group_id) REFERENCES alert_group(group_id),
   FOREIGN KEY (target_id) REFERENCES alert_target(target_id)
 );
@@ -232,6 +236,7 @@ CREATE TABLE alert_group_target (
 CREATE TABLE alert_grouping (
   definition_id BIGINT NOT NULL,
   group_id BIGINT NOT NULL,
+  PRIMARY KEY (group_id, definition_id),
   FOREIGN KEY (definition_id) REFERENCES alert_definition(definition_id),
   FOREIGN KEY (group_id) REFERENCES alert_group(group_id)
 );
@@ -246,11 +251,13 @@ CREATE TABLE alert_notice (
   FOREIGN KEY (history_id) REFERENCES alert_history(alert_id)
 );
 
+CREATE INDEX idx_alert_history_def_id on alert_history(alert_definition_id);
 CREATE INDEX idx_alert_history_service on alert_history(service_name);
 CREATE INDEX idx_alert_history_host on alert_history(host_name);
 CREATE INDEX idx_alert_history_time on alert_history(alert_timestamp);
 CREATE INDEX idx_alert_history_state on alert_history(alert_state);
 CREATE INDEX idx_alert_group_name on alert_group(group_name);
+CREATE INDEX idx_alert_notice_state on alert_notice(notify_state);
 
 ---------inserting some data-----------
 BEGIN;
@@ -297,7 +304,9 @@ BEGIN;
   union all
   select 'alert_history_id_seq', 0
   union all
-  select 'alert_notice_id_seq', 0;
+  select 'alert_notice_id_seq', 0,
+  union all
+  select 'alert_current_id_seq', 0;
 
   INSERT INTO adminresourcetype (resource_type_id, resource_type_name)
   SELECT 1, 'AMBARI'

http://git-wip-us.apache.org/repos/asf/ambari/blob/7602acae/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
index f78f07f..aac5521 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
@@ -232,7 +232,7 @@ CREATE TABLE ambari.alert_definition (
   component_name VARCHAR(255),
   scope VARCHAR(255),
   enabled SMALLINT DEFAULT 1 NOT NULL,
-  schedule_interval BIGINT NOT NULL,
+  schedule_interval INTEGER NOT NULL,
   source_type VARCHAR(255) NOT NULL,
   alert_source TEXT NOT NULL,
   hash VARCHAR(64) NOT NULL,
@@ -260,11 +260,14 @@ CREATE TABLE ambari.alert_history (
 
 CREATE TABLE ambari.alert_current (
   alert_id BIGINT NOT NULL,
+  definition_id BIGINT NOT NULL,
+  history_id BIGINT NOT NULL UNIQUE,
   maintenance_state VARCHAR(255),
   original_timestamp BIGINT NOT NULL,
   latest_timestamp BIGINT NOT NULL,
   PRIMARY KEY (alert_id),
-  FOREIGN KEY (alert_id) REFERENCES ambari.alert_history(alert_id)
+  FOREIGN KEY (definition_id) REFERENCES ambari.alert_definition(definition_id),
+  FOREIGN KEY (history_id) REFERENCES ambari.alert_history(alert_id)
 );
 
 CREATE TABLE ambari.alert_group (
@@ -288,15 +291,17 @@ CREATE TABLE ambari.alert_target (
 CREATE TABLE ambari.alert_group_target (
   group_id BIGINT NOT NULL,
   target_id BIGINT NOT NULL,
+  PRIMARY KEY (group_id, target_id),
   FOREIGN KEY (group_id) REFERENCES ambari.alert_group(group_id),
-  FOREIGN KEY (target_id) REFERENCES ambari.alert_target(target_id)
+  FOREIGN KEY (target_id) REFERENCES ambari.alert_target(target_id)  
 );
 
 CREATE TABLE ambari.alert_grouping (
   definition_id BIGINT NOT NULL,
   group_id BIGINT NOT NULL,
+  PRIMARY KEY (group_id, definition_id),
   FOREIGN KEY (definition_id) REFERENCES ambari.alert_definition(definition_id),
-  FOREIGN KEY (group_id) REFERENCES ambari.alert_group(group_id)
+  FOREIGN KEY (group_id) REFERENCES ambari.alert_group(group_id)  
 );
 
 CREATE TABLE ambari.alert_notice (
@@ -318,12 +323,13 @@ GRANT ALL PRIVILEGES ON TABLE ambari.alert_group_target TO :username;
 GRANT ALL PRIVILEGES ON TABLE ambari.alert_grouping TO :username;
 GRANT ALL PRIVILEGES ON TABLE ambari.alert_notice TO :username;
 
-
+CREATE INDEX idx_alert_history_def_id on ambari.alert_history(alert_definition_id);
 CREATE INDEX idx_alert_history_service on ambari.alert_history(service_name);
 CREATE INDEX idx_alert_history_host on ambari.alert_history(host_name);
 CREATE INDEX idx_alert_history_time on ambari.alert_history(alert_timestamp);
 CREATE INDEX idx_alert_history_state on ambari.alert_history(alert_state);
 CREATE INDEX idx_alert_group_name on ambari.alert_group(group_name);
+CREATE INDEX idx_alert_notice_state on ambari.alert_notice(notify_state);
 
 ---------inserting some data-----------
 BEGIN;
@@ -370,7 +376,9 @@ INSERT INTO ambari.ambari_sequences (sequence_name, "value")
   union all
   select 'alert_history_id_seq', 0
   union all
-  select 'alert_notice_id_seq', 0;
+  select 'alert_notice_id_seq', 0,
+  union all
+  select 'alert_current_id_seq', 0;
   
 
 INSERT INTO ambari.adminresourcetype (resource_type_id, resource_type_name)

http://git-wip-us.apache.org/repos/asf/ambari/blob/7602acae/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AlertDefinitionResourceProviderTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AlertDefinitionResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AlertDefinitionResourceProviderTest.java
index b7bcab6..fc57389 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AlertDefinitionResourceProviderTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AlertDefinitionResourceProviderTest.java
@@ -181,7 +181,7 @@ public class AlertDefinitionResourceProviderTest {
     Assert.assertEquals("my_def", entity.getDefinitionName());
     Assert.assertTrue(entity.getEnabled());
     Assert.assertNotNull(entity.getHash());
-    Assert.assertEquals(Long.valueOf(1), entity.getScheduleInterval());
+    Assert.assertEquals(Integer.valueOf(1), entity.getScheduleInterval());
     Assert.assertNull(entity.getScope());
     Assert.assertEquals("HDFS", entity.getServiceName());
     Assert.assertNotNull(entity.getSource());
@@ -321,7 +321,7 @@ public class AlertDefinitionResourceProviderTest {
     entity.setDefinitionName("my_def");
     entity.setEnabled(true);
     entity.setHash("tmphash");
-    entity.setScheduleInterval(Long.valueOf(2L));
+    entity.setScheduleInterval(Integer.valueOf(2));
     entity.setServiceName(null);
     entity.setSourceType("metric");
     entity.setSource("{'jmx': 'beanName/attributeName', 'host': '{{aa:123445}}'}");

http://git-wip-us.apache.org/repos/asf/ambari/blob/7602acae/ambari-server/src/test/java/org/apache/ambari/server/orm/OrmTestHelper.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/orm/OrmTestHelper.java b/ambari-server/src/test/java/org/apache/ambari/server/orm/OrmTestHelper.java
index 5e77a2d..0258e47 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/orm/OrmTestHelper.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/orm/OrmTestHelper.java
@@ -24,6 +24,7 @@ import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
+import java.util.UUID;
 
 import javax.persistence.EntityManager;
 
@@ -31,6 +32,7 @@ import org.apache.ambari.server.Role;
 import org.apache.ambari.server.RoleCommand;
 import org.apache.ambari.server.actionmanager.HostRoleStatus;
 import org.apache.ambari.server.orm.dao.AlertDefinitionDAO;
+import org.apache.ambari.server.orm.dao.AlertDispatchDAO;
 import org.apache.ambari.server.orm.dao.ClusterDAO;
 import org.apache.ambari.server.orm.dao.HostDAO;
 import org.apache.ambari.server.orm.dao.HostRoleCommandDAO;
@@ -38,6 +40,9 @@ import org.apache.ambari.server.orm.dao.RequestDAO;
 import org.apache.ambari.server.orm.dao.RoleDAO;
 import org.apache.ambari.server.orm.dao.StageDAO;
 import org.apache.ambari.server.orm.dao.UserDAO;
+import org.apache.ambari.server.orm.entities.AlertDefinitionEntity;
+import org.apache.ambari.server.orm.entities.AlertGroupEntity;
+import org.apache.ambari.server.orm.entities.AlertTargetEntity;
 import org.apache.ambari.server.orm.entities.ClusterEntity;
 import org.apache.ambari.server.orm.entities.ClusterServiceEntity;
 import org.apache.ambari.server.orm.entities.HostEntity;
@@ -50,6 +55,7 @@ import org.apache.ambari.server.orm.entities.RoleEntity;
 import org.apache.ambari.server.orm.entities.StageEntity;
 import org.apache.ambari.server.orm.entities.UserEntity;
 import org.apache.ambari.server.state.HostState;
+import org.apache.ambari.server.state.alert.Scope;
 import org.springframework.security.crypto.password.PasswordEncoder;
 import org.springframework.util.Assert;
 
@@ -265,4 +271,74 @@ public class OrmTestHelper {
     Assert.isTrue(clusterEntity.getClusterId() > 0);
     return clusterEntity.getClusterId();
   }
+
+  /**
+   * Creates an alert target.
+   * 
+   * @return
+   */
+  @Transactional
+  public AlertTargetEntity createAlertTarget() throws Exception {
+    AlertTargetEntity target = new AlertTargetEntity();
+    target.setDescription("Target Description");
+    target.setNotificationType("EMAIL");
+    target.setProperties("Target Properties");
+    target.setTargetName("Target Name " + System.currentTimeMillis());
+
+    AlertDispatchDAO dao = injector.getInstance(AlertDispatchDAO.class);
+    dao.create(target);
+
+    return dao.findTargetById(target.getTargetId());
+  }
+  
+  /**
+   * Creates an alert definition.
+   * 
+   * @param clusterId
+   * @return
+   * @throws Exception
+   */
+  @Transactional
+  public AlertDefinitionEntity createAlertDefinition(long clusterId)
+      throws Exception {
+    AlertDefinitionEntity definition = new AlertDefinitionEntity();
+    definition.setDefinitionName("Alert Definition "
+        + System.currentTimeMillis());
+    definition.setServiceName("Service " + System.currentTimeMillis());
+    definition.setComponentName(null);
+    definition.setClusterId(clusterId);
+    definition.setHash(UUID.randomUUID().toString());
+    definition.setScheduleInterval(60);
+    definition.setScope(Scope.SERVICE);
+    definition.setSource("Source " + System.currentTimeMillis());
+    definition.setSourceType("SCRIPT");
+    
+    AlertDefinitionDAO dao = injector.getInstance(AlertDefinitionDAO.class);
+    dao.create(definition);
+
+    return dao.findById(definition.getDefinitionId());
+  }
+
+  /**
+   * Creates an alert group.
+   * 
+   * @param clusterId
+   * @param targets
+   * @return
+   * @throws Exception
+   */
+  @Transactional
+  public AlertGroupEntity createAlertGroup(long clusterId,
+      Set<AlertTargetEntity> targets) throws Exception {
+    AlertGroupEntity group = new AlertGroupEntity();
+    group.setDefault(false);
+    group.setGroupName("Group Name " + System.currentTimeMillis());
+    group.setClusterId(clusterId);
+    group.setAlertTargets(targets);
+
+    AlertDispatchDAO dao = injector.getInstance(AlertDispatchDAO.class);
+    dao.create(group);
+
+    return dao.findGroupById(group.getGroupId());
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/7602acae/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/AlertDefinitionDAOTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/AlertDefinitionDAOTest.java b/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/AlertDefinitionDAOTest.java
index de2f5d3..4b1f4be 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/AlertDefinitionDAOTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/AlertDefinitionDAOTest.java
@@ -24,10 +24,16 @@ import static org.easymock.EasyMock.expect;
 import static org.easymock.EasyMock.replay;
 import static org.easymock.EasyMock.reset;
 import static org.easymock.EasyMock.verify;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertSame;
 
+import java.util.Calendar;
 import java.util.Collections;
+import java.util.Date;
 import java.util.List;
+import java.util.TimeZone;
 import java.util.UUID;
 
 import javax.persistence.EntityManager;
@@ -36,7 +42,15 @@ import javax.persistence.TypedQuery;
 import org.apache.ambari.server.orm.GuiceJpaInitializer;
 import org.apache.ambari.server.orm.InMemoryDefaultTestModule;
 import org.apache.ambari.server.orm.OrmTestHelper;
+import org.apache.ambari.server.orm.entities.AlertCurrentEntity;
 import org.apache.ambari.server.orm.entities.AlertDefinitionEntity;
+import org.apache.ambari.server.orm.entities.AlertGroupEntity;
+import org.apache.ambari.server.orm.entities.AlertHistoryEntity;
+import org.apache.ambari.server.orm.entities.AlertNoticeEntity;
+import org.apache.ambari.server.state.AlertState;
+import org.apache.ambari.server.state.MaintenanceState;
+import org.apache.ambari.server.state.NotificationState;
+import org.apache.ambari.server.state.alert.Scope;
 import org.junit.AfterClass;
 import org.junit.Assert;
 import org.junit.Before;
@@ -54,21 +68,30 @@ import com.google.inject.persist.PersistService;
  */
 @SuppressWarnings("unchecked")
 public class AlertDefinitionDAOTest {
+  static Injector injector;
+  static Long clusterId;
+  static AlertDefinitionDAO dao;
+  static AlertsDAO alertsDao;
+  static AlertDispatchDAO dispatchDao;
+  static OrmTestHelper helper;
+  static Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
 
-  AlertDefinitionDAO realDAO;
   AlertDefinitionDAO mockDAO;
   Provider<EntityManager> mockEntityManagerProvider = createStrictMock(Provider.class);
   EntityManager entityManager = createStrictMock(EntityManager.class);
 
-  private static Injector injector;
-  private static Long clusterId;
-
+  /**
+   * 
+   */
   @BeforeClass
   public static void beforeClass() {
     injector = Guice.createInjector(new InMemoryDefaultTestModule());
     injector.getInstance(GuiceJpaInitializer.class);
-    AlertDefinitionDAO alertDefinitionDAO = injector.getInstance(AlertDefinitionDAO.class);
-    clusterId = injector.getInstance(OrmTestHelper.class).createCluster();
+    dao = injector.getInstance(AlertDefinitionDAO.class);
+    alertsDao = injector.getInstance(AlertsDAO.class);
+    dispatchDao = injector.getInstance(AlertDispatchDAO.class);
+    helper = injector.getInstance(OrmTestHelper.class);
+    clusterId = helper.createCluster();
 
     for (int i = 0; i < 8; i++) {
       AlertDefinitionEntity definition = new AlertDefinitionEntity();
@@ -77,11 +100,11 @@ public class AlertDefinitionDAOTest {
       definition.setComponentName(null);
       definition.setClusterId(clusterId);
       definition.setHash(UUID.randomUUID().toString());
-      definition.setScheduleInterval(60L);
-      definition.setScope("SERVICE");
+      definition.setScheduleInterval(60);
+      definition.setScope(Scope.SERVICE);
       definition.setSource("Source " + i);
       definition.setSourceType("SCRIPT");
-      alertDefinitionDAO.create(definition);
+      dao.create(definition);
     }
   }
 
@@ -95,7 +118,7 @@ public class AlertDefinitionDAOTest {
    * 
    */
   @Before
-  public void init() {
+  public void before() {
     injector = Guice.createInjector(new InMemoryDefaultTestModule());
     injector.getInstance(GuiceJpaInitializer.class);
     injector.injectMembers(this);
@@ -104,11 +127,7 @@ public class AlertDefinitionDAOTest {
     expect(mockEntityManagerProvider.get()).andReturn(entityManager).atLeastOnce();
     replay(mockEntityManagerProvider);
 
-    realDAO = new AlertDefinitionDAO();
-    mockDAO = new AlertDefinitionDAO();
-    injector.injectMembers(realDAO);
-    injector.injectMembers(mockDAO);
-
+    mockDAO = injector.getInstance(AlertDefinitionDAO.class);
     mockDAO.entityManagerProvider = mockEntityManagerProvider;
   }
 
@@ -139,10 +158,10 @@ public class AlertDefinitionDAOTest {
     assertSame(result, entity);
     verify(mockEntityManagerProvider, entityManager);
 
-    List<AlertDefinitionEntity> definitions = realDAO.findAll();
+    List<AlertDefinitionEntity> definitions = dao.findAll();
     Assert.assertNotNull(definitions);
     AlertDefinitionEntity definition = definitions.get(2);
-    AlertDefinitionEntity retrieved = realDAO.findByName(
+    AlertDefinitionEntity retrieved = dao.findByName(
         definition.getClusterId(), definition.getDefinitionName());
 
     Assert.assertEquals(definition, retrieved);
@@ -170,7 +189,7 @@ public class AlertDefinitionDAOTest {
     assertSame(entity, entities.get(0));
     verify(mockEntityManagerProvider, entityManager);
 
-    List<AlertDefinitionEntity> definitions = realDAO.findAll();
+    List<AlertDefinitionEntity> definitions = dao.findAll();
     Assert.assertNotNull(definitions);
     Assert.assertEquals(8, definitions.size());
   }
@@ -192,10 +211,10 @@ public class AlertDefinitionDAOTest {
     assertSame(result, entity);
     verify(mockEntityManagerProvider, entityManager);
 
-    List<AlertDefinitionEntity> definitions = realDAO.findAll();
+    List<AlertDefinitionEntity> definitions = dao.findAll();
     Assert.assertNotNull(definitions);
     AlertDefinitionEntity definition = definitions.get(2);
-    AlertDefinitionEntity retrieved = realDAO.findById(definition.getDefinitionId());
+    AlertDefinitionEntity retrieved = dao.findById(definition.getDefinitionId());
 
     Assert.assertEquals(definition, retrieved);
   }
@@ -244,18 +263,83 @@ public class AlertDefinitionDAOTest {
   }
 
   @Test
-  public void testRemove() {
-    AlertDefinitionEntity entity = new AlertDefinitionEntity();
-    AlertDefinitionEntity entity2 = new AlertDefinitionEntity();
-
-    // set expectations
-    expect(entityManager.merge(eq(entity))).andReturn(entity2);
-    entityManager.remove(eq(entity2));
-    replay(entityManager);
-
-    mockDAO.entityManagerProvider = mockEntityManagerProvider;
-    mockDAO.remove(entity);
+  public void testRemove() throws Exception {
+    AlertDefinitionEntity definition = helper.createAlertDefinition(clusterId);
+    definition = dao.findById(definition.getDefinitionId());
+    assertNotNull(definition);
+    dao.remove(definition);
+    definition = dao.findById(definition.getDefinitionId());
+    assertNull(definition);
+  }
 
-    verify(mockEntityManagerProvider, entityManager);
+  /**
+   * @throws Exception
+   */
+  @Test
+  public void testCascadeDelete() throws Exception {
+    AlertDefinitionEntity definition = helper.createAlertDefinition(clusterId);
+
+    AlertGroupEntity group = helper.createAlertGroup(clusterId, null);
+    group.getAlertDefinitions().add(definition);
+    dispatchDao.merge(group);
+
+    AlertHistoryEntity history = new AlertHistoryEntity();
+    history.setServiceName(definition.getServiceName());
+    history.setClusterId(clusterId);
+    history.setAlertDefinition(definition);
+    history.setAlertLabel("Label");
+    history.setAlertState(AlertState.OK);
+    history.setAlertText("Alert Text");
+    history.setAlertTimestamp(calendar.getTimeInMillis());
+    alertsDao.create(history);
+
+    AlertCurrentEntity current = new AlertCurrentEntity();
+    current.setAlertHistory(history);
+    current.setLatestTimestamp(new Date().getTime());
+    current.setOriginalTimestamp(new Date().getTime() - 10800000);
+    current.setMaintenanceState(MaintenanceState.OFF);
+    alertsDao.create(current);
+
+    AlertNoticeEntity notice = new AlertNoticeEntity();
+    notice.setAlertHistory(history);
+    notice.setAlertTarget(helper.createAlertTarget());
+    notice.setNotifyState(NotificationState.PENDING);
+    dispatchDao.create(notice);
+
+    group = dispatchDao.findGroupById(group.getGroupId());
+    assertNotNull(group);
+    assertNotNull(group.getAlertDefinitions());
+    assertEquals(1, group.getAlertDefinitions().size());
+
+    history = alertsDao.findById(history.getAlertId());
+    assertNotNull(history);
+
+    current = alertsDao.findCurrentById(current.getAlertId());
+    assertNotNull(current);
+    assertNotNull(current.getAlertHistory());
+
+    notice = dispatchDao.findNoticeById(notice.getNotificationId());
+    assertNotNull(notice);
+    assertNotNull(notice.getAlertHistory());
+    assertNotNull(notice.getAlertTarget());
+
+    // delete the definition
+    definition = dao.findById(definition.getDefinitionId());
+    dao.refresh(definition);
+    dao.remove(definition);
+
+    notice = dispatchDao.findNoticeById(notice.getNotificationId());
+    assertNull(notice);
+
+    current = alertsDao.findCurrentById(current.getAlertId());
+    assertNull(current);
+
+    history = alertsDao.findById(history.getAlertId());
+    assertNull(history);
+
+    group = dispatchDao.findGroupById(group.getGroupId());
+    assertNotNull(group);
+    assertNotNull(group.getAlertDefinitions());
+    assertEquals(0, group.getAlertDefinitions().size());
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/7602acae/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/AlertDispatchDAOTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/AlertDispatchDAOTest.java b/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/AlertDispatchDAOTest.java
index 3b6aaa0..cf25bd5 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/AlertDispatchDAOTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/AlertDispatchDAOTest.java
@@ -18,17 +18,26 @@
 
 package org.apache.ambari.server.orm.dao;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
+import java.util.UUID;
 
 import org.apache.ambari.server.orm.GuiceJpaInitializer;
 import org.apache.ambari.server.orm.InMemoryDefaultTestModule;
 import org.apache.ambari.server.orm.OrmTestHelper;
+import org.apache.ambari.server.orm.entities.AlertDefinitionEntity;
 import org.apache.ambari.server.orm.entities.AlertGroupEntity;
 import org.apache.ambari.server.orm.entities.AlertTargetEntity;
+import org.apache.ambari.server.state.alert.Scope;
 import org.junit.AfterClass;
-import org.junit.Assert;
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
@@ -44,14 +53,21 @@ public class AlertDispatchDAOTest {
 
   static Long clusterId;
   static Injector injector;
-  AlertDispatchDAO dao;
+  static AlertDispatchDAO dao;
+  static OrmTestHelper helper;
+
+  AlertDefinitionDAO definitionDao;
 
+  /**
+   * 
+   */
   @BeforeClass
   public static void beforeClass() {
     injector = Guice.createInjector(new InMemoryDefaultTestModule());
     injector.getInstance(GuiceJpaInitializer.class);
-    clusterId = injector.getInstance(OrmTestHelper.class).createCluster();
-    AlertDispatchDAO alertDispatchDAO = injector.getInstance(AlertDispatchDAO.class);
+    helper = injector.getInstance(OrmTestHelper.class);
+    clusterId = helper.createCluster();
+    dao = injector.getInstance(AlertDispatchDAO.class);
 
     Set<AlertTargetEntity> targets = new HashSet<AlertTargetEntity>();
     for (int i = 0; i < 5; i++) {
@@ -60,7 +76,7 @@ public class AlertDispatchDAOTest {
       target.setNotificationType("EMAIL");
       target.setProperties("Target Properties " + i);
       target.setTargetName("Target Name " + i);
-      alertDispatchDAO.create(target);
+      dao.create(target);
       targets.add(target);
     }
 
@@ -70,9 +86,8 @@ public class AlertDispatchDAOTest {
       group.setGroupName("Group Name " + i);
       group.setClusterId(clusterId);
       group.setAlertTargets(targets);
-      alertDispatchDAO.create(group);
+      dao.create(group);
     }
-
   }
 
   /**
@@ -89,56 +104,269 @@ public class AlertDispatchDAOTest {
    */
   @Before
   public void setup() {
-    dao = new AlertDispatchDAO();
-    injector.injectMembers(dao);
+    definitionDao = injector.getInstance(AlertDefinitionDAO.class);
   }
 
   /**
    * 
    */
   @Test
-  public void testFindAllTargets() {
+  public void testFindAllTargets() throws Exception {
     List<AlertTargetEntity> targets = dao.findAllTargets();
-    Assert.assertNotNull(targets);
-    Assert.assertEquals(5, targets.size());
+    assertNotNull(targets);
+    assertEquals(5, targets.size());
   }
 
   /**
    * 
    */
   @Test
-  public void testFindTargetByName() {
+  public void testFindTargetByName() throws Exception {
     List<AlertTargetEntity> targets = dao.findAllTargets();
-    Assert.assertNotNull(targets);
+    assertNotNull(targets);
     AlertTargetEntity target = targets.get(3);
 
     AlertTargetEntity actual = dao.findTargetByName(target.getTargetName());
-    Assert.assertEquals(target, actual);
+    assertEquals(target, actual);
   }
 
   /**
    * 
    */
   @Test
-  public void testFindAllGroups() {
+  public void testFindAllGroups() throws Exception {
     List<AlertGroupEntity> groups = dao.findAllGroups();
-    Assert.assertNotNull(groups);
-    Assert.assertEquals(10, groups.size());
+    assertNotNull(groups);
+    assertEquals(10, groups.size());
   }
 
   /**
    * 
    */
   @Test
-  public void testFindGroupByName() {
+  public void testFindGroupByName() throws Exception {
     List<AlertGroupEntity> groups = dao.findAllGroups();
-    Assert.assertNotNull(groups);
+    assertNotNull(groups);
     AlertGroupEntity group = groups.get(3);
 
     AlertGroupEntity actual = dao.findGroupByName(group.getClusterId(),
         group.getGroupName());
 
-    Assert.assertEquals(group, actual);
+    assertEquals(group, actual);
   }
 
+  /**
+   * 
+   */
+  @Test
+  public void testCreateGroup() throws Exception {
+    AlertTargetEntity target = helper.createAlertTarget();
+    Set<AlertTargetEntity> targets = new HashSet<AlertTargetEntity>();
+    targets.add(target);
+
+    AlertGroupEntity group = helper.createAlertGroup(clusterId, targets);
+    AlertGroupEntity actual = dao.findGroupById(group.getGroupId());
+    assertNotNull(group);
+
+    assertEquals(group.getGroupName(), actual.getGroupName());
+    assertEquals(group.isDefault(), actual.isDefault());
+    assertEquals(group.getAlertTargets(), actual.getAlertTargets());
+    assertEquals(group.getAlertDefinitions(), actual.getAlertDefinitions());
+  }
+
+  /**
+   * 
+   */
+  @Test
+  public void testGroupDefinitions() throws Exception {
+    List<AlertDefinitionEntity> definitions = createDefinitions();
+
+    AlertGroupEntity group = helper.createAlertGroup(clusterId, null);
+
+    group = dao.findGroupById(group.getGroupId());
+    assertNotNull(group);
+
+    group.getAlertDefinitions().addAll(definitions);
+    dao.merge(group);
+
+    group = dao.findGroupByName(group.getGroupName());
+    assertEquals(definitions.size(), group.getAlertDefinitions().size());
+
+    for (AlertDefinitionEntity definition : definitions) {
+      assertTrue(group.getAlertDefinitions().contains(definition));
+    }
+
+    definitionDao.refresh(definitions.get(0));
+    definitionDao.remove(definitions.get(0));
+    definitions.remove(0);
+
+    group = dao.findGroupByName(group.getGroupName());
+    assertEquals(definitions.size(), group.getAlertDefinitions().size());
+
+    for (AlertDefinitionEntity definition : definitions) {
+      assertTrue(group.getAlertDefinitions().contains(definition));
+    }
+  }
+
+  /**
+   * 
+   */
+  @Test
+  public void testCreateTarget() throws Exception {
+    int targetCount = dao.findAllTargets().size();
+
+    AlertTargetEntity target = helper.createAlertTarget();
+    Set<AlertTargetEntity> targets = new HashSet<AlertTargetEntity>();
+    targets.add(target);
+
+    AlertGroupEntity group = helper.createAlertGroup(clusterId, targets);
+    AlertTargetEntity actual = dao.findTargetById(target.getTargetId());
+    assertNotNull(actual);
+
+    assertEquals(target.getTargetName(), actual.getTargetName());
+    assertEquals(target.getDescription(), actual.getDescription());
+    assertEquals(target.getNotificationType(), actual.getNotificationType());
+    assertEquals(target.getProperties(), actual.getProperties());
+
+    assertNotNull(actual.getAlertGroups());
+    Iterator<AlertGroupEntity> iterator = actual.getAlertGroups().iterator();
+    AlertGroupEntity actualGroup = iterator.next();
+
+    assertEquals(group, actualGroup);
+
+    assertEquals(targetCount + 1, dao.findAllTargets().size());
+  }
+
+  /**
+   * 
+   */
+  @Test
+  public void testDeleteGroup() throws Exception {
+    int targetCount = dao.findAllTargets().size();    
+    
+    AlertGroupEntity group = helper.createAlertGroup(clusterId, null);
+    AlertTargetEntity target = helper.createAlertTarget();
+    assertEquals(targetCount + 1, dao.findAllTargets().size());
+
+    Set<AlertTargetEntity> targets = new HashSet<AlertTargetEntity>();
+    targets.add(target);
+
+    group = dao.findGroupById(group.getGroupId());
+    assertNotNull(group);
+    assertNotNull(group.getAlertTargets());
+    assertEquals(0, group.getAlertTargets().size());
+
+    group.setAlertTargets(targets);
+    dao.merge(group);
+
+    group = dao.findGroupById(group.getGroupId());
+    assertNotNull(group);
+    assertNotNull(group.getAlertTargets());
+    assertEquals(1, group.getAlertTargets().size());
+
+    dao.remove(group);
+    group = dao.findGroupById(group.getGroupId());
+    assertNull(group);
+
+    target = dao.findTargetById(target.getTargetId());
+    assertNotNull(target);
+    assertEquals(targetCount + 1, dao.findAllTargets().size());
+  }
+
+  /**
+   * 
+   */
+  @Test
+  public void testDeleteTarget() throws Exception {
+    AlertTargetEntity target = helper.createAlertTarget();
+    target = dao.findTargetById(target.getTargetId());
+    assertNotNull(target);
+
+    dao.remove(target);
+
+    target = dao.findTargetById(target.getTargetId());
+    assertNull(target);
+  }
+
+  /**
+   * 
+   */
+  @Test
+  public void testDeleteAssociatedTarget() throws Exception {
+    AlertTargetEntity target = helper.createAlertTarget();
+    Set<AlertTargetEntity> targets = new HashSet<AlertTargetEntity>();
+    targets.add(target);
+
+    AlertGroupEntity group = helper.createAlertGroup(clusterId, targets);
+
+    target = dao.findTargetById(target.getTargetId());
+    assertNotNull(target);
+
+    dao.remove(target);
+    target = dao.findTargetById(target.getTargetId());
+    assertNull(target);
+
+    group = dao.findGroupById(group.getGroupId());
+    assertNotNull(group);
+
+    assertEquals(0, group.getAlertTargets().size());
+  }
+
+  /**
+   * 
+   */
+  @Test
+  public void testUpdateGroup() throws Exception {
+    AlertTargetEntity target = helper.createAlertTarget();
+    Set<AlertTargetEntity> targets = new HashSet<AlertTargetEntity>();
+    targets.add(target);
+
+    String groupName = "Group Name " + System.currentTimeMillis();
+
+    AlertGroupEntity group = helper.createAlertGroup(clusterId, null);
+
+    group = dao.findGroupById(group.getGroupId());
+    group.setGroupName(groupName + "FOO");
+    group.setDefault(true);
+
+    dao.merge(group);
+    group = dao.findGroupById(group.getGroupId());
+
+    assertEquals(groupName + "FOO", group.getGroupName());
+    assertEquals(true, group.isDefault());
+    assertNotNull(group.getAlertDefinitions());
+    assertNotNull(group.getAlertTargets());
+    assertEquals(0, group.getAlertDefinitions().size());
+    assertEquals(0, group.getAlertTargets().size());
+
+    group.getAlertTargets().add(target);
+    dao.merge(group);
+
+    group = dao.findGroupById(group.getGroupId());
+    assertEquals(targets, group.getAlertTargets());
+  }
+
+  /**
+   * @return
+   */
+  private List<AlertDefinitionEntity> createDefinitions() throws Exception {
+    List<AlertDefinitionEntity> alertDefinitions = new ArrayList<AlertDefinitionEntity>();
+
+    for (int i = 0; i < 8; i++) {
+      AlertDefinitionEntity definition = new AlertDefinitionEntity();
+      definition.setDefinitionName("Alert Definition " + i);
+      definition.setServiceName("HDFS");
+      definition.setComponentName(null);
+      definition.setClusterId(clusterId);
+      definition.setHash(UUID.randomUUID().toString());
+      definition.setScheduleInterval(60);
+      definition.setScope(Scope.SERVICE);
+      definition.setSource("Source " + i);
+      definition.setSourceType("SCRIPT");
+      definitionDao.create(definition);
+      alertDefinitions.add(definition);
+    }
+
+    return alertDefinitions;
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/7602acae/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/AlertsDAOTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/AlertsDAOTest.java b/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/AlertsDAOTest.java
index 2bc2b7f..1366f15 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/AlertsDAOTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/AlertsDAOTest.java
@@ -18,6 +18,7 @@
 
 package org.apache.ambari.server.orm.dao;
 
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 
@@ -37,6 +38,7 @@ import org.apache.ambari.server.orm.entities.AlertDefinitionEntity;
 import org.apache.ambari.server.orm.entities.AlertHistoryEntity;
 import org.apache.ambari.server.state.AlertState;
 import org.apache.ambari.server.state.MaintenanceState;
+import org.apache.ambari.server.state.alert.Scope;
 import org.junit.AfterClass;
 import org.junit.Before;
 import org.junit.BeforeClass;
@@ -54,16 +56,23 @@ public class AlertsDAOTest {
   static Long clusterId;
   static Injector injector;
   static Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
+  static OrmTestHelper helper;
+  static AlertsDAO dao;
+  static AlertDefinitionDAO definitionDao;
+  static AlertDispatchDAO dispatchDao;
 
-  AlertsDAO dao;
-
+  /**
+   * 
+   */
   @BeforeClass
   public static void beforeClass() {
     injector = Guice.createInjector(new InMemoryDefaultTestModule());
     injector.getInstance(GuiceJpaInitializer.class);
-    clusterId = injector.getInstance(OrmTestHelper.class).createCluster();
-    AlertsDAO alertDAO = injector.getInstance(AlertsDAO.class);
-    AlertDefinitionDAO alertDefinitionDAO = injector.getInstance(AlertDefinitionDAO.class);
+    helper = injector.getInstance(OrmTestHelper.class);
+    clusterId = helper.createCluster();
+    dao = injector.getInstance(AlertsDAO.class);
+    definitionDao = injector.getInstance(AlertDefinitionDAO.class);
+    dispatchDao = injector.getInstance(AlertDispatchDAO.class);
 
     // create 5 definitions
     for (int i = 0; i < 5; i++) {
@@ -73,14 +82,14 @@ public class AlertsDAOTest {
       definition.setComponentName(null);
       definition.setClusterId(clusterId);
       definition.setHash(UUID.randomUUID().toString());
-      definition.setScheduleInterval(60L);
-      definition.setScope("SERVICE");
+      definition.setScheduleInterval(60);
+      definition.setScope(Scope.SERVICE);
       definition.setSource("Source " + i);
       definition.setSourceType("SCRIPT");
-      alertDefinitionDAO.create(definition);
+      definitionDao.create(definition);
     }
 
-    List<AlertDefinitionEntity> definitions = alertDefinitionDAO.findAll();
+    List<AlertDefinitionEntity> definitions = definitionDao.findAll();
     assertNotNull(definitions);
     assertEquals(5, definitions.size());
 
@@ -95,26 +104,24 @@ public class AlertsDAOTest {
         history.setClusterId(clusterId);
         history.setAlertDefinition(definition);
         history.setAlertLabel(definition.getDefinitionName() + " " + i);
-        history.setAlertState(AlertState.OK);
         history.setAlertText(definition.getDefinitionName() + " " + i);
         history.setAlertTimestamp(calendar.getTimeInMillis());
 
+        history.setAlertState(AlertState.OK);
+        if (i == 0 || i == 5) {
+          history.setAlertState(AlertState.CRITICAL);
+        }
+
         // increase the days for each
         calendar.add(Calendar.DATE, 1);
 
-        alertDAO.create(history);
-
-        if (i == 0 || i == 1) {
-          history.setAlertId(null);
-          history.setAlertState(AlertState.CRITICAL);
-          alertDAO.create(history);
-        }
+        dao.create(history);
       }
     }
 
     // for each definition, create a current alert
     for (AlertDefinitionEntity definition : definitions) {
-      List<AlertHistoryEntity> alerts = alertDAO.findAll();
+      List<AlertHistoryEntity> alerts = dao.findAll();
       AlertHistoryEntity history = null;
       for (AlertHistoryEntity alert : alerts) {
         if (definition.equals(alert.getAlertDefinition())) {
@@ -125,12 +132,11 @@ public class AlertsDAOTest {
       assertNotNull(history);
 
       AlertCurrentEntity current = new AlertCurrentEntity();
-      current.setAlertId(history.getAlertId());
       current.setAlertHistory(history);
       current.setLatestTimestamp(new Date().getTime());
       current.setOriginalTimestamp(new Date().getTime() - 10800000);
       current.setMaintenanceState(MaintenanceState.OFF);
-      alertDAO.create(current);
+      dao.create(current);
     }
   }
 
@@ -148,8 +154,6 @@ public class AlertsDAOTest {
    */
   @Before
   public void setup() {
-    dao = new AlertsDAO();
-    injector.injectMembers(dao);
   }
 
   /**
@@ -159,7 +163,7 @@ public class AlertsDAOTest {
   public void testFindAll() {
     List<AlertHistoryEntity> alerts = dao.findAll(clusterId);
     assertNotNull(alerts);
-    assertEquals(60, alerts.size());
+    assertEquals(50, alerts.size());
   }
 
   /**
@@ -207,11 +211,11 @@ public class AlertsDAOTest {
         
     List<AlertHistoryEntity> history = dao.findAll(clusterId, allStates);
     assertNotNull(history);
-    assertEquals(60, history.size());
+    assertEquals(50, history.size());
 
     history = dao.findAll(clusterId, Collections.singletonList(AlertState.OK));
     assertNotNull(history);
-    assertEquals(50, history.size());
+    assertEquals(40, history.size());
 
     history = dao.findAll(clusterId,
         Collections.singletonList(AlertState.CRITICAL));
@@ -237,12 +241,12 @@ public class AlertsDAOTest {
         calendar.getTime(), null);
 
     assertNotNull(history);
-    assertEquals(60, history.size());
+    assertEquals(50, history.size());
 
     // on or before 1/1/2014
     history = dao.findAll(clusterId, null, calendar.getTime());
     assertNotNull(history);
-    assertEquals(2, history.size());
+    assertEquals(1, history.size());
 
     // between 1/5 and 1/10
     calendar.set(2014, Calendar.JANUARY, 5);