Open Session In View com JPA

Olá pessoal,

Alguem sabe como fazer o filter para o caso do open sesion in view com JPA? Já que o mesmo nao possui o recurso session.

Esse exemplo é do site do Jboss! Alguem sabe como alterar para funcionar com JPA?

Vlw

public class HibernateSessionRequestFilter implements Filter {
 
    private static Log log = LogFactory.getLog(HibernateSessionRequestFilter.class);
 
    private SessionFactory sf;
 
    public void doFilter(ServletRequest request,
                         ServletResponse response,
                         FilterChain chain)
            throws IOException, ServletException {
 
        try {
            log.debug("Starting a database transaction");
            sf.getCurrentSession().beginTransaction();
 
            // Call the next filter (continue request processing)
            chain.doFilter(request, response);
 
            // Commit and cleanup
            log.debug("Committing the database transaction");
            sf.getCurrentSession().getTransaction().commit();
 
        } catch (StaleObjectStateException staleEx) {
            log.error("This interceptor does not implement optimistic concurrency control!");
            log.error("Your application will not work until you add compensation actions!");
            throw staleEx;
        } catch (Throwable ex) {
            // Rollback only
            ex.printStackTrace();
            try {
                if (sf.getCurrentSession().getTransaction().isActive()) {
                    log.debug("Trying to rollback database transaction after exception");
                    sf.getCurrentSession().getTransaction().rollback();
                }
            } catch (Throwable rbEx) {
                log.error("Could not rollback transaction after exception!", rbEx);
            }
 
            // Let others handle it... maybe another interceptor for exceptions?
            throw new ServletException(ex);
        }
    }
 
    public void init(FilterConfig filterConfig) throws ServletException {
        log.debug("Initializing filter...");
        log.debug("Obtaining SessionFactory from static HibernateUtil singleton");
        sf = HibernateUtil.getSessionFactory();
    }
 
    public void destroy() {}
 
}

cara é muito simples

public class HibernateSessionRequestFilter implements Filter {

    public void init(FilterConfig config) throws ServletException{}

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HibernateUtil.beginTransaction();
        try {
            //response.setContentType("text/html; charset=UTF-8");//opcional
            chain.doFilter(request, response);
            HibernateUtil.commitTransaction();
        } catch (HibernateException exception) {
            exception.printStackTrace();
            HibernateUtil.rollbackTransaction();
        } finally {
            HibernateUtil.closeSession();
        }
    }

    /**
     * Finalização da classe exige também sua reescrita
     */
    public void destroy(){}

}

onde o hibernate util pode ser

public class HibernateUtil {

    private static final SessionFactory SESSION_FACTORY;
    private static final ThreadLocal SESSION_THREAD = new ThreadLocal();
    private static final ThreadLocal TRANSACTION_THREAD = new ThreadLocal();

    static {
        try {
            AnnotationConfiguration configuration = new AnnotationConfiguration();
            configuration.setProperty("hibernate.dialect", "org.hibernate.dialect.SQLServerDialect");
            configuration.setProperty("hibernate.connection.datasource", "seupool");//configurado no glassfish
            configuration.setProperty("hibernate.order_updates", "true");
            configuration.setProperty("hibernate.cache.provider_class", "org.hibernate.cache.NoCacheProvider");
            configuration.setProperty("hibernate.show_sql", "false");
            configuration.setProperty("hibernate.format_sql", "true");
            configuration.setProperty("hibernate.current_session_context_class", "thread");

            Scanner.scan(Thread.currentThread().getContextClassLoader(), Collections.EMPTY_SET, Collections.EMPTY_SET, configuration);//é um metodo que efetua o addanotationclass automatico ou você pode fazer varios addannotationsclass e substituir esse metodo. 
            SESSION_FACTORY = configuration.buildSessionFactory();
        } catch (Throwable ex) {
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static Session getSession() {
        if (SESSION_THREAD.get() == null) {
            Session session = SESSION_FACTORY.openSession();
            SESSION_THREAD.set(session);
        }
        return (Session) SESSION_THREAD.get();
    }

    public static void closeSession() {
        Session session = (Session) SESSION_THREAD.get();
        if (session != null && session.isOpen()) {
            SESSION_THREAD.set(null);
            session.close();
        }
    }

    public static void beginTransaction() {
        Transaction transaction = getSession().beginTransaction();
        TRANSACTION_THREAD.set(transaction);
    }

    public static void commitTransaction() {
        Transaction transaction = (Transaction) TRANSACTION_THREAD.get();
        if (transaction != null && !transaction.wasCommitted() && !transaction.wasRolledBack()) {
            transaction.commit();
            TRANSACTION_THREAD.set(null);
        }
    }

    public static void rollbackTransaction() {
        Transaction transaction = (Transaction) TRANSACTION_THREAD.get();
        if (transaction != null && !transaction.wasCommitted() && !transaction.wasRolledBack()) {
            transaction.rollback();
            TRANSACTION_THREAD.set(null);
        }
    }
}

no seu web.xml coloque

<filter>
        <filter-name>HibernateFilter</filter-name>
        <filter-class>br.com.empresa.pacote.HibernateSessionRequestFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>HibernateFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

Vlw,

No meu MB eu devo chamar o HibernateUtil.beginTransaction e HibernateUtil.closeSession? Ou o HibernateSessionRequestFilter faz isso automaticante?

não precisa mais de fechar!

na hora de usar se for para listar dê um getSession().clear(); e um return getSession().creatquery… apenas
e se for para salvar em varias tabelas e exigir um comit só no final use no inicio o getSession().begintransaction etc…

e nada de fechar mais nas listas!

Então a principal sacada para resolver esse problema é deixar o EntityManager (Session) como estatico?
E depois fazer o filtro para dar o commit/roolback tirando essa responsabilidade das classes?

É isso mesmo?

Vlw

[quote=apalmeira]Então a principal sacada para resolver esse problema é deixar o EntityManager (Session) como estatico?
E depois fazer o filtro para dar o commit/roolback tirando essa responsabilidade das classes?

É isso mesmo?

Vlw
[/quote]

sim, seus DAOs podem extender ao HibernateUtil dando funcionalidade direto ao getSession sendo ele static