Una delle cose più comode che si possano pensare per ricevere delle exception è riceverle direttamente via email, con tanto di Stack Trace e nome della classe (o bean) che l’ha generata.
A tal fine mi sono scritto un piccolo session bean che viene poi chiamato dall’exception handler in altri componenti delle mie applicazioni.
La prima cosa da fare è configurare una risorsa JavaMail su Glassfish:

Se avete la fortuna, come nel mio caso, di avere a disposizione un server SMTP aperto a dogs&pigs allora basterà impostare un nome JNDI, l’host e dare un utente a proprio piacimento.
Il passo successivo è creare un bean che verrà utilizzato da tutti gli altri componenti per mandare le email:
public class sendMail implements sendMailLocal { // Map resource configured in Glassfish server @Resource(name = "$JNDI_NAME") // Inserite qui il JNDI che avete impostato su Glassfish private Session mailSession; static protected final Logger log = Logger.getLogger(sendMail.class.getName()); /** * EJB used to send emails * @param recipient * @param subject * @param body */ @Override public void doSendMail(String recipient, String subject, String body) { // Prepare mail session Message msg = new MimeMessage(mailSession); try { // Set transport to SMTP Transport trans = mailSession.getTransport("smtp"); msg.setSubject(subject); // Parse recepients in properties file StringTokenizer recipientToken = new StringTokenizer(recipient,",;"); while (recipientToken.hasMoreTokens()) { String email = recipientToken.nextToken(); msg.addRecipient(RecipientType.TO, new InternetAddress(email)); } msg.setText(body); Transport.send(msg); } catch (MessagingException me) { StringWriter sw = new StringWriter(); me.printStackTrace(new PrintWriter(sw)); String stacktrace = sw.toString(); log.log(Level.INFO, stacktrace); } } }
A questo punto non rimane che invocare il bean, in questo caso mandiamo una mail in caso di exception dentro un message driven bean:
@EJB private sendMailLocal sendMail; .... @Override public void onMessage(Message message) { .... } catch (JMSException je) { log.log(Level.WARNING, je.toString()); sendMail.doSendMail("someuser@vostrodomain.it", "Vostro Subject", "Something went very bad"); } } }
Invece nel caso si voglia chiamare il bean da una classe comune (pojo):
public class vostraClasse { sendMailLocal sendMail = lookupsendMailLocal(); .... private sendMailLocal lookupsendMailLocal() { try { Context c = new InitialContext(); return (sendMailLocal) c.lookup(""pathToEJB"); } catch (NamingException ne) { Logger.getLogger(getClass().getName()).log(Level.SEVERE, "exception caught", ne); throw new RuntimeException(ne); } }
Se utilizzate Netbeans, come me, basta un click destro e selezionare “Call Enteprise Bean”, tutto il codice necessario verrà generato automaticamente.
Torniamo ora al caso del MDB che manda un’email in caso di exception:
} catch (JMSException je) { log.log(Level.WARNING, je.toString()); sendMail.doSendMail("someuser@vostrodomain.it", "Vostro Subject", "Something went very bad"); }
Non è che sia molto utile un’informazione così striminzita, noi vogliamo invece lo stacktrace dettagliato, il trucco è molto semplice:
} catch (JMSException je) { StringWriter sw = new StringWriter(); je.printStackTrace(new PrintWriter(sw)); String stacktrace = je.toString(); sendMail.doSendMail("someuser@vostrodomain.it", "Vostro Subject", "Exception " + getClass().getName() + "\n" + stacktrace); }