Add cleanUp method to Handler base class, and call it from AjaxServlet. cleanUp uses reflection to inspect the impl instance for fields of type Session (Hibernate), and if one is found, attempts to close the Session if it was not already closed.

This commit is contained in:
Andy Janata 2012-07-14 15:06:36 -07:00
parent 7e577add21
commit 06e8ea4a07
3 changed files with 43 additions and 0 deletions

View File

@ -56,6 +56,10 @@ public class CahModule extends AbstractModule {
return 30;
}
/**
* @return A Hibernate session. Objects which receive a Hibernate session should close the
* session when they are done!
*/
@Provides
Session provideHibernateSession() {
return HibernateUtil.instance.sessionFactory.openSession();

View File

@ -23,8 +23,11 @@
package net.socialgamer.cah.handlers;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.http.HttpSession;
@ -33,6 +36,8 @@ import net.socialgamer.cah.Constants.ErrorCode;
import net.socialgamer.cah.Constants.ReturnableData;
import net.socialgamer.cah.RequestWrapper;
import org.hibernate.Session;
/**
* Implementations of this interface MUST also have a public static final String OP. There will be
@ -41,6 +46,8 @@ import net.socialgamer.cah.RequestWrapper;
* @author Andy Janata (ajanata@socialgamer.net)
*/
public abstract class Handler {
private final Logger logger = Logger.getLogger("net.socialgamer.cah.handlers.Handler");
/**
* Handle a request.
*
@ -66,4 +73,35 @@ public abstract class Handler {
data.put(AjaxResponse.ERROR_CODE, errorCode.toString());
return data;
}
/**
* Clean up after this Handler. Currently, this means using reflection to see if the concrete
* Handler implementation had a field of type Session (Hibernate), and closing it if it does and
* did not already close it.
*/
public final void cleanUp() {
for (final Field field : this.getClass().getDeclaredFields()) {
if (field.getType() == Session.class) {
try {
// This Handler had a Hibernate Session. Try to close it if it wasn't already closed.
// This is extremely dirty but also extremely awesome to not have problems if it is
// forgotten.
field.setAccessible(true);
final Session session = (Session) field.get(this);
if (session.isOpen()) {
session.close();
logger.log(Level.INFO, "Closing unclosed Hibernate Session in "
+ this.getClass().getName());
}
} catch (final Exception e) {
// Something prevented us from ignoring access control check, so we can't close the
// session. Log about it and continue.
e.printStackTrace();
logger.log(Level.SEVERE, "Unable to reflect and get Hibernate Session from "
+ this.getClass().getName());
logger.log(Level.SEVERE, e.toString());
}
}
}
}
}

View File

@ -91,6 +91,7 @@ public class AjaxServlet extends CahServlet {
return;
}
final Map<ReturnableData, Object> data = handler.handle(new RequestWrapper(request), hSession);
handler.cleanUp();
data.put(AjaxResponse.SERIAL, serial);
returnData(user, out, data);
return;