package org.hibernate.auction.persistence;

import net.sf.hibernate.Session;
import org.apache.commons.logging.*;

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;

/**
 * Filtr serwletowy rozłączający i ponownie łączący sesję Hibernate dla każdego żądania
 * <p>
 * Użyj filtru we wzorcu <b>sesja na transakcje aplikacyjną</b> z
 * <i>długą sesją</i>. Nie zappomnij odpowiednio oznaczać transakcji aplikacyjnych w kodzie.
 *
 * @see HibernateUtil
 * @author Christian Bauer <christian@hibernate.org>
 */
public class HibernateFilterLong
		implements Filter {

	private static final String HTTPSESSIONKEY = "HibernateSession";
	private static Log log = LogFactory.getLog(HibernateFilterLong.class);

	public void init(FilterConfig filterConfig) throws ServletException {
		log.info("Inicjalizacja filtru serwletu, rozłącza i ponownie łączy sesję dla każdego żądania.");
	}

	public void doFilter(ServletRequest request,
						 ServletResponse response,
						 FilterChain chain)
			throws IOException, ServletException {

		// Spróbuj pobrać sesję z HttpSession.
		HttpSession userSession =
				((HttpServletRequest) request).getSession();
		Session hibernateSession =
				(Session) userSession.getAttribute(HTTPSESSIONKEY);

		if (hibernateSession != null)
			HibernateUtil.reconnect(hibernateSession);

		// Jeśli nie ma sesji, pierwsze wywołanie
		// HibernateUtil.beginTransaction w kodzie aplikacji spowoduje
		// utworzenie nowej sesji dla wątku.
		try {
			chain.doFilter(request, response);

			// Zatwierdź oczekującą transakcję bazodanową.
			HibernateUtil.commitTransaction();

		} finally {
			// TODO: Sesję należy zamknąć w przypadku błędu krytycznego.

			// Niezależnie od tego, co się stanie, odłącz sesję
			hibernateSession = HibernateUtil.disconnectSession();
			// i zapamiętaj ją w obiekcie HttpSession.
			userSession.setAttribute(HTTPSESSIONKEY, hibernateSession);
		}
	}

	public void destroy() {}

}
