Bu iş için Gmail'i kullanabilir miyiz diye küçük bir arama yaptığımda şu blog girdisine rastladım. Örnek kodta Gmail ayarları barındıran bir Enum mevcut. Mail gönderimi için de Spring çatısının Email desteği kullanılmış. Spring Email kullanabilmek için ayrıca activation.jar ve mail.jar kütüphaneleri de gerekli. Madem Spring kullanacağız bağımlılık yönetimini Spring'e bırakalım. Enum sınıfı yerine öncelikle JavaMailSenderImpl yaratan bir bean tanımı yapalım:
<bean id="javaMailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl"> <property name="host" value="smtp.googlemail.com"/> <property name="port" value="587"/> <property name="username" value="gmailAccount@gmail.com"/> <property name="password" value="armut123"/> <property name="javaMailProperties"> <props> <prop key="mail.smtp.auth">true</prop> <prop key="mail.smtp.starttls.enable">true</prop> </props> </property> </bean>
Yapmış olduğumuz bean tanımını ApplicationContext'ten alıp GMailAppender sınıfının kullanımına sunacak olan JavaMailSenderFactory sınıfını yazalım:
@Component public class JavaMailSenderFactory implements ApplicationContextAware { private static ApplicationContext applicationContext; public static JavaMailSender createJavaMailSender(){ return applicationContext.getBean("javaMailSender", JavaMailSender.class); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } }
JavaMailSenderFactory sınıfını da annotation yardımıyla Spring bean olarak tanımladık. Bean tanımını XML ile de yapabilirdik. Bu sınıf ApplicationContextAware arayüzünü gerçekleştirdiği için Spring application context'e erişerek JavaMailSender beanine ulaşabiliriz. Bunun için bean tanımını döndüren static bir metot yeterli olur. Log4j'nin SMTPAppender sınıfınından türetilen GMailAppender sınıfının bizim yaptığımız değişiklikler sonrasında aldığı hal şu şekilde:
public class GMailAppender extends SMTPAppender { private static final String NL = System.getProperty("line.separator"); @Override public void append(LoggingEvent event){ SimpleMailMessage msg = new SimpleMailMessage(); StringBuilder builder = new StringBuilder(); builder.append(getLayout().format(event)); builder.append(event.getMessage().toString()); if (event.getThrowableInformation() != null) { builder.append(NL); String[] stackTrace = event.getThrowableInformation().getThrowableStrRep(); for(int i = 0; i < stackTrace.length; i++) { builder.append(stackTrace[i] + NL); } } String[] senders = getTo().trim().replace(" ", "").split(","); msg.setTo(senders); msg.setText(builder.toString()); msg.setSubject(this.getSubject()); try{ JavaMailSender javaMail = JavaMailSenderFactory.createJavaMailSender(); javaMail.send(msg); }catch (MailException e) { System.err.println("!!! HATA MAILI GONDERILEMEDI !!! : "); e.printStackTrace(); } } }
Referans aldığım sitedeki append()metodunu da az biraz değiştirdim. Değişikliğin nedeni append() metodunun super.append(event) ile akışı SMTPAppender sınıfına aktarmış olması. GMailAppender içinde gerekli biçimlendirme ve gönderim işlemi yapıldığı için buna gerek yok aslında. Şimdi de GMailAppender için Log4J ayarlarını yapılandıralım. Ben properties dosyası yerine log4j.xml kullanmayı tercih ettim:
<root> <priority value="info" /> <appender-ref ref="GMailAppender" /> </root> <appender name="GMailAppender" class="com.prime.mobileme.core.util.appender.GMailAppender"> <param name="BufferSize" value="1" /> <param name="SMTPDebug" value="false" /> <param name="To" value="dasgin@gmail.com" /> <param name="Subject" value="Ucundan Java ERROR" /> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="[%d] [%t] %-5p %c %x" /> </layout> <filter class="org.apache.log4j.varia.LevelRangeFilter"> <param name="LevelMin" value="error" /> <param name="LevelMax" value="fatal" /> </filter> </appender>
Yukarıdaki ayarlardan da anlaşılacağı gibi yakaladığınız Exception'ları log4j ile error ya da fatal olarak loglarsanız loglanan hata mail olarak belirttiğiniz Gmail hesabı üzerinden gönderilecektir. Peki yakalayamadığımız hata durumlarında ne yapmalı? Eğer JSF 2 kullanıyorsanız şu blog girdisinden faydalanabiliriz. Gene buradaki örneği kendi ihtiyaçlarımıza göre yeniden düzenleyelim. Öncelikle oluşan hatayı ele alarak log4j'ye error olarak log düşen ExceptionHandler sınıfını hazırlayalım:
public class MyExceptionHandler extends ExceptionHandlerWrapper { private static Logger logger = LoggerFactory.getLogger(MyExceptionHandler.class); private ExceptionHandler wrappedExceptionHandler; public MyExceptionHandler(ExceptionHandler exceptionHandler){ this.wrappedExceptionHandler = exceptionHandler; } @Override public ExceptionHandler getWrapped() { return wrappedExceptionHandler; } @Override public void handle(){ for (ExceptionQueuedEvent event : getUnhandledExceptionQueuedEvents()) { ExceptionQueuedEventContext context = (ExceptionQueuedEventContext)event.getSource(); Throwable t = context.getException(); logger.error("Unhandled Exception: ", t); } getWrapped().handle(); } }
Ardından ExceptionHandler sınıfımızı JSF'in kullanabilmesi için ExceptionHandlerFactory sınımızı hazırlayalım:
public class MyExceptionHandlerFactory extends ExceptionHandlerFactory { private ExceptionHandlerFactory parent; public MyExceptionHandlerFactory(ExceptionHandlerFactory parent){ this.parent = parent; } @Override public ExceptionHandler getExceptionHandler() { return new MyExceptionHandler(parent.getExceptionHandler()); } }
En son adımda da faces-config.xml'e yazdığımız factory sınıfını tanıtmak kalıyor:
<factory> <exception-handler-factory> ucundan.java.MyExceptionHandlerFactory </exception-handler-factory> </factory>
Kaynaklar:
* GMail and log4j e-mail appender - error STARTTLS
* JSF 2 Exception Handling
Hiç yorum yok:
Yorum Gönder