La mia applicazione Java utilizza Hibernate come framework ORM. Mi trovo spesso a scrivere codice come questo:
Session session = HibernateUtil.getSessionFactory().openSession();
try {
session.beginTransaction();
// do some work, which might or might not yield a result which will be returned
doWork(session);
// it also might involve using and changing local variables, like success and failure counters
session.getTransaction().commit();
return result;
} catch (Exception e) {
// optional: log the exception
Utility.logException("some log node", e);
// Also, some other actions like sending an alert email might happen at this place.
if (session.getTransaction().isActive()) {
session.getTransaction().rollback();
}
// optional: rethrow the exception
//throw e;
} finally {
if (session.isOpen()) {
session.close();
}
}
e mi chiedo se c'è un buon modo per inserire questo codice "boilerplate" in un unico metodo. Il doWork
spesso (ma non sempre) comporta la modifica delle variabili locali.
Se si trattava di un'applicazione C #, avrei creato un metodo come questo:
public static void DoWorkInSession(Action<Session> workToDo, String logNode, bool rethrowException)
e chiama l'azione workToDo
all'interno del metodo.
L'uso della reflection (che già faccio in alcuni punti) risolve solo parzialmente il problema e rende meno convenienti gli errori di logging con 'InvocationTargetException's. Ci sono altri (migliori) modi per farlo, ad es. usando le funzionalità di Java 8 che sto lentamente iniziando a scoprire?