From: <ga...@us...> - 2009-11-14 05:20:58
|
Revision: 4242 http://jaffa.svn.sourceforge.net/jaffa/?rev=4242&view=rev Author: gautamj Date: 2009-11-14 05:20:49 +0000 (Sat, 14 Nov 2009) Log Message: ----------- Enhanced the MessageBean to send failure notifications, if a queue is so configured. Modified Paths: -------------- trunk/JaffaCore/source/java/org/jaffa/util/EmailerBean.java trunk/JaffaCore/source/java/org/jaffa/util/ExceptionHelper.java trunk/JaffaSOA/source/java/org/jaffa/modules/messaging/ApplicationResources.pfragment trunk/JaffaSOA/source/java/org/jaffa/modules/messaging/services/JaffaMessageBean.java Modified: trunk/JaffaCore/source/java/org/jaffa/util/EmailerBean.java =================================================================== --- trunk/JaffaCore/source/java/org/jaffa/util/EmailerBean.java 2009-11-13 19:31:41 UTC (rev 4241) +++ trunk/JaffaCore/source/java/org/jaffa/util/EmailerBean.java 2009-11-14 05:20:49 UTC (rev 4242) @@ -50,6 +50,8 @@ package org.jaffa.util; import java.io.StringWriter; +import java.util.Map; +import javax.mail.BodyPart; import javax.mail.MessagingException; import org.apache.log4j.Logger; import org.apache.velocity.VelocityContext; @@ -227,10 +229,22 @@ */ public void sendMailTemplate(String from, String[] to, String subject, String bodyText, Object data) throws MessagingException { + sendMailTemplate(from, to, subject, bodyText, data, null); + } + + /** Sends an email from a specified "from address" + * @param from from email ie pa...@ya... + * @param to (REQUIRED) array of strings to send email to ie bo...@ya... + * @param subject Text for the email subject (defaults to 'No Subject' if null) + * @param bodyText Text for the main mail's body + * @throws MessagingException Contains error if message could not be sent + */ + public void sendMailTemplate(String from, String[] to, String subject, String bodyText, Object data, BodyPart[] attachments) + throws MessagingException { subject = processTemplate(subject,data); bodyText = processTemplate(bodyText,data); EmailHelper.emailAttachments(getSmtpHost(), getSmtpLocalHost(), getSmtpUser(), getSmtpPassword(), - from!=null?from:administrator, to, subject, bodyText, null); + from!=null?from:administrator, to, subject, bodyText, attachments); } @@ -244,9 +258,15 @@ if(template==null) return ""; VelocityContext context = new VelocityContext(); - if(data!=null) - context.put("data", data); - else + if(data!=null) { + if (data instanceof Map) { + for (Object key : ((Map) data).keySet()) { + if (key instanceof String) + context.put((String) key, ((Map) data).get(key)); + } + } else + context.put("data", data); + } else log.warn("Main Context Data Object is null"); context.put("context", ContextManagerFactory.instance().getThreadContext()); StringWriter output = new StringWriter(); Modified: trunk/JaffaCore/source/java/org/jaffa/util/ExceptionHelper.java =================================================================== --- trunk/JaffaCore/source/java/org/jaffa/util/ExceptionHelper.java 2009-11-13 19:31:41 UTC (rev 4241) +++ trunk/JaffaCore/source/java/org/jaffa/util/ExceptionHelper.java 2009-11-14 05:20:49 UTC (rev 4242) @@ -49,6 +49,8 @@ package org.jaffa.util; +import java.io.PrintWriter; +import java.io.StringWriter; import org.apache.log4j.Logger; import org.jaffa.exceptions.ApplicationException; import org.jaffa.exceptions.ApplicationExceptions; @@ -141,5 +143,16 @@ throwAF(exception); return exception instanceof RuntimeException ? (RuntimeException) exception : new RuntimeException(null, exception); } - + + /** + * Returns the stacktrace of the input exception as a String. + * @param exception an exception. + * @return the stacktrace of the input exception as a String. + */ + public static String getStackTrace(Throwable exception) { + StringWriter sw = new StringWriter(); + exception.printStackTrace(new PrintWriter(sw)); + sw.flush(); + return sw.toString(); + } } Modified: trunk/JaffaSOA/source/java/org/jaffa/modules/messaging/ApplicationResources.pfragment =================================================================== --- trunk/JaffaSOA/source/java/org/jaffa/modules/messaging/ApplicationResources.pfragment 2009-11-13 19:31:41 UTC (rev 4241) +++ trunk/JaffaSOA/source/java/org/jaffa/modules/messaging/ApplicationResources.pfragment 2009-11-14 05:20:49 UTC (rev 4242) @@ -46,3 +46,6 @@ label.Jaffa.Messaging.BusinessEventLog.SourceMethod=Source Method label.Jaffa.Messaging.BusinessEventLog.SourceLine=Source Line label.Jaffa.Messaging.BusinessEventLog.StackTrace=Stack Trace + +email.subject.messaging.failureNotification=Failure notification for queue ${queue} +email.body.messaging.failureNotification=<html>There was a failure in processing a Message in the queue ${queue}#if($exception.localizedMessage != "")<br><b><pre>${exception.localizedMessage}</pre></b>#end <p>Check <a href='${appUrl}/startComponent.do?component=Jaffa.Messaging.QueueViewer&messageMode=ERROR&queue=${queue}'/>Error Queue</a> and <a href='${appUrl}/startComponent.do?component=Jaffa.Messaging.MessageViewer&messageMode=ERROR&queue=${queue}&JMSMessageID=${message.JMSMessageID}'/>Message Details</a></html> Modified: trunk/JaffaSOA/source/java/org/jaffa/modules/messaging/services/JaffaMessageBean.java =================================================================== --- trunk/JaffaSOA/source/java/org/jaffa/modules/messaging/services/JaffaMessageBean.java 2009-11-13 19:31:41 UTC (rev 4241) +++ trunk/JaffaSOA/source/java/org/jaffa/modules/messaging/services/JaffaMessageBean.java 2009-11-14 05:20:49 UTC (rev 4242) @@ -51,7 +51,9 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import java.util.HashMap; import java.util.Iterator; +import java.util.Map; import javax.ejb.MessageDrivenBean; import javax.ejb.MessageDrivenContext; import javax.jms.Connection; @@ -60,6 +62,9 @@ import javax.jms.MessageListener; import javax.jms.Session; import javax.jms.TextMessage; +import javax.mail.BodyPart; +import javax.mail.MessagingException; +import javax.mail.internet.MimeBodyPart; import org.apache.log4j.Logger; import org.jaffa.exceptions.ApplicationException; import org.jaffa.exceptions.ApplicationExceptions; @@ -68,6 +73,8 @@ import org.jaffa.modules.user.services.UserContextWrapper; import org.jaffa.modules.user.services.UserContextWrapperFactory; import org.jaffa.presentation.portlet.session.UserSessionSetupException; +import org.jaffa.session.ContextManagerFactory; +import org.jaffa.util.EmailerBean; import org.jaffa.util.ExceptionHelper; import org.jaffa.util.MessageHelper; import org.jaffa.util.JAXBHelper; @@ -77,6 +84,9 @@ public class JaffaMessageBean implements MessageDrivenBean, MessageListener { private static final Logger log = Logger.getLogger(JaffaMessageBean.class); + private static final String RULE_FAILURE_NOTIFICATION_PREFIX = "jaffa.messaging.failureNotification."; + private static final String EMAIL_SUBJECT_NOTIFICATION = "email.subject.messaging.failureNotification"; + private static final String EMAIL_BODY_NOTIFICATION = "email.body.messaging.failureNotification"; private MessageDrivenContext m_context; /** Standard EBJ method. @@ -200,7 +210,7 @@ if (messageInfo.getQueueName() != null) { // Redirect to ErrorQueue, if the original message was passed. Else rethrow the exception if (aMessage != null) - handleException(aMessage, e); + handleException(aMessage, payload, e); else throw ExceptionHelper.throwAFR(e); } @@ -317,9 +327,10 @@ * A RuntimeException is thrown in case an error is thrown while redirecting the Message to the ErrorQueue. * * @param aMessage the Message. + * @param payload Any serializable object. * @param e the error that was thrown while consuming the message. */ - private static void handleException(Message aMessage, Exception e) { + private static void handleException(Message aMessage, Object payload, Exception e) { Session session = null; try { if (log.isInfoEnabled()) @@ -366,8 +377,10 @@ newMessage.setObjectProperty(JmsBrowser.HEADER_ERROR_DETAILS, errorMessage); // Writes the cloned Message to the errorQueue - JmsClientHelper.send(session, newMessage, JmsBrowser. - getErrorQueueName()); + JmsClientHelper.send(session, newMessage, JmsBrowser.getErrorQueueName()); + + // send a failure notification, if configured + sendFailureNotification(newMessage, payload, e); } catch (Exception e1) { log.error(MessageHelper.findMessage("error.Jaffa.Messaging.JaffaMessageBean.redirectError", null), e1); throw new RuntimeException("Exception thrown while redirecting the Message to the ErrorQueue", e1); @@ -381,4 +394,59 @@ } } } + + /** + * Constructs an email with error information, provided the application + * rule 'jaffa.messaging.failureNotification.{queuename}' is defined. + */ + private static void sendFailureNotification(Message aMessage, Object payload, Exception e) throws JMSException, MessagingException { + String queueName = aMessage.getStringProperty(JmsBrowser.HEADER_ORIGINAL_QUEUE_NAME); + String ruleName = RULE_FAILURE_NOTIFICATION_PREFIX + queueName; + String ruleValue = (String) ContextManagerFactory.instance().getProperty(ruleName); + if (ruleValue != null && ruleValue.length() > 0) { + // the rule value is expected to be a semicolon-separated list of email-addresses + String[] to = ruleValue.split(";"); + String token = EMAIL_SUBJECT_NOTIFICATION + '.' + payload.getClass().getName(); + + // obtain the template for the subject + String subject = MessageHelper.findMessage(token, null); + if (subject == null || subject.length() == 0 || subject.startsWith("???")) { + if (log.isDebugEnabled()) + log.debug("Entry '" + token + "' not found in the resource bundle for generating the subject of the failure notification. Will use the generic subject."); + subject = MessageHelper.findMessage(EMAIL_SUBJECT_NOTIFICATION, null); + } + + // obtain the template for the body + token = EMAIL_BODY_NOTIFICATION + '.' + payload.getClass().getName(); + String body = MessageHelper.findMessage(token, null); + if (body == null || body.length() == 0 || body.startsWith("???")) { + if (log.isDebugEnabled()) + log.debug("Entry '" + token + "' not found in the resource bundle for generating the body of the failure notification. Will use the generic body."); + body = MessageHelper.findMessage(EMAIL_BODY_NOTIFICATION, null); + } + + // create the context for the template + Map context = new HashMap(); + context.put("message", aMessage); + context.put("bean", payload); + context.put("exception", e); + context.put("queue", queueName); + context.put("context", ContextManagerFactory.instance().getThreadContext()); + context.put("appUrl", ContextManagerFactory.instance().getProperty("app.url")); + + // transform the stacktrace into an attachment + BodyPart attachment = new MimeBodyPart(); + attachment.setContent(ExceptionHelper.getStackTrace(e), "text/plain"); + attachment.setFileName("stacktrace.txt"); + + // send the failure notification + if (log.isDebugEnabled()) + log.debug("Sending failure notification to " + ruleValue); + EmailerBean eb = new EmailerBean(); + eb.sendMailTemplate(null, to, subject, body, context, new BodyPart[]{attachment}); + } else { + if (log.isDebugEnabled()) + log.debug("Failure Notification will not be sent since rule " + ruleName + " is undefined"); + } + } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |