/* * Databinder: a simple bridge from Wicket to Hibernate * Copyright (C) 2006 Nathan Hamblen nathan@technically.us * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* * Note: this class contains code adapted from wicket-contrib-database. */ package net.databinder.hib; import java.util.HashSet; import net.databinder.CookieRequestCycle; import org.apache.wicket.Page; import org.apache.wicket.Response; import org.apache.wicket.protocol.http.WebApplication; import org.apache.wicket.protocol.http.WebRequest; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.context.ManagedSessionContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * <p>Opens Hibernate sessions and transactions as required and closes them at a request's * end. Uncomitted transactions are rolled back. Uses keyed Hibernate session factories from * Databinder service.</p> * @see Databinder * @author Nathan Hamblen */ public class DataRequestCycle extends CookieRequestCycle implements HibernateRequestCycle { /** Keys for session factories that have been opened for this request */ protected HashSet<Object> keys = new HashSet<Object>(); private static final Logger log = LoggerFactory.getLogger(DataRequestCycle.class); public DataRequestCycle(WebApplication application, WebRequest request, Response response) { super(application, request, response); } /** Roll back active transactions and close session. */ protected void closeSession(Object key) { Session sess = Databinder.getHibernateSession(key); if (sess.isOpen()) try { if (sess.getTransaction().isActive()) { log.debug("Rolling back uncomitted transaction."); sess.getTransaction().rollback(); } } finally { sess.close(); } } /** * Called by DataStaticService when a session is needed and does not already exist. * Opens a new thread-bound Hibernate session. */ public void dataSessionRequested(Object key) { openHibernateSession(key); } /** * Open a session and begin a transaction for the keyed session factory. * @param key object, or null for the default factory * @return newly opened session */ protected org.hibernate.classic.Session openHibernateSession(Object key) { org.hibernate.classic.Session sess = Databinder.getHibernateSessionFactory(key).openSession(); sess.beginTransaction(); ManagedSessionContext.bind(sess); keys.add(key); return sess; } /** * Closes all Hibernate sessions opened for this request. If a transaction has * not been committed, it will be rolled back before closing the session. * @see net.databinder.components.hib.DataForm#onSubmit() */ @Override protected void onEndRequest() { for (Object key : keys) { SessionFactory sf = Databinder.getHibernateSessionFactory(key); if (ManagedSessionContext.hasBind(sf)) { closeSession(key); ManagedSessionContext.unbind(sf); } } } /** * Closes and reopens sessions for this request cycle. Unrelated models may try to load * themselves after this point. */ @Override public Page onRuntimeException(Page page, RuntimeException e) { onEndRequest(); onBeginRequest(); return null; } }