[prev in list] [next in list] [prev in thread] [next in thread] 

List:       rhq-commits
Subject:    [rhq] Branch 'release-3.0.0' - modules/core modules/enterprise
From:       joseph42 () fedoraproject ! org (Joseph Marques)
Date:       2010-06-30 7:29:19
Message-ID: 20100630072919.5992812071E () lists ! fedorahosted ! org
[Download RAW message or body]

 modules/core/dbutils/src/main/scripts/dbsetup/alert-schema.xml                       \
|    4   modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml               \
|    6   modules/core/domain/src/main/java/org/rhq/core/domain/alert/notification/AlertNotificationLog.java \
|   96 ++----  modules/core/domain/src/main/java/org/rhq/core/domain/alert/notification/ResultState.java \
|   14   modules/core/domain/src/main/java/org/rhq/core/domain/alert/notification/SenderResult.java \
|  156 +++++++---  modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/AlertDataSource.java \
|   13   modules/enterprise/gui/portal-war/src/main/webapp/resource/common/monitor/alerts/ViewAlertNotifications.jsp \
|   20 -  modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertManagerBean.java \
|  139 +++-----  modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertManagerLocal.java \
|    3   modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/alert/AlertSender.java \
|    1   modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/alert/test/AlertManagerBeanTest.java \
|    3   modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/scheduler/jobs/DataPurgeJobTest.java \
|    3   modules/enterprise/server/plugins/alert-email/src/main/java/org/rhq/enterprise/server/plugins/alertEmail/EmailSender.java \
|   31 +  modules/enterprise/server/plugins/alert-irc/src/main/java/org/rhq/enterprise/server/plugins/alertIrc/IrcSender.java \
|   14   modules/enterprise/server/plugins/alert-microblog/src/main/java/org/rhq/enterprise/server/plugins/alertMicroblog/MicroblogSender.java \
|   29 -  modules/enterprise/server/plugins/alert-mobicents/src/main/java/org/rhq/enterprise/server/plugins/alertMobicents/MobicentsSender.java \
|  144 ++++-----  modules/enterprise/server/plugins/alert-operations/src/main/java/org/rhq/enterprise/server/plugins/alertOperations/AlertTokenReplacer.java \
|    4   modules/enterprise/server/plugins/alert-operations/src/main/java/org/rhq/enterprise/server/plugins/alertOperations/OperationsSender.java \
|   15   modules/enterprise/server/plugins/alert-roles/src/main/java/org/rhq/enterprise/server/plugins/alertRoles/RolesSender.java \
|   31 +  modules/enterprise/server/plugins/alert-snmp/src/main/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpSender.java \
|   34 --  modules/enterprise/server/plugins/alert-subject/src/main/java/org/rhq/enterprise/server/plugins/alertSubject/SubjectsSender.java \
|   31 +  21 files changed, 424 insertions(+), 367 deletions(-)

New commits:
commit 894b6792a5f614d63b10703a726a29e4aab603e0
Author: Joseph Marques <joseph at redhat.com>
Date:   Wed Jun 30 03:26:37 2010 -0400

    BZ-602123: BZ-602270: various tweaks for alert notification processing
    
    * never allow any exceptions to bubble up during notification processing
    
    * add new UNKNOWN status for AlertNotificationLogs
    ** use the UNKNOWN state to catching mishaving plugins during alert processing
    
    * add new DEFERRED status for AlertNotificationLogs
    ** use the DEFERRED state or operations
    ** since we don't wait for the operation to complete, we don't know it's \
termination state)  
    * add new PARTIAL status for AlertNotificationLogs
    ** use it to represent mixed success/failures during email sending
    * * do not defer email sending anymore, execute during each notification \
                processing
    ** by processing them all upfront, easier to reason about terminating ResultState

diff --git a/modules/core/dbutils/src/main/scripts/dbsetup/alert-schema.xml \
b/modules/core/dbutils/src/main/scripts/dbsetup/alert-schema.xml index \
                a9ad342..bce92a3 100644
--- a/modules/core/dbutils/src/main/scripts/dbsetup/alert-schema.xml
+++ b/modules/core/dbutils/src/main/scripts/dbsetup/alert-schema.xml
@@ -96,11 +96,9 @@
         <index name="RHQ_ALERT_IDX_ALERT" unique="false">
             <field ref="ALERT_ID"/>
         </index>
-        <column name="SENDER" required="false" size="200" type="VARCHAR2"/>
+        <column name="SENDER" required="false" size="100" type="VARCHAR2"/>
         <column name="RESULT_STATE" required="false" size="20" type="VARCHAR2"/>
         <column name="MESSAGE" required="false" size="4000" type="VARCHAR2"/>
-        <column name="ALL_EMAILS" required="false" size="4000" type="VARCHAR2"/>
-        <column name="EMAILS_FAILED" required="false" size="4000" type="VARCHAR2"/>
     </table>
 
     <table name="RHQ_ALERT_CONDITION_LOG" \
                tablespace="@@@LARGE_TABLESPACE_FOR_DATA@@@"
diff --git a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml \
b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml index \
                daf68f4..7f8f9da 100644
--- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
+++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
@@ -2062,6 +2062,7 @@
             </schemaSpec>
             <schemaSpec version="2.70.1">
                 <schema-addColumn table="RHQ_ALERT_NOTIFICATION" \
column="SENDER_NAME" precision="100" columnType="VARCHAR2" /> +                \
<schema-alterColumn table="RHQ_ALERT_NOTIFICATION" column="SENDER_NAME" \
                nullable="FALSE" />
                 <schema-addColumn table="RHQ_ALERT_NOTIFICATION" \
                column="SENDER_CONFIG_ID" columnType="INTEGER" />
                 <schema-addColumn table="RHQ_ALERT_NOTIFICATION" \
column="EXTRA_CONFIG_ID" columnType="INTEGER" />  <schema-directSQL>
@@ -2082,11 +2083,10 @@
                 </schema-directSQL>
             </schemaSpec>
             <schemaSpec version="2.70.2">
-                <schema-addColumn table="RHQ_ALERT_NOTIF_LOG" column="SENDER" \
columnType="VARCHAR2" precision="200" /> +                <schema-addColumn \
table="RHQ_ALERT_NOTIF_LOG" column="SENDER" columnType="VARCHAR2" precision="100" /> \
+                <schema-alterColumn table="RHQ_ALERT_NOTIF_LOG" column="SENDER" \
                nullable="FALSE" />
                 <schema-addColumn table="RHQ_ALERT_NOTIF_LOG" column="RESULT_STATE" \
                columnType="VARCHAR2" precision="20" />
                 <schema-addColumn table="RHQ_ALERT_NOTIF_LOG" column="MESSAGE" \
                columnType="VARCHAR2" precision="4000" />
-                <schema-addColumn table="RHQ_ALERT_NOTIF_LOG" column="ALL_EMAILS" \
                columnType="VARCHAR2" precision="4000" />
-                <schema-addColumn table="RHQ_ALERT_NOTIF_LOG" column="EMAILS_FAILED" \
columnType="VARCHAR2" precision="4000" />  </schemaSpec>
             <schemaSpec version="2.70.3">
                 <schema-directSQL>
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/alert/notification/AlertNotificationLog.java \
b/modules/core/domain/src/main/java/org/rhq/core/domain/alert/notification/AlertNotificationLog.java
 index 6e25431..de07675 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/alert/notification/AlertNotificationLog.java
                
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/alert/notification/AlertNotificationLog.java
 @@ -23,8 +23,6 @@
 package org.rhq.core.domain.alert.notification;
 
 import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.List;
 
 import javax.persistence.Column;
 import javax.persistence.Entity;
@@ -41,13 +39,11 @@ import javax.persistence.PrePersist;
 import javax.persistence.PreUpdate;
 import javax.persistence.SequenceGenerator;
 import javax.persistence.Table;
-import javax.persistence.Transient;
 import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
 import javax.xml.bind.annotation.XmlTransient;
 
 import org.rhq.core.domain.alert.Alert;
-import org.rhq.core.domain.util.StringUtils;
 
 @Entity
 @NamedQueries( { @NamedQuery(name = \
AlertNotificationLog.QUERY_DELETE_BY_ALERT_CTIME, // @@ -90,23 +86,16 @@ public class \
AlertNotificationLog implements Serializable {  @XmlTransient
     private Alert alert;
 
+    @Column(name = "SENDER")
     private String sender;
 
     @Column(name = "RESULT_STATE")
     @Enumerated(EnumType.STRING)
     private ResultState resultState;
 
+    @Column(name = "MESSAGE")
     private String message;
 
-    @Column(name = "ALL_EMAILS")
-    private String allEmails;
-
-    @Column(name = "EMAILS_FAILED")
-    private String badEmails;
-
-    @Transient
-    transient List<String> transientEmails = new ArrayList<String>();
-
     @PrePersist
     @PreUpdate
     public void trimMessage() {
@@ -122,24 +111,45 @@ public class AlertNotificationLog implements Serializable {
         this.alert = alert;
         this.sender = sender;
         this.resultState = senderResult.getState();
-        this.message = senderResult.getMessage();
-        if (resultState == ResultState.DEFERRED_EMAIL && senderResult.getEmails() != \
                null) {
-            this.transientEmails.addAll(senderResult.getEmails());
-            this.allEmails = StringUtils.getListAsString(senderResult.getEmails(), \
                ",");
-        }
-    }
-
-    public AlertNotificationLog(Alert alert, String sender) {
-        this.alert = alert;
-        this.sender = sender;
-        this.resultState = ResultState.FAILURE; // Default if nothing specified
+        this.message = getMessage(senderResult);
     }
 
     public AlertNotificationLog(Alert alert, String senderName, ResultState state, \
String message) {  this.alert = alert;
+        this.sender = senderName;
         this.resultState = state;
         this.message = message;
+    }
+
+    private String getMessage(SenderResult result) {
+        StringBuilder builder = new StringBuilder();
 
+        boolean first = true;
+
+        if (result.getSummary() != null) {
+            first = false;
+            builder.append(result.getSummary());
+        }
+
+        for (String success : result.getSuccessMessages()) {
+            if (first) {
+                first = false;
+            } else {
+                builder.append("<br/>");
+            }
+            builder.append(success);
+        }
+
+        for (String failure : result.getFailureMessages()) {
+            if (first) {
+                first = false;
+            } else {
+                builder.append("<br/>");
+            }
+            builder.append(failure);
+        }
+
+        return builder.toString();
     }
 
     public int getId() {
@@ -150,10 +160,6 @@ public class AlertNotificationLog implements Serializable {
         return alert;
     }
 
-    public void setAlert(Alert alert) {
-        this.alert = alert;
-    }
-
     public String getSender() {
         return sender;
     }
@@ -166,38 +172,6 @@ public class AlertNotificationLog implements Serializable {
         return message;
     }
 
-    public String getAllEmails() {
-        return allEmails;
-    }
-
-    public String getBadEmails() {
-        return badEmails;
-    }
-
-    public void setResultState(ResultState resultState) {
-        this.resultState = resultState;
-    }
-
-    public void setMessage(String message) {
-        this.message = message;
-    }
-
-    public void setAllEmails(String allEmails) {
-        this.allEmails = allEmails;
-    }
-
-    public void setBadEmails(String badEmails) {
-        this.badEmails = badEmails;
-    }
-
-    public List<String> getTransientEmails() {
-        return transientEmails;
-    }
-
-    public void setTransientEmails(List<String> transientEmails) {
-        this.transientEmails = transientEmails;
-    }
-
     @Override
     public String toString() {
         final StringBuilder sb = new StringBuilder();
@@ -207,8 +181,6 @@ public class AlertNotificationLog implements Serializable {
         sb.append(", sender='").append(sender).append('\'');
         sb.append(", resultState=").append(resultState);
         sb.append(", message='").append(message).append('\'');
-        sb.append(", allEmails='").append(allEmails).append('\'');
-        sb.append(", badEmails='").append(badEmails).append('\'');
         sb.append('}');
         return sb.toString();
     }
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/alert/notification/ResultState.java \
b/modules/core/domain/src/main/java/org/rhq/core/domain/alert/notification/ResultState.java
 index 0c8d1bc..a2de159 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/alert/notification/ResultState.java
                
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/alert/notification/ResultState.java
 @@ -24,12 +24,14 @@ package org.rhq.core.domain.alert.notification;
  * @see SenderResult
  */
 public enum ResultState {
-    /** Success: sending of the notification was a success  */
+    /** Success: sending of the notification was a known success */
     SUCCESS,
-    /** Deferred_email: this sender itself was successful, but l8er email sending \
                may fail */
-    DEFERRED_EMAIL,
-    /** Failure: sending of the notification failed */
+    /** Partial: sending of the notification has some failures */
+    PARTIAL,
+    /** Failure: sending of the notification was a known failure */
     FAILURE,
-    /** Sending one ore more emails from the plugin failed */
-    FAILED_EMAIL
+    /** Deferred: sender action was invoked, but response can not be immediately \
determined */ +    DEFERRED,
+    /** Unknown: alert sender returned a null result */
+    UNKNOWN
 }
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/alert/notification/SenderResult.java \
b/modules/core/domain/src/main/java/org/rhq/core/domain/alert/notification/SenderResult.java
 index b4ec8e1..7191636 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/alert/notification/SenderResult.java
                
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/alert/notification/SenderResult.java
 @@ -27,88 +27,156 @@ import java.util.List;
  */
 public class SenderResult {
 
-    /** Message returned for logging purposes */
-    private String message;
-    /** Was calling the AlertSender.send() method successful? */
-    private ResultState state;
-    /** A list of email addresses that should be notified */
-    private List<String> emails = new ArrayList<String>();
-
-    /**
-     * Default constructor. State is FAILURE by default
+    /*
+     * the state is UNKNOWN by default, but will be determined as messages are \
added.  if only success messages  +     * are added, then the result is considered a \
SUCCESS.  if only failure messages are added, then the result +     * is considered a \
FAILURE.  if a mixed of success and failure messages are added, then the result is \
considered +     * PARTIAL.  the user is free to manually set 
      */
+    private boolean deferred;
+    private String summary; // can be set, will not affect calculated ResultState
+    private List<String> successMessages = new ArrayList<String>();
+    private List<String> failureMessages = new ArrayList<String>();
+
     public SenderResult() {
-        this.message = "No message set";
-        this.state = ResultState.FAILURE;
+        this.deferred = false;
+    }
+
+    public static SenderResult getSimpleSuccess(String message) {
+        SenderResult result = new SenderResult();
+        result.addSuccessMessage(message);
+        return result;
     }
 
-    public SenderResult(ResultState state, String message) {
-        this.message = message;
-        this.state = state;
+    public static SenderResult getSimpleFailure(String message) {
+        SenderResult result = new SenderResult();
+        result.addFailureMessage(message);
+        return result;
     }
 
-    public SenderResult(ResultState state, String message, List<String> emails) {
-        this.message = message;
-        this.state = state;
-        this.emails = emails;
+    public static SenderResult getSimpleDeffered(String message) {
+        SenderResult result = new SenderResult();
+        result.setSummary(message);
+        result.setDeffered();
+        return result;
     }
 
-    public String getMessage() {
-        return message;
+    public void setSummary(String summary) {
+        this.summary = summary;
     }
 
-    public void setMessage(String message) {
-        this.message = message;
+    public String getSummary() {
+        return summary;
     }
 
     public ResultState getState() {
-        return state;
+        if (deferred) {
+            return ResultState.DEFERRED;
+        }
+
+        if (successMessages.size() != 0) {
+            if (failureMessages.size() == 0) {
+                return ResultState.SUCCESS;
+            } else {
+                return ResultState.PARTIAL;
+            }
+        } else {
+            if (failureMessages.size() != 0) {
+                return ResultState.FAILURE;
+            }
+        }
+
+        return ResultState.UNKNOWN;
     }
 
-    public void setState(ResultState state) {
-        this.state = state;
+    public void setDeffered() {
+        deferred = true;
     }
 
-    public List<String> getEmails() {
-        return emails;
+    public void addSuccessMessage(String message) {
+        successMessages.add(message);
     }
 
-    public void setEmails(List<String> emails) {
-        this.emails = emails;
+    public List<String> getSuccessMessages() {
+        return successMessages;
     }
 
-    public void addEmail(String email) {
-        emails.add(email);
+    public void addFailureMessage(String message) {
+        failureMessages.add(message);
+    }
+
+    public List<String> getFailureMessages() {
+        return failureMessages;
     }
 
     @Override
     public String toString() {
         final StringBuilder sb = new StringBuilder();
         sb.append("SenderResult");
-        sb.append("{message='").append(message).append('\'');
-        sb.append(", state=").append(state);
-        sb.append(", emails=").append(emails);
+        sb.append("{state=").append(getState());
+        sb.append(", summary=").append(summary);
+        sb.append(", successMessages=").append(successMessages);
+        sb.append(", failureMessages=").append(failureMessages);
         sb.append('}');
         return sb.toString();
     }
 
     @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        SenderResult that = (SenderResult) o;
-
-        if (message != null ? !message.equals(that.message) : that.message != null) \
                return false;
-        if (state != that.state) return false;
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+
+        if (obj == null) {
+            return false;
+        }
+
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+
+        SenderResult other = (SenderResult) obj;
+
+        if (getState() != other.getState()) {
+            return false;
+        }
+
+        if (summary == null) {
+            if (other.summary != null) {
+                return false;
+            }
+        } else if (!summary.equals(other.summary)) {
+            return false;
+        }
+
+        if (failureMessages == null) {
+            if (other.failureMessages != null) {
+                return false;
+            }
+        } else if (!failureMessages.equals(other.failureMessages)) {
+            return false;
+        }
+
+        if (successMessages == null) {
+            if (other.successMessages != null) {
+                return false;
+            }
+        } else if (!successMessages.equals(other.successMessages)) {
+            return false;
+        }
 
         return true;
     }
 
     @Override
     public int hashCode() {
-        int result = message != null ? message.hashCode() : 0;
-        result = 31 * result + (state != null ? state.hashCode() : 0);
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((summary == null) ? 0 : summary.hashCode());
+        result = prime * result + ((failureMessages == null) ? 0 : \
failureMessages.hashCode()); +        result = prime * result + ((successMessages == \
null) ? 0 : successMessages.hashCode()); +        result = prime * result + \
(getState() != null ? getState().hashCode() : 0);  return result;
     }
+
 }
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/AlertDataSource.java \
b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/AlertDataSource.java
 index de4d5ea..6e5430f 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/AlertDataSource.java
                
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/AlertDataSource.java
 @@ -38,7 +38,6 @@ import com.smartgwt.client.data.fields.DataSourceBooleanField;
 import com.smartgwt.client.data.fields.DataSourceIntegerField;
 import com.smartgwt.client.data.fields.DataSourceTextField;
 import com.smartgwt.client.rpc.RPCResponse;
-import com.smartgwt.client.types.FieldType;
 import com.smartgwt.client.widgets.grid.ListGrid;
 import com.smartgwt.client.widgets.grid.ListGridRecord;
 
@@ -99,13 +98,9 @@ public class AlertDataSource extends RPCDataSource<Alert> {
         resourceName.setCanSortClientOnly(true);
         fields.add(resourceName);
 
-
-//        DataSourceTextField recoveryInfoField = new \
                DataSourceTextField("recoveryInfo", "Recovery Info");
-//        recoveryInfoField.setCanSortClientOnly(true);
-//        fields.add(recoveryInfoField);
-
-
-
+        //        DataSourceTextField recoveryInfoField = new \
DataSourceTextField("recoveryInfo", "Recovery Info"); +        //        \
recoveryInfoField.setCanSortClientOnly(true); +        //        \
fields.add(recoveryInfoField);  
         // TODO: Will using DataSourceEnumField here allow us to do
         //       record.setAttribute("priority", \
alert.getAlertDefinition().getPriority()), rather than @@ -269,8 +264,6 @@ public \
class AlertDataSource extends RPCDataSource<Alert> {  dc.setAttribute("sender", \
log.getSender());  dc.setAttribute("status", log.getResultState());
             dc.setAttribute("message", log.getMessage());
-            dc.setAttribute("allEmails", log.getAllEmails());
-            dc.setAttribute("badEmails", log.getBadEmails());
 
             notifications[i++] = dc;
 
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/resource/common/monitor/alerts/ViewAlertNotifications.jsp \
b/modules/enterprise/gui/portal-war/src/main/webapp/resource/common/monitor/alerts/ViewAlertNotifications.jsp
 index f228d2b..282db80 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/resource/common/monitor/alerts/ViewAlertNotifications.jsp
                
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/resource/common/monitor/alerts/ViewAlertNotifications.jsp
 @@ -15,20 +15,21 @@
     <c:choose>
         <c:when test="${not empty aNotifLogs }">
             <tr>
-                <td class="BlockLeftAlignLabel" width="10%">Sender</td>
-                <td class="BlockLeftAlignLabel" width="10%">Result</td>
-                <td class="BlockLeftAlignLabel" width="30%">Message</td>
-                <td class="BlockLeftAlignLabel" width="25%">All emails</td>
-                <td class="BlockLeftAlignLabel" width="25%">Failed emails</td>
+                <td class="BlockLeftAlignLabel" width="15%">Sender</td>
+                <td class="BlockLeftAlignLabel" width="15%">Result</td>
+                <td class="BlockLeftAlignLabel" width="70%">Message</td>
+            </tr>
+            <tr>
+                <td colspan="3" class="BlockBottomLine"><html:img \
page="/images/spacer.gif" width="1" height="1" border="0"/></td>  </tr>
             <c:forEach var="notif" items="${aNotifLogs}">
                 <tr valign="top">
                     <td class="BlockContent"><c:out value="${notif.sender}"/></td>
                     <td class="BlockContent"><c:out \
                value="${notif.resultState}"/></td>
                     <td class="BlockContent"><c:out escapeXml="false" \
                value="${fn:replace(fn:replace(notif.message, '&lt;', '<'), '&gt;', \
                '>')}"/></td>
-                    <td class="BlockContent"><c:out \
                value="${notif.allEmails}"/></td>
-                    <td class="BlockContent"><c:out \
                value="${notif.badEmails}"/></td>
-                <p/>
+                </tr>
+                <tr>
+                    <td colspan="3" class="BlockBottomLine"><html:img \
page="/images/spacer.gif" width="1" height="1" border="0"/></td>  </tr>
             </c:forEach>
         </c:when>
@@ -37,6 +38,9 @@
                <td class="BlockContent">
                   <strong>No notifications were specified for this alert's \
definition</strong>  </td>
+               <tr>
+                  <td class="BlockBottomLine"><html:img page="/images/spacer.gif" \
width="1" height="1" border="0"/></td> +               </tr>
             </tr>
         </c:otherwise>
     </c:choose>
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertManagerBean.java \
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertManagerBean.java
 index c856a24..108e2d5 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertManagerBean.java
                
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertManagerBean.java
 @@ -27,7 +27,7 @@ import java.util.Arrays;
 import java.util.Collection;
 import java.util.Date;
 import java.util.HashMap;
-import java.util.LinkedHashSet;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -67,7 +67,6 @@ import org.rhq.core.domain.resource.Resource;
 import org.rhq.core.domain.util.PageControl;
 import org.rhq.core.domain.util.PageList;
 import org.rhq.core.domain.util.PageOrdering;
-import org.rhq.core.domain.util.StringUtils;
 import org.rhq.core.server.MeasurementConverter;
 import org.rhq.core.server.PersistenceUtility;
 import org.rhq.core.util.collection.ArrayUtils;
@@ -654,94 +653,48 @@ public class AlertManagerBean implements AlertManagerLocal, \
AlertManagerRemote {  try {
             log.debug("Sending alert notifications for " + alert.toSimpleString() + \
                "...");
             List<AlertNotification> alertNotifications = \
                alert.getAlertDefinition().getAlertNotifications();
-            Set<String> emailAddresses = new LinkedHashSet<String>();
+            //Set<String> emailAddresses = new LinkedHashSet<String>();
 
             AlertSenderPluginManager alertSenderPluginManager = \
getAlertPluginManager();  
             for (AlertNotification alertNotification : alertNotifications) {
+                AlertNotificationLog notificationLog = null;
 
-                // Send over the new AlertSender plugins
                 String senderName = alertNotification.getSenderName();
                 if (senderName == null) {
-                    log.error("Alert notification " + alertNotification + " has no \
                sender name defined");
-                    continue;
-                }
-
-                AlertNotificationLog alNoLo;
-                AlertSender<?> sender = \
                alertSenderPluginManager.getAlertSenderForNotification(alertNotification);
                
-
-                if (sender != null) {
-                    try {
-                        SenderResult result = sender.send(alert);
-
-                        if (result == null) {
-                            log.warn("- !! -- sender [" + senderName
-                                + "] did not return a SenderResult. Please fix this \
                -- !! - ");
-                            alNoLo = new AlertNotificationLog(alert, senderName);
-                            alNoLo.setMessage("Sender did not return a SenderResult, \
assuming failure"); +                    notificationLog = new \
AlertNotificationLog(alert, senderName, ResultState.FAILURE, "Sender '" +             \
+ senderName + "' is not defined"); +                } else {
 
-                        } else if (result.getState() == ResultState.DEFERRED_EMAIL) \
{ +                    AlertSender<?> notificationSender = alertSenderPluginManager
+                        .getAlertSenderForNotification(alertNotification);
+                    if (notificationSender == null) {
+                        notificationLog = new AlertNotificationLog(alert, \
senderName, ResultState.FAILURE, +                            "Failed to obtain a \
sender with given name"); +                    } else {
+                        try {
+                            SenderResult result = notificationSender.send(alert);
+                            if (log.isDebugEnabled()) {
+                                log.debug(result);
+                            }
 
-                            alNoLo = new AlertNotificationLog(alert, senderName, \
                result);
-                            if (result.getEmails() != null && \
                !result.getEmails().isEmpty()) {
-                                emailAddresses.addAll(result.getEmails());
+                            if (result == null) {
+                                notificationLog = new AlertNotificationLog(alert, \
senderName, ResultState.UNKNOWN, +                                    "Sender did not \
return any result"); +                            } else {
+                                notificationLog = new AlertNotificationLog(alert, \
senderName, result);  }
-                        } else {
-                            alNoLo = new AlertNotificationLog(alert, senderName, \
result); +                        } catch (Throwable t) {
+                            log.error("Notification processing terminated abruptly" \
+ t.getMessage()); +                            notificationLog = new \
AlertNotificationLog(alert, senderName, ResultState.FAILURE, +                        \
"Notification processing terminated abruptly, cause: " + t.getMessage());  }
-                        log.debug(result);
-                    } catch (Throwable t) {
-                        log.error("Sender failed: " + t.getMessage());
-                        if (log.isDebugEnabled())
-                            log.debug("Sender " + sender.toString() + "failed: \n", \
                t);
-                        alNoLo = new AlertNotificationLog(alert, senderName, \
                ResultState.FAILURE,
-                            "Failed with exception: " + t.getMessage());
                     }
-                } else {
-                    alNoLo = new AlertNotificationLog(alert, senderName, \
                ResultState.FAILURE,
-                        "Failed to obtain a sender with given name");
                 }
-                entityManager.persist(alNoLo);
-                alert.addAlertNotificatinLog(alNoLo);
-            }
 
-            // send them off
-            Collection<String> badAddresses = null;
-            try {
-                badAddresses = sendAlertNotificationEmails(alert, emailAddresses);
-            } catch (Throwable t) {
-                badAddresses = new ArrayList<String>();
-                log.error("Could not send emails to " + emailAddresses + " for " + \
                alert + ", cause:", t);
-            }
-            // TODO we may do the same for SMS in the future.
-
-            // log those bad addresses to the gui and their individual senders (if \
                possible)
-            if (!badAddresses.isEmpty()) {
-                for (AlertNotificationLog anl : alert.getAlertNotificationLogs()) {
-                    if (!(anl.getResultState() == ResultState.DEFERRED_EMAIL))
-                        continue;
-
-                    List<String> badList = new ArrayList<String>();
-                    for (String badOne : badAddresses) {
-                        if (anl.getTransientEmails().contains(badOne)) {
-                            anl.setResultState(ResultState.FAILED_EMAIL);
-                            badList.add(badOne);
-                        }
-                    }
-                    if (anl.getResultState() == ResultState.FAILED_EMAIL)
-                        anl.setBadEmails(StringUtils.getListAsString(badList, ","));
-                    if (anl.getResultState() == ResultState.DEFERRED_EMAIL && \
                badList.isEmpty())
-                        anl.setResultState(ResultState.SUCCESS);
-                }
-            } else { // No bad addresses
-                // Only set the result state to success for email sending \
                notifications
-                // We must not set them if the notification failed.
-                for (AlertNotificationLog anl : alert.getAlertNotificationLogs()) {
-                    if (anl.getResultState() == ResultState.DEFERRED_EMAIL)
-                        anl.setResultState(ResultState.SUCCESS);
-                }
+                entityManager.persist(notificationLog);
+                alert.addAlertNotificatinLog(notificationLog);
             }
-
         } catch (Throwable t) {
             log.error("Failed to send all notifications for " + \
alert.toSimpleString(), t);  }
@@ -767,35 +720,37 @@ public class AlertManagerBean implements AlertManagerLocal, \
AlertManagerRemote {  return manager;
     }
 
-    /**
-     *
-     * @param alert
-     * @param emailAddresses
-     * @return
-     */
-    private Collection<String> sendAlertNotificationEmails(Alert alert, Set<String> \
emailAddresses) { +    public Collection<String> sendAlertNotificationEmails(Alert \
alert, Collection<String> emailAddresses) { +        log.debug("Sending alert \
notifications for " + alert.toSimpleString() + "...");  
-        if (emailAddresses.size() == 0)
+        if (emailAddresses.size() == 0) {
             return new ArrayList<String>(0); // No email to send -> no bad addresses
-
-        log.debug("Sending alert notifications for " + alert.toSimpleString() + \
"..."); +        }
 
         AlertDefinition alertDefinition = alert.getAlertDefinition();
         Map<String, String> alertMessage = emailManager.getAlertEmailMessage(
-            prettyPrintResourceHierarchy(alertDefinition.getResource()), \
                alertDefinition.getResource().getName(),
-            alertDefinition.getName(), alertDefinition.getPriority().toString(), new \
                Date(alert.getCtime()).toString(),
-            prettyPrintAlertConditions(alert.getConditionLogs(), false), \
prettyPrintAlertURL(alert)); +            \
prettyPrintResourceHierarchy(alertDefinition.getResource()), // +            \
alertDefinition.getResource().getName(), // +            alertDefinition.getName(), \
// +            alertDefinition.getPriority().toString(), //
+            new Date(alert.getCtime()).toString(), //
+            prettyPrintAlertConditions(alert.getConditionLogs(), false), //
+            prettyPrintAlertURL(alert));
+
         String messageSubject = alertMessage.keySet().iterator().next();
         String messageBody = alertMessage.values().iterator().next();
 
-        Collection<String> badAddresses;
-        badAddresses = emailManager.sendEmail(emailAddresses, messageSubject, \
messageBody); +        Set<String> uniqueAddresses = new \
HashSet<String>(emailAddresses); +        Collection<String> badAddresses = \
emailManager.sendEmail(uniqueAddresses, messageSubject, messageBody); +
         if (log.isDebugEnabled()) {
-            if (badAddresses.isEmpty())
+            if (badAddresses.isEmpty()) {
                 log.debug("All notifications for " + alert.toSimpleString() + " \
                succeeded");
-            else
+            } else {
                 log.debug("Sending email notifications for " + badAddresses + " \
failed"); +            }
         }
+
         return badAddresses;
     }
 
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertManagerLocal.java \
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertManagerLocal.java
 index f32c82e..528fdf5 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertManagerLocal.java
                
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertManagerLocal.java
 @@ -18,6 +18,7 @@
  */
 package org.rhq.enterprise.server.alert;
 
+import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 
@@ -109,6 +110,8 @@ public interface AlertManagerLocal {
      */
     boolean willDefinitionBeDisabled(Alert alert);
 
+    Collection<String> sendAlertNotificationEmails(Alert alert, Collection<String> \
emailAddresses); +
     // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
     //
     // The following are shared with the Remote Interface
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/alert/AlertSender.java \
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/alert/AlertSender.java
 index 5a958b1..de35d54 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/alert/AlertSender.java
                
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/alert/AlertSender.java
 @@ -161,4 +161,5 @@ public abstract class AlertSender<T extends \
ServerPluginComponent> {  }
         return builder.toString();
     }
+
 }
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/alert/test/AlertManagerBeanTest.java \
b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/alert/test/AlertManagerBeanTest.java
 index 3d6ab03..79fcb3b 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/alert/test/AlertManagerBeanTest.java
                
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/alert/test/AlertManagerBeanTest.java
 @@ -35,6 +35,7 @@ import org.rhq.core.domain.alert.AlertDefinition;
 import org.rhq.core.domain.alert.AlertPriority;
 import org.rhq.core.domain.alert.BooleanExpression;
 import org.rhq.core.domain.alert.notification.AlertNotificationLog;
+import org.rhq.core.domain.alert.notification.ResultState;
 import org.rhq.core.domain.auth.Subject;
 import org.rhq.core.domain.resource.Agent;
 import org.rhq.core.domain.resource.Resource;
@@ -115,7 +116,7 @@ public class AlertManagerBeanTest extends AbstractEJB3Test {
                 Alert a = new Alert(ad, now);
                 em.persist(a);
 
-                AlertNotificationLog anl = new AlertNotificationLog(a, "dummy");
+                AlertNotificationLog anl = new AlertNotificationLog(a, "dummy", \
ResultState.SUCCESS, "message");  em.persist(anl);
 
             } catch (Exception e) {
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/scheduler/jobs/DataPurgeJobTest.java \
b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/scheduler/jobs/DataPurgeJobTest.java
 index 7f06451..6f6ec38 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/scheduler/jobs/DataPurgeJobTest.java
                
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/scheduler/jobs/DataPurgeJobTest.java
 @@ -49,6 +49,7 @@ import org.rhq.core.domain.alert.AlertDefinition;
 import org.rhq.core.domain.alert.AlertPriority;
 import org.rhq.core.domain.alert.BooleanExpression;
 import org.rhq.core.domain.alert.notification.AlertNotificationLog;
+import org.rhq.core.domain.alert.notification.ResultState;
 import org.rhq.core.domain.auth.Subject;
 import org.rhq.core.domain.event.Event;
 import org.rhq.core.domain.event.EventDefinition;
@@ -427,7 +428,7 @@ public class DataPurgeJobTest extends AbstractEJB3Test {
         Alert a = new Alert(ad, timestamp);
         em.persist(a);
 
-        AlertNotificationLog anl = new AlertNotificationLog(a, "dummy");
+        AlertNotificationLog anl = new AlertNotificationLog(a, "dummy", \
ResultState.SUCCESS, "message");  em.persist(anl);
 
         AlertCondition ac = ad.getConditions().iterator().next();
diff --git a/modules/enterprise/server/plugins/alert-email/src/main/java/org/rhq/enterprise/server/plugins/alertEmail/EmailSender.java \
b/modules/enterprise/server/plugins/alert-email/src/main/java/org/rhq/enterprise/server/plugins/alertEmail/EmailSender.java
 index 81b1383..5b07b7b 100644
--- a/modules/enterprise/server/plugins/alert-email/src/main/java/org/rhq/enterprise/server/plugins/alertEmail/EmailSender.java
                
+++ b/modules/enterprise/server/plugins/alert-email/src/main/java/org/rhq/enterprise/server/plugins/alertEmail/EmailSender.java
 @@ -18,12 +18,16 @@
  */
 package org.rhq.enterprise.server.plugins.alertEmail;
 
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 
 import org.rhq.core.domain.alert.Alert;
-import org.rhq.core.domain.alert.notification.ResultState;
 import org.rhq.core.domain.alert.notification.SenderResult;
 import org.rhq.enterprise.server.plugin.pc.alert.AlertSender;
+import org.rhq.enterprise.server.util.LookupUtil;
 
 /**
  * Class to send emails. Actually it does not do the work
@@ -37,11 +41,32 @@ public class EmailSender extends AlertSender {
     public SenderResult send(Alert alert) {
         String emailAddressString = alertParameters.getSimpleValue("emailAddress", \
null);  if (emailAddressString == null) {
-            return new SenderResult(ResultState.FAILURE, "No email address given");
+            return SenderResult.getSimpleFailure("No email address given");
         }
 
         List<String> emails = AlertSender.unfence(emailAddressString, String.class, \
                ",");
-        return new SenderResult(ResultState.DEFERRED_EMAIL, "Sending to addresses: " \
+ emails, emails); +        try {
+            Set<String> uniqueEmails = new HashSet<String>(emails);
+            Collection<String> badEmails = LookupUtil.getAlertManager()
+                .sendAlertNotificationEmails(alert, uniqueEmails);
+
+            List<String> goodEmails = new ArrayList<String>(uniqueEmails);
+            goodEmails.removeAll(badEmails);
+
+            SenderResult result = new SenderResult();
+            result.setSummary("Target addresses were: " + uniqueEmails);
+            if (goodEmails.size() > 0) {
+                result.addSuccessMessage("Successfully sent to: " + goodEmails);
+            }
+            if (badEmails.size() > 0) {
+                result.addFailureMessage("Failed to send to: " + badEmails);
+            }
+            return result;
+        } catch (Throwable t) {
+            return SenderResult.getSimpleFailure("Error sending email notifications \
to " + emails + ", cause: " +                + t.getMessage());
+        }
+
     }
 
     @Override
diff --git a/modules/enterprise/server/plugins/alert-irc/src/main/java/org/rhq/enterprise/server/plugins/alertIrc/IrcSender.java \
b/modules/enterprise/server/plugins/alert-irc/src/main/java/org/rhq/enterprise/server/plugins/alertIrc/IrcSender.java
 index 95abdb9..d0a48bf 100644
--- a/modules/enterprise/server/plugins/alert-irc/src/main/java/org/rhq/enterprise/server/plugins/alertIrc/IrcSender.java
                
+++ b/modules/enterprise/server/plugins/alert-irc/src/main/java/org/rhq/enterprise/server/plugins/alertIrc/IrcSender.java
 @@ -22,7 +22,6 @@ import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
 import org.rhq.core.domain.alert.Alert;
-import org.rhq.core.domain.alert.notification.ResultState;
 import org.rhq.core.domain.alert.notification.SenderResult;
 import org.rhq.enterprise.server.alert.AlertManagerLocal;
 import org.rhq.enterprise.server.plugin.pc.alert.AlertSender;
@@ -39,20 +38,17 @@ public class IrcSender extends AlertSender<IrcAlertComponent> {
 
     @Override
     public SenderResult send(Alert alert) {
-        SenderResult result;
         String channel = this.alertParameters.getSimpleValue("channel", null);
-        String server = preferences.getSimpleValue("server","-not set-");
+        String server = preferences.getSimpleValue("server", "-not set-");
         String chan = "irc://" + server + "/" + channel;
 
         try {
             this.pluginComponent.sendIrcMessage(channel, getIrcMessage(alert));
-            result = new SenderResult(ResultState.SUCCESS, "IRC Alert sent to \
                channel [" + chan + "].");
-        } catch (IllegalStateException e) {
-            log.error(e.getMessage());
-            result = new SenderResult(ResultState.FAILURE, "IRC Alert to [" + chan + \
"] failed! " + e.getMessage()); +            return \
SenderResult.getSimpleSuccess("IRC Alert sent to channel [" + chan + "]."); +        \
} catch (Throwable t) { +            log.error(t.getMessage());
+            return SenderResult.getSimpleFailure("IRC Alert to [" + chan + "] \
failed! " + t.getMessage());  }
-
-        return result;
     }
 
     private String getIrcMessage(Alert alert) {
diff --git a/modules/enterprise/server/plugins/alert-microblog/src/main/java/org/rhq/enterprise/server/plugins/alertMicroblog/MicroblogSender.java \
b/modules/enterprise/server/plugins/alert-microblog/src/main/java/org/rhq/enterprise/server/plugins/alertMicroblog/MicroblogSender.java
 index b13763e..37f724a 100644
--- a/modules/enterprise/server/plugins/alert-microblog/src/main/java/org/rhq/enterprise/server/plugins/alertMicroblog/MicroblogSender.java
                
+++ b/modules/enterprise/server/plugins/alert-microblog/src/main/java/org/rhq/enterprise/server/plugins/alertMicroblog/MicroblogSender.java
 @@ -18,20 +18,19 @@
  */
 package org.rhq.enterprise.server.plugins.alertMicroblog;
 
-import twitter4j.Status;
-import twitter4j.Twitter;
-import twitter4j.TwitterException;
-
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
 import org.rhq.core.domain.alert.Alert;
-import org.rhq.core.domain.alert.notification.ResultState;
 import org.rhq.core.domain.alert.notification.SenderResult;
 import org.rhq.enterprise.server.alert.AlertManagerLocal;
 import org.rhq.enterprise.server.plugin.pc.alert.AlertSender;
 import org.rhq.enterprise.server.util.LookupUtil;
 
+import twitter4j.Status;
+import twitter4j.Twitter;
+import twitter4j.TwitterException;
+
 /**
  * Send alert notifications via Microblogging services like Twitter or laconi.ca
  * @author Heiko W. Rupp
@@ -43,12 +42,12 @@ public class MicroblogSender extends AlertSender {
     @Override
     public SenderResult send(Alert alert) {
 
-        String user = preferences.getSimpleValue("user",null);
-        String password = preferences.getSimpleValue("password",null);
-        String baseUrl = \
preferences.getSimpleValue("microblogServerUrl","http://twitter.com/"); +        \
String user = preferences.getSimpleValue("user", null); +        String password = \
preferences.getSimpleValue("password", null); +        String baseUrl = \
preferences.getSimpleValue("microblogServerUrl", "http://twitter.com/");  if \
                (!baseUrl.endsWith("/"))
-           baseUrl = baseUrl +"/";
-        Twitter twitter = new Twitter(user,password,baseUrl);
+            baseUrl = baseUrl + "/";
+        Twitter twitter = new Twitter(user, password, baseUrl);
         AlertManagerLocal alertManager = LookupUtil.getAlertManager();
         twitter.setSource("Jopr");
         StringBuilder b = new StringBuilder("Alert ");
@@ -61,22 +60,20 @@ public class MicroblogSender extends AlertSender {
         b.append("-by @JBossJopr"); // TODO not for production :-)
         // TODO use some alert url shortening service
 
-        SenderResult result ;
         String txt = "user at baseUrl [" + user + "@" + baseUrl + "]:";
         try {
             String msg = b.toString();
-            if (msg.length()>140)
-                msg = msg.substring(0,140);
+            if (msg.length() > 140)
+                msg = msg.substring(0, 140);
 
             Status status = twitter.updateStatus(msg);
 
-            result = new SenderResult(ResultState.SUCCESS,"Send notification to " + \
txt + ", msg-id: " + status.getId()); +            return \
SenderResult.getSimpleSuccess("Send notification to " + txt + ", msg-id: " + \
status.getId());  } catch (TwitterException e) {
 
             log.warn("Notification via Microblog failed for " + txt + " ", e);
-            result = new SenderResult(ResultState.FAILURE,"Sending failed :" + \
e.getMessage()); +            return SenderResult.getSimpleFailure("Sending failed :" \
+ e.getMessage());  
         }
-        return result;
     }
 }
diff --git a/modules/enterprise/server/plugins/alert-mobicents/src/main/java/org/rhq/enterprise/server/plugins/alertMobicents/MobicentsSender.java \
b/modules/enterprise/server/plugins/alert-mobicents/src/main/java/org/rhq/enterprise/server/plugins/alertMobicents/MobicentsSender.java
 index b14c85d..4884e3a 100644
--- a/modules/enterprise/server/plugins/alert-mobicents/src/main/java/org/rhq/enterprise/server/plugins/alertMobicents/MobicentsSender.java
                
+++ b/modules/enterprise/server/plugins/alert-mobicents/src/main/java/org/rhq/enterprise/server/plugins/alertMobicents/MobicentsSender.java
 @@ -28,7 +28,6 @@ import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
 import org.rhq.core.domain.alert.Alert;
-import org.rhq.core.domain.alert.notification.ResultState;
 import org.rhq.core.domain.alert.notification.SenderResult;
 import org.rhq.core.domain.resource.Resource;
 import org.rhq.enterprise.server.alert.AlertManagerLocal;
@@ -46,13 +45,13 @@ public class MobicentsSender extends AlertSender {
     @Override
     public SenderResult send(Alert alert) {
 
-        String baseUrl = \
                preferences.getSimpleValue("mobicentsServerUrl","http://localhost:8080/mobicents");
                
-        String tel = alertParameters.getSimpleValue("targetAddress",null);
-        if (tel==null) {
+        String baseUrl = preferences.getSimpleValue("mobicentsServerUrl", \
"http://localhost:8080/mobicents"); +        String tel = \
alertParameters.getSimpleValue("targetAddress", null); +        if (tel == null) {
             log.warn("No number to call given, not sending");
-            return new SenderResult(ResultState.FAILURE, "No target address given");
+            return SenderResult.getSimpleFailure("No target address given");
         }
-        String kindString = alertParameters.getSimpleValue("kind","VOICE");
+        String kindString = alertParameters.getSimpleValue("kind", "VOICE");
         MobiKind kind = MobiKind.valueOf(kindString);
 
         Integer alertId = alert.getId();
@@ -61,81 +60,81 @@ public class MobicentsSender extends AlertSender {
         AlertManagerLocal alertManager = LookupUtil.getAlertManager();
 
         switch (kind) {
-            case VOICE:
-                b.append("Alert on resource ");
-                do {
-                    b.append(res.getName());
-                    res = res.getParentResource();
-                    if (res!=null)
-                        b.append(" with parent ");
-                } while (res!=null);
-                b.append(". Cause is ");
-
-                // Switch locale to english, as the voice synthesizer expects this \
                for now
-                Locale currentLocale = Locale.getDefault();
-                Locale.setDefault(Locale.ENGLISH);
-                b.append(alertManager.prettyPrintAlertConditions(alert, false));
-                Locale.setDefault(currentLocale);
-
-                boolean willBeDisabled = \
                alertManager.willDefinitionBeDisabled(alert);
-
-                if (willBeDisabled)
-                    b.append(" The alert definition will now be disabled. \n\n");
-
-    //            b.append(" Please press ");
-    //
-    //            if (willBeDisabled) {
-    //                b.append(AlertFeedback.REENABLE.getText());
-    //            } else {
-    //                b.append(AlertFeedback.DISABLE.getText());
-    //            }
-    //            b.append(", ");
-    //            b.append(AlertFeedback.DELETE.getText());
-    //            b.append(" or just hang up to do nothing.");
-                break;
-            case SMS:
-                b.append("Alert: ");
+        case VOICE:
+            b.append("Alert on resource ");
+            do {
                 b.append(res.getName());
-                b.append(",id=(").append(res.getId()).append(")");
-                b.append("Brought by RHQ");
-                break;
-            default:
-                log.warn("Unsupported Mobicents notification type for now");
+                res = res.getParentResource();
+                if (res != null)
+                    b.append(" with parent ");
+            } while (res != null);
+            b.append(". Cause is ");
+
+            // Switch locale to english, as the voice synthesizer expects this for \
now +            Locale currentLocale = Locale.getDefault();
+            Locale.setDefault(Locale.ENGLISH);
+            b.append(alertManager.prettyPrintAlertConditions(alert, false));
+            Locale.setDefault(currentLocale);
+
+            boolean willBeDisabled = alertManager.willDefinitionBeDisabled(alert);
+
+            if (willBeDisabled)
+                b.append(" The alert definition will now be disabled. \n\n");
+
+            //            b.append(" Please press ");
+            //
+            //            if (willBeDisabled) {
+            //                b.append(AlertFeedback.REENABLE.getText());
+            //            } else {
+            //                b.append(AlertFeedback.DISABLE.getText());
+            //            }
+            //            b.append(", ");
+            //            b.append(AlertFeedback.DELETE.getText());
+            //            b.append(" or just hang up to do nothing.");
+            break;
+        case SMS:
+            b.append("Alert: ");
+            b.append(res.getName());
+            b.append(",id=(").append(res.getId()).append(")");
+            b.append("Brought by RHQ");
+            break;
+        default:
+            log.warn("Unsupported Mobicents notification type for now");
         }
 
         URL url;
-        int code=0;
+        int code = 0;
         HttpURLConnection conn = null;
         try {
             tel = tel.trim();
-            String telEnc = URLEncoder.encode(tel,"UTF-8"); // url encode tel-no, as \
it can contain '+' +            String telEnc = URLEncoder.encode(tel, "UTF-8"); // \
url encode tel-no, as it can contain '+'  switch (kind) {
-                case SMS:
-                    baseUrl = baseUrl + "sms"; // No trailing '/' !
-                    break;
-                case VOICE:
-                    baseUrl = baseUrl + "call"; // No trailing '/' !
-                    break;
-                default:
-                    baseUrl = baseUrl + "--not-supported-yet--";
+            case SMS:
+                baseUrl = baseUrl + "sms"; // No trailing '/' !
+                break;
+            case VOICE:
+                baseUrl = baseUrl + "call"; // No trailing '/' !
+                break;
+            default:
+                baseUrl = baseUrl + "--not-supported-yet--";
             }
-            baseUrl = baseUrl +"?alertId="+alertId;
-            baseUrl = baseUrl +"&tel=";
-            if (kind==MobiKind.VOICE) {
+            baseUrl = baseUrl + "?alertId=" + alertId;
+            baseUrl = baseUrl + "&tel=";
+            if (kind == MobiKind.VOICE) {
                 if (!tel.startsWith("sip:")) {
-                    baseUrl = baseUrl +"sip:";
+                    baseUrl = baseUrl + "sip:";
                 }
             }
-            baseUrl = baseUrl +telEnc;
-            if (kind==MobiKind.VOICE) {
+            baseUrl = baseUrl + telEnc;
+            if (kind == MobiKind.VOICE) {
                 if (!tel.contains("@")) { // Append domain from preferences if user \
                has none provided
-                    String domain = \
preferences.getSimpleValue("defaultVoipDomain","localhost"); +                    \
String domain = preferences.getSimpleValue("defaultVoipDomain", "localhost");  \
baseUrl = baseUrl + "@" + domain;  }
             }
             // TODO SMS url
 
-            log.info("Mobicents alert ["+ kind + "] to baseUrl [" + baseUrl + "] \
with message:\n" + b.toString()); +            log.info("Mobicents alert [" + kind + \
"] to baseUrl [" + baseUrl + "] with message:\n" + b.toString());  url = new \
URL(baseUrl);  conn = (HttpURLConnection) url.openConnection();
             conn.setRequestMethod("POST");
@@ -151,20 +150,17 @@ public class MobicentsSender extends AlertSender {
             code = conn.getResponseCode();
         } catch (Exception e) {
             log.warn("Notification via VoIP failed: " + e);
-            return new SenderResult(ResultState.FAILURE,"Sending failed " + \
                e.getMessage());
-        }
-        finally {
-            if (conn!=null)
+            return SenderResult.getSimpleFailure("Sending failed " + \
e.getMessage()); +        } finally {
+            if (conn != null)
                 conn.disconnect();
         }
-        SenderResult result;
-        if (code!=200) {
+
+        if (code != 200) {
             log.info("Notification via Mobicents returned code " + code);
-            result=new SenderResult(ResultState.FAILURE,"Notification via Mobicents \
                returned code " + code);
-        }
-        else {
-            result=new SenderResult(ResultState.SUCCESS,"Mobicents alert ["+ kind + \
"] to baseUrl [" + baseUrl + "]" ); +            return \
SenderResult.getSimpleFailure("Notification via Mobicents returned code " + code); +  \
} else { +            return SenderResult.getSimpleSuccess("Mobicents alert [" + kind \
+ "] to baseUrl [" + baseUrl + "]");  }
-        return result;
     }
 }
diff --git a/modules/enterprise/server/plugins/alert-operations/src/main/java/org/rhq/enterprise/server/plugins/alertOperations/AlertTokenReplacer.java \
b/modules/enterprise/server/plugins/alert-operations/src/main/java/org/rhq/enterprise/server/plugins/alertOperations/AlertTokenReplacer.java
 index 21c3bfe..cdf03ac 100644
--- a/modules/enterprise/server/plugins/alert-operations/src/main/java/org/rhq/enterprise/server/plugins/alertOperations/AlertTokenReplacer.java
                
+++ b/modules/enterprise/server/plugins/alert-operations/src/main/java/org/rhq/enterprise/server/plugins/alertOperations/AlertTokenReplacer.java
 @@ -67,7 +67,9 @@ public class AlertTokenReplacer {
         String work = input;
         Matcher matcher = pattern.matcher(work);
         if (!matcher.find()) {
-            log.warn("No tokens found in " + input);
+            if (log.isDebugEnabled()) {
+                log.debug("No tokens found in " + input);
+            }
             return input;
         }
         matcher.reset();
diff --git a/modules/enterprise/server/plugins/alert-operations/src/main/java/org/rhq/enterprise/server/plugins/alertOperations/OperationsSender.java \
b/modules/enterprise/server/plugins/alert-operations/src/main/java/org/rhq/enterprise/server/plugins/alertOperations/OperationsSender.java
 index 83563e6..e50b143 100644
--- a/modules/enterprise/server/plugins/alert-operations/src/main/java/org/rhq/enterprise/server/plugins/alertOperations/OperationsSender.java
                
+++ b/modules/enterprise/server/plugins/alert-operations/src/main/java/org/rhq/enterprise/server/plugins/alertOperations/OperationsSender.java
 @@ -19,7 +19,6 @@
 package org.rhq.enterprise.server.plugins.alertOperations;
 
 import org.rhq.core.domain.alert.Alert;
-import org.rhq.core.domain.alert.notification.ResultState;
 import org.rhq.core.domain.alert.notification.SenderResult;
 import org.rhq.core.domain.auth.Subject;
 import org.rhq.core.domain.configuration.Configuration;
@@ -47,7 +46,7 @@ public class OperationsSender extends AlertSender {
 
         OperationInfo info = OperationInfo.load(alertParameters, extraParameters);
         if (info.error != null) {
-            return new SenderResult(ResultState.FAILURE, info.error);
+            return SenderResult.getSimpleFailure(info.error);
         }
 
         Subject subject = LookupUtil.getSubjectManager().getOverlord(); // TODO get \
real subject for authz? @@ -61,7 +60,7 @@ public class OperationsSender extends \
AlertSender {  } catch (Throwable t) {
             String message = getResultMessage(info, "could not calculate which \
resources to execute the operation on: "  + t.getMessage());
-            return new SenderResult(ResultState.FAILURE, message);
+            return SenderResult.getSimpleFailure(message);
         }
 
         Configuration replacedParameters = null;
@@ -79,7 +78,7 @@ public class OperationsSender extends AlertSender {
             }
         } catch (Exception e) {
             String message = getResultMessage(info, "parameterized argument \
                replacement failed with " + e.getMessage());
-            return new SenderResult(ResultState.FAILURE, message);
+            return SenderResult.getSimpleFailure(message);
         }
 
         // Now fire off the operation with no delay and no repetition.
@@ -89,13 +88,17 @@ public class OperationsSender extends AlertSender {
                 targetResource.getId(), operation.getName(), 0, 0, 0, 0, \
                replacedParameters, description);
             String message = getResultMessage(info, \
getHyperLinkForOperationSchedule(subject, targetResource.getId(),  \
                operation.getName(), schedule.getJobId()));
-            return new SenderResult(ResultState.SUCCESS, message);
+            return SenderResult.getSimpleDeffered(message);
         } catch (Throwable t) {
             String message = getResultMessage(info, "invocation failed with " + \
                t.getMessage());
-            return new SenderResult(ResultState.FAILURE, message);
+            return SenderResult.getSimpleFailure(message);
         }
     }
 
+    /* 
+     * if we actually execute the operation at the time of alert sending, we can \
report the +     * operation's failure/success accurately instead of just returning a \
"deferred" result +     */
     private String getHyperLinkForOperationSchedule(Subject subject, int resourceId, \
String operationName, JobId jobId) {  /*
         OperationManagerLocal operationManager = LookupUtil.getOperationManager();
diff --git a/modules/enterprise/server/plugins/alert-roles/src/main/java/org/rhq/enterprise/server/plugins/alertRoles/RolesSender.java \
b/modules/enterprise/server/plugins/alert-roles/src/main/java/org/rhq/enterprise/server/plugins/alertRoles/RolesSender.java
 index 2846266..35b558e 100644
--- a/modules/enterprise/server/plugins/alert-roles/src/main/java/org/rhq/enterprise/server/plugins/alertRoles/RolesSender.java
                
+++ b/modules/enterprise/server/plugins/alert-roles/src/main/java/org/rhq/enterprise/server/plugins/alertRoles/RolesSender.java
 @@ -19,10 +19,12 @@
 package org.rhq.enterprise.server.plugins.alertRoles;
 
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 
 import org.rhq.core.domain.alert.Alert;
-import org.rhq.core.domain.alert.notification.ResultState;
 import org.rhq.core.domain.alert.notification.SenderResult;
 import org.rhq.core.domain.auth.Subject;
 import org.rhq.core.domain.authz.Role;
@@ -45,12 +47,33 @@ public class RolesSender extends AlertSender {
     public SenderResult send(Alert alert) {
         List<Integer> roleIds = getRoleIdsFromConfiguration();
         if (roleIds == null) {
-            return new SenderResult(ResultState.FAILURE, "No roles defined");
+            return SenderResult.getSimpleFailure("No roles defined");
         }
 
-        List<String> emails = getRoleEmails(roleIds);
         List<String> names = getRoleNames(roleIds);
-        return new SenderResult(ResultState.DEFERRED_EMAIL, "Sending to roles: " + \
names, emails); +        List<String> emails = getRoleEmails(roleIds);
+
+        try {
+            Set<String> uniqueEmails = new HashSet<String>(emails);
+            Collection<String> badEmails = LookupUtil.getAlertManager()
+                .sendAlertNotificationEmails(alert, uniqueEmails);
+
+            List<String> goodEmails = new ArrayList<String>(uniqueEmails);
+            goodEmails.removeAll(badEmails);
+
+            SenderResult result = new SenderResult();
+            result.setSummary("Target roles were: " + names);
+            if (goodEmails.size() > 0) {
+                result.addSuccessMessage("Successfully sent to: " + goodEmails);
+            }
+            if (badEmails.size() > 0) {
+                result.addFailureMessage("Failed to send to: " + badEmails);
+            }
+            return result;
+        } catch (Throwable t) {
+            return SenderResult.getSimpleFailure("Error sending role notifications \
to " + names + ", cause: " +                + t.getMessage());
+        }
     }
 
     @Override
diff --git a/modules/enterprise/server/plugins/alert-snmp/src/main/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpSender.java \
b/modules/enterprise/server/plugins/alert-snmp/src/main/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpSender.java
 index 1639e81..627e23d 100644
--- a/modules/enterprise/server/plugins/alert-snmp/src/main/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpSender.java
                
+++ b/modules/enterprise/server/plugins/alert-snmp/src/main/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpSender.java
 @@ -25,7 +25,6 @@ import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
 import org.rhq.core.domain.alert.Alert;
-import org.rhq.core.domain.alert.notification.ResultState;
 import org.rhq.core.domain.alert.notification.SenderResult;
 import org.rhq.core.domain.resource.Resource;
 import org.rhq.enterprise.server.alert.AlertManagerLocal;
@@ -46,34 +45,29 @@ public class SnmpSender extends AlertSender {
 
         SnmpInfo info = SnmpInfo.load(alertParameters);
         if (info.error != null) {
-            return new SenderResult(ResultState.FAILURE, info.error);
+            return SenderResult.getSimpleFailure(info.error);
         }
         log.debug("Sending SNMP trap to: " + info);
 
-        AlertManagerLocal alertManager = LookupUtil.getAlertManager();
-        ResourceManagerLocal resourceManager = LookupUtil.getResourceManager();
+        try {
+            AlertManagerLocal alertManager = LookupUtil.getAlertManager();
+            ResourceManagerLocal resourceManager = LookupUtil.getResourceManager();
 
-        SnmpTrapSender snmpTrapSender = new SnmpTrapSender(preferences);
+            SnmpTrapSender snmpTrapSender = new SnmpTrapSender(preferences);
 
-        List<Resource> lineage = \
                resourceManager.getResourceLineage(alert.getAlertDefinition().getResource().getId());
                
-        String platformName = lineage.get(0).getName();
-        String conditions = alertManager.prettyPrintAlertConditions(alert, false);
-        String alertUrl = alertManager.prettyPrintAlertURL(alert);
+            List<Resource> lineage = \
resourceManager.getResourceLineage(alert.getAlertDefinition().getResource() +         \
.getId()); +            String platformName = lineage.get(0).getName();
+            String conditions = alertManager.prettyPrintAlertConditions(alert, \
false); +            String alertUrl = alertManager.prettyPrintAlertURL(alert);
 
-        String result;
-        SenderResult res;
-        try {
             Date bootTime = new Date(); // TODO: want to use \
                LookupUtil.getCoreServer().getBootTime() but ServiceMBean is not \
                visible
-            result = snmpTrapSender.sendSnmpTrap(alert, alertParameters, \
                platformName, conditions, bootTime, alertUrl);
-            res = new SenderResult(ResultState.SUCCESS, result);
+            String result = snmpTrapSender.sendSnmpTrap(alert, alertParameters, \
platformName, conditions, bootTime, +                alertUrl);
+            return SenderResult.getSimpleSuccess(result);
         } catch (Throwable t) {
-            result = "failed - cause: " + t;
-            res = new SenderResult(ResultState.FAILURE, result);
+            return SenderResult.getSimpleFailure("failed - cause: " + t);
         }
-
-        log.debug("Result of sending SNMP trap: " + result);
-
-        return res;
     }
 
     @Override
diff --git a/modules/enterprise/server/plugins/alert-subject/src/main/java/org/rhq/enterprise/server/plugins/alertSubject/SubjectsSender.java \
b/modules/enterprise/server/plugins/alert-subject/src/main/java/org/rhq/enterprise/server/plugins/alertSubject/SubjectsSender.java
 index 13f4f32..201e13f 100644
--- a/modules/enterprise/server/plugins/alert-subject/src/main/java/org/rhq/enterprise/server/plugins/alertSubject/SubjectsSender.java
                
+++ b/modules/enterprise/server/plugins/alert-subject/src/main/java/org/rhq/enterprise/server/plugins/alertSubject/SubjectsSender.java
 @@ -19,10 +19,12 @@
 package org.rhq.enterprise.server.plugins.alertSubject;
 
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 
 import org.rhq.core.domain.alert.Alert;
-import org.rhq.core.domain.alert.notification.ResultState;
 import org.rhq.core.domain.alert.notification.SenderResult;
 import org.rhq.core.domain.auth.Subject;
 import org.rhq.core.domain.configuration.PropertySimple;
@@ -44,12 +46,33 @@ public class SubjectsSender extends AlertSender {
     public SenderResult send(Alert alert) {
         List<Integer> subjectIds = getSubjectIdsFromConfiguration();
         if (subjectIds == null) {
-            return new SenderResult(ResultState.FAILURE, "No subjects defined");
+            return SenderResult.getSimpleFailure("No subjects defined");
         }
 
-        List<String> emails = getSubjectEmails(subjectIds);
         List<String> names = getSubjectNames(subjectIds);
-        return new SenderResult(ResultState.DEFERRED_EMAIL, "Sending to subjects: " \
+ names, emails); +        List<String> emails = getSubjectEmails(subjectIds);
+
+        try {
+            Set<String> uniqueEmails = new HashSet<String>(emails);
+            Collection<String> badEmails = LookupUtil.getAlertManager()
+                .sendAlertNotificationEmails(alert, uniqueEmails);
+
+            List<String> goodEmails = new ArrayList<String>(uniqueEmails);
+            goodEmails.removeAll(badEmails);
+
+            SenderResult result = new SenderResult();
+            result.setSummary("Target subjects were: " + names);
+            if (goodEmails.size() > 0) {
+                result.addSuccessMessage("Successfully sent to: " + goodEmails);
+            }
+            if (badEmails.size() > 0) {
+                result.addFailureMessage("Failed to send to: " + badEmails);
+            }
+            return result;
+        } catch (Throwable t) {
+            return SenderResult.getSimpleFailure("Error sending subject \
notifications to " + names + ", cause: " +                + t.getMessage());
+        }
     }
 
     @Override


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic