Since it seemed almost impossible to get log4j's SMTPAppender to work with jboss 7 i decided to create a logging handler of my own.
A custom handler must inherit java.util.logging.Handler
So without further due, here's the code for the custom email handler.
package com.company.logging; import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; import java.util.Date; import java.util.Hashtable; import java.util.logging.ErrorManager; import java.util.logging.Handler; import java.util.logging.LogRecord; import javax.mail.Address; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.Session; import javax.mail.Transport; import javax.mail.internet.AddressException; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; public class EmailHandler extends Handler { private Session mailSession; private String subject; private String senderAddress; private String recieverAddress; private String logFile; private String jndiLookup; private Boolean debugMode; public BufferedWriter out = null; public EmailHandler() { super(); jndiLookup = "java:jboss/mail/Default"; debugMode = false; logFile = ""; } @Override public void publish(LogRecord record) { if (!initialize()) { return; } if(isLoggable(record)) { process(record); } } private synchronized boolean initialize() { if (out==null && logFile!=null && !logFile.equals("")) { FileWriter fstream = null; try { fstream = new FileWriter(logFile,true); out = new BufferedWriter(fstream); } catch (IOException e) { reportError(e.getMessage(), e, ErrorManager.OPEN_FAILURE); } logToFile("Log file initialized. Logging to: " + logFile); } if(mailSession==null) { final Hashtable jndiProperties = new Hashtable(); jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming"); Context context; String jndiNamespace = jndiLookup; if(debugMode) logToFile("Trying to initialize the mail session from jndi"); try { context = new InitialContext(jndiProperties); if(debugMode) logToFile("Initial context was "+(context==null?"not found":"found")); mailSession = (Session) context.lookup(jndiNamespace); if(debugMode) logToFile("Mail session was "+(mailSession==null?"not found":"found")); } catch (NamingException e) { String message = "There was an error initializing the mail session"; if(debugMode) logToFile(message + ": "+ e.getMessage()); reportError(message, e, ErrorManager.GENERIC_FAILURE); return false; } } return true; } private void process(LogRecord logRecord) { if(debugMode) logToFile("New mail should be sent"); MimeMessage m = new MimeMessage(mailSession); if(debugMode) logToFile("New mail created"); Address from; try { from = new InternetAddress(senderAddress); if(debugMode) logToFile("Sender address: " + senderAddress); Address[] to = new InternetAddress[] {new InternetAddress(recieverAddress) }; if(debugMode) logToFile("Reciepient address: " + recieverAddress); m.setFrom(from); m.setRecipients(Message.RecipientType.TO, to); m.setSubject(subject); if(debugMode) logToFile("Subject: "+ subject); m.setSentDate(new java.util.Date()); m.setContent(getFormatter().format(logRecord),"text/plain"); Transport.send(m); if(debugMode) { logToFile("Mail successfully sent"); } else { logToFile("Mail successfully sent to: "+ senderAddress); } } catch (AddressException e) { String message = "Could not resolve address"; if(debugMode) logToFile(message + ": "+ e.getMessage()); reportError(message, e, ErrorManager.GENERIC_FAILURE); } catch (MessagingException e) { String message = "Mail could not be sent due to"; if(debugMode) logToFile(message + ": "+ e.getMessage()); reportError(message, e, ErrorManager.GENERIC_FAILURE); } } private void logToFile(String text) { try { if (out!=null) { out.write((new Date()).toString() + "\t" + text+"\n"); out.flush(); } } catch (IOException e) { reportError(e.getMessage(), e, ErrorManager.WRITE_FAILURE); } } @Override public void flush() { try { if (out!=null) { out.flush(); } } catch (IOException e) { reportError(e.getMessage(), e, ErrorManager.FLUSH_FAILURE); } } @Override public void close() { if(out!=null) { try { out.close(); } catch (IOException e) { reportError(e.getMessage(), e, ErrorManager.CLOSE_FAILURE); } } } public void setSubject(String subject) { this.subject = subject; } public void setSenderAddress(String senderAddress) { this.senderAddress = senderAddress; } public void setRecieverAddress(String recieverAddress) { this.recieverAddress = recieverAddress; } public void setLogFile(String logFile) { this.logFile = logFile; } public void setJndiLookup(String jndiLookup) { this.jndiLookup = jndiLookup; } public void setDebugMode(String debugMode) { this.debugMode = false; try { this.debugMode = Boolean.parseBoolean(debugMode); } catch (Exception e) { } } }
The file is then packaged into a jar and placed in the modules directory. i.e. Jboss-as-7.1.0.Final/modules/com/company/loggers/main
together with a module.xml file. The contents of the module.xml should look like this.
<?xml version="1.0" encoding="UTF-8"?> <module xmlns="urn:jboss:module:1.0" name="com.company.loggers"> <resources> <resource-root path="EmailHandler.jar"/> <!-- Insert resources here --> </resources> <dependencies> <module name="org.jboss.logging"/> <module name="javax.api"/> <module name="javax.mail.api"/> </dependencies> </module>
Then modify the standalone.xml to support logging to the custom logger
<custom-handler name="EmailAppender" class="com.company.logging.EmailHandler" module="com.company.loggers"> <level name="ERROR"/> <formatter> <pattern-formatter pattern="%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n"/> </formatter> <properties> <property name="jndiLookup" value="java:jboss/mail/Default"/> <property name="subject" value="[SMTPAppender] Application message"/> <property name="senderAddress" value="sender@server" /> <property name="recieverAddress" value="reciepient@domain.com"/> <property name="logFile" value="c:\\temp\\logfile.txt"/> <property name="debugMode" value="true"/> </properties> </custom-handler>
And also set up the mail subsystem and modify the remote-destination host accordingly
<socket-binding-group name="standard-sockets" default-interface="public" port-offset="${jboss.socket.binding.port-offset:0}"> <socket-binding name="http" port="8080"/> <socket-binding name="https" port="8443"/> <socket-binding name="management-native" interface="management" port="${jboss.management.native.port:9999}"/> <socket-binding name="management-http" interface="management" port="${jboss.management.http.port:9990}"/> <socket-binding name="management-https" interface="management" port="${jboss.management.https.port:9443}"/> <socket-binding name="osgi-http" interface="management" port="8090"/> <socket-binding name="remoting" port="4447"/> <socket-binding name="txn-recovery-environment" port="4712"/> <socket-binding name="txn-status-manager" port="4713"/> <outbound-socket-binding name="mail-smtp"> <remote-destination host="smtp.yourserver.com" port="25"/> </outbound-socket-binding> </socket-binding-group>
Don't forget to add the EmailAppender to the root logger as well.
Kind Regards
/Danjel Nyberg
Comments