2013-04-01 4 views
1

Я использую SpringSessionInViewFilter Spring в сочетании с Wicket, и я продолжал работать в LazyInitializationExceptions, который я не мог решить. Я мог видеть, что сеанс hibernate был закрыт до того, как было выброшено исключение, поэтому я явно делал что-то неправильно.OpenSessionInViewFilter и Wicket и все еще запущены в LazyInitializationExceptions

ответ

2

OSIVFilter должен быть выше WicketFilter, иначе запросы не дойдут до него. WicketFilter обрабатывает сами запросы страниц, он не передает другим компонентам, таким как другой сервлет (таким образом, цепочка фильтров останавливается).

Другой способ сделать это - создать реализацию IRequestCycleListener, которая делает то же, что и OSIVFilter. Я создал такой класс, изменяя код фильтра Spring, чтобы выполнить новый интерфейс, как показано ниже:

import org.apache.wicket.MetaDataKey; 
import org.apache.wicket.protocol.http.WebApplication; 
import org.apache.wicket.request.cycle.AbstractRequestCycleListener; 
import org.apache.wicket.request.cycle.RequestCycle; 
import org.hibernate.FlushMode; 
import org.hibernate.HibernateException; 
import org.hibernate.Session; 
import org.hibernate.SessionFactory; 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 
import org.springframework.dao.DataAccessResourceFailureException; 
import org.springframework.orm.hibernate4.SessionFactoryUtils; 
import org.springframework.orm.hibernate4.SessionHolder; 
import org.springframework.transaction.support.TransactionSynchronizationManager; 
import org.springframework.web.context.WebApplicationContext; 
import org.springframework.web.context.support.WebApplicationContextUtils; 

public class OpenSessionInViewRequestCycleListener extends AbstractRequestCycleListener { 

    protected final Logger logger = LoggerFactory.getLogger(getClass()); 

    public static final String DEFAULT_SESSION_FACTORY_BEAN_NAME = "sessionFactory"; 

    private static final MetaDataKey<Boolean> PARTICIPATE = new MetaDataKey<Boolean>() { 
    }; 

    private static final MetaDataKey<SessionFactory> SESSION_FACTORY = new MetaDataKey<SessionFactory>() { 
    }; 

    private String sessionFactoryBeanName = DEFAULT_SESSION_FACTORY_BEAN_NAME; 

    private final WebApplication application; 

    public OpenSessionInViewRequestCycleListener(WebApplication application) { 
     this.application = application; 
    } 

    /** 
    * Set the bean name of the SessionFactory to fetch from Spring's 
    * root application context. Default is "sessionFactory". 
    * @see #DEFAULT_SESSION_FACTORY_BEAN_NAME 
    */ 
    public void setSessionFactoryBeanName(String sessionFactoryBeanName) { 
     this.sessionFactoryBeanName = sessionFactoryBeanName; 
    } 

    /** 
    * Return the bean name of the SessionFactory to fetch from Spring's 
    * root application context. 
    */ 
    protected String getSessionFactoryBeanName() { 
     return this.sessionFactoryBeanName; 
    } 

    @Override 
    public void onBeginRequest(RequestCycle cycle) { 
     SessionFactory sessionFactory = lookupSessionFactory(cycle); 
     cycle.setMetaData(SESSION_FACTORY, sessionFactory); 
     cycle.setMetaData(PARTICIPATE, false); 

     if (TransactionSynchronizationManager.hasResource(sessionFactory)) { 
      // Do not modify the Session: just set the participate flag. 
      cycle.setMetaData(PARTICIPATE, true); 
     } 
     else { 
      logger.debug("Opening Hibernate Session in OpenSessionInViewRequestCycleListener"); 
      Session session = openSession(sessionFactory); 
      SessionHolder sessionHolder = new SessionHolder(session); 
      TransactionSynchronizationManager.bindResource(sessionFactory, sessionHolder); 
     } 
    } 

    @Override 
    public void onEndRequest(RequestCycle cycle) { 
     if (!cycle.getMetaData(PARTICIPATE)) { 
      SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.unbindResource(cycle.getMetaData(SESSION_FACTORY)); 
      logger.debug("Closing Hibernate Session in OpenSessionInViewFilter"); 
      SessionFactoryUtils.closeSession(sessionHolder.getSession()); 
     } 
    } 

    /** 
    * Look up the SessionFactory that this filter should use, 
    * taking the current HTTP request as argument. 
    * <p>The default implementation delegates to the {@link #lookupSessionFactory()} 
    * variant without arguments. 
    * @param cycle the current request 
    * @return the SessionFactory to use 
    */ 
    protected SessionFactory lookupSessionFactory(RequestCycle cycle) { 
     return lookupSessionFactory(); 
    } 

    /** 
    * Look up the SessionFactory that this filter should use. 
    * <p>The default implementation looks for a bean with the specified name 
    * in Spring's root application context. 
    * @return the SessionFactory to use 
    * @see #getSessionFactoryBeanName 
    */ 
    protected SessionFactory lookupSessionFactory() { 
     if (logger.isDebugEnabled()) { 
      logger.debug("Using SessionFactory '" + getSessionFactoryBeanName() + "' for OpenSessionInViewFilter"); 
     } 
     WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(this.application.getServletContext()); 
     return wac.getBean(getSessionFactoryBeanName(), SessionFactory.class); 
    } 

    /** 
    * Open a Session for the SessionFactory that this filter uses. 
    * <p>The default implementation delegates to the 
    * {@code SessionFactory.openSession} method and 
    * sets the {@code Session}'s flush mode to "MANUAL". 
    * @param sessionFactory the SessionFactory that this filter uses 
    * @return the Session to use 
    * @throws DataAccessResourceFailureException if the Session could not be created 
    * @see org.hibernate.FlushMode#MANUAL 
    */ 
    protected Session openSession(SessionFactory sessionFactory) throws DataAccessResourceFailureException { 
     try { 
      Session session = sessionFactory.openSession(); 
      session.setFlushMode(FlushMode.MANUAL); 
      return session; 
     } catch (HibernateException ex) { 
      throw new DataAccessResourceFailureException("Could not open Hibernate Session", ex); 
     } 
    } 

} 
+0

Ввод OSIV-фильтр над фильтром калитки в web.xml сервлета решенного к вопросу. –

+0

Он работает, но имеет один недостаток: если исключение вызывается OSIVFilter, пользователь увидит страницу ошибки Tomcat, а не страницу ошибки Wicket. Это может быть проблема или нет. – tetsuo

Смежные вопросы