|
#1
|
|||
|
|||
|
Hi,
I have a problem that is driving me nuts. I have configured the OpenSessionInViewFilter like this in my web.xml: Code:
<filter>
<filter-name>sitemesh</filter-name>
<filter-class>com.opensymphony.module.sitemesh.filter.PageFilter</filter-class>
</filter>
<filter>
<filter-name>hibernate</filter-name>
<filter-class>org.springframework.orm.hibernate.support.OpenSessionInViewFilter</filter-class>
<init-param>
<param-name>singleSession</param-name>
<param-value>false</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>sitemesh</filter-name>
<url-pattern>/abp/action/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
<filter-mapping>
<filter-name>hibernate</filter-name>
<url-pattern>/abp/action/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>abploader</servlet-name>
<servlet-class>de.rpf.customer.ihk.abpboerse.web.servlet.LoaderServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>/abp/action/*</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
I changed OpenSessionInViewFilter to have some more logging: Code:
if (isSingleSession()) {
// single session mode
logger.debug("Single Session Mode");
if (TransactionSynchronizationManager.hasResource(sessionFactory)) {
// do not modify the Session: just set the participate flag
logger.debug("only participating");
participate = true;
}
else {
logger.debug("Opening single Hibernate session in OpenSessionInViewFilter");
session = getSession(sessionFactory);
TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session));
}
}
else {
logger.debug("Deferred Close Mode");
if (SessionFactoryUtils.isDeferredCloseActive(sessionFactory)) {
// do not modify deferred close: just set the participate flag
logger.debug("only participating");
participate = true;
}
else {
logger.debug("initDeferredClose");
SessionFactoryUtils.initDeferredClose(sessionFactory);
}
}
try {
logger.debug("going to filterchain");
filterChain.doFilter(request, response);
logger.debug("back from filterchain");
}
finally {
if (!participate) {
if (isSingleSession()) {
// single session mode
TransactionSynchronizationManager.unbindResource(sessionFactory);
logger.debug("Closing single Hibernate session in OpenSessionInViewFilter");
closeSession(session, sessionFactory);
}
else {
// deferred close mode
logger.debug("processing deferred close");
SessionFactoryUtils.processDeferredClose(sessionFactory);
}
}
}
Code:
DEBUG - OpenSessionInViewFilter.lookupSessionFactory(206) | Using session factory 'sessionFactory' for OpenSessionInViewFilter DEBUG - OpenSessionInViewFilter.doFilterInternal(161) | Deferred Close Mode DEBUG - OpenSessionInViewFilter.doFilterInternal(168) | initDeferredClose DEBUG - SessionFactoryUtils.initDeferredClose(494) | Initializing deferred close of Hibernate sessions DEBUG - OpenSessionInViewFilter.doFilterInternal(174) | going to filterchain DEBUG - AbstractPlatformTransactionManager.getTransaction(195) | Using transaction object [org.springframework.orm.hibernate.HibernateTransactionObject@1b98cbb] DEBUG - AbstractPlatformTransactionManager.getTransaction(267) | Creating new transaction DEBUG - SessionFactoryUtils.getSession(324) | Opening Hibernate session DEBUG - HibernateTransactionManager.doBegin(368) | Opened new session [net.sf.hibernate.impl.SessionImpl@c68351] for Hibernate transaction DEBUG - HibernateTransactionManager.doBegin(410) | Exposing Hibernate transaction as JDBC transaction [org.hsqldb.jdbc.jdbcConnection@d76237] DEBUG - AbstractPlatformTransactionManager.triggerBeforeCommit(495) | Triggering beforeCommit synchronization DEBUG - AbstractPlatformTransactionManager.triggerBeforeCompletion(510) | Triggering beforeCompletion synchronization DEBUG - AbstractPlatformTransactionManager.commit(372) | Initiating transaction commit DEBUG - HibernateTransactionManager.doCommit(456) | Committing Hibernate transaction on session [net.sf.hibernate.impl.SessionImpl@c68351] DEBUG - AbstractPlatformTransactionManager.triggerAfterCompletion(540) | Triggering afterCompletion synchronization DEBUG - HibernateTransactionManager.doCleanupAfterCompletion(532) | Closing Hibernate session [net.sf.hibernate.impl.SessionImpl@c68351] after transaction DEBUG - SessionFactoryUtils.doClose(567) | Closing Hibernate session ERROR - LazyInitializationException.<init>(25) | Failed to lazily initialize a collection - no session or session was closed I strongly suspect something is wrong with my configuration, but I have no idea what it could be. Any ideas? Thanks Carl-Eric |
|
#2
|
|||
|
|||
|
how about removing
<init-param> <param-name>singleSession</param-name> <param-value>false</param-value> </init-param> |
|
#3
|
|||
|
|||
|
I tried that, but the result is the same. The log changes only slightly:
Code:
DEBUG - OpenSessionInViewFilter.lookupSessionFactory(206) | Using session factory 'sessionFactory' for OpenSessionInViewFilter DEBUG - OpenSessionInViewFilter.doFilterInternal(148) | Single Session Mode DEBUG - OpenSessionInViewFilter.doFilterInternal(155) | Opening single Hibernate session in OpenSessionInViewFilter DEBUG - SessionFactoryUtils.getSession(324) | Opening Hibernate session DEBUG - OpenSessionInViewFilter.doFilterInternal(174) | going to filterchain DEBUG - AbstractPlatformTransactionManager.getTransaction(195) | Using transaction object [org.springframework.orm.hibernate.HibernateTransactionObj ect@1f9c5c8] DEBUG - AbstractPlatformTransactionManager.getTransaction(267) | Creating new transaction DEBUG - SessionFactoryUtils.getSession(324) | Opening Hibernate session DEBUG - HibernateTransactionManager.doBegin(368) | Opened new session [net.sf.hibernate.impl.SessionImpl@12801c5] for Hibernate transaction DEBUG - HibernateTransactionManager.doBegin(410) | Exposing Hibernate transaction as JDBC transaction [org.hsqldb.jdbc.jdbcConnection@18c668c] DEBUG - AbstractPlatformTransactionManager.triggerBeforeCommit(495) | Triggering beforeCommit synchronization DEBUG - AbstractPlatformTransactionManager.triggerBeforeCompletion(510) | Triggering beforeCompletion synchronization DEBUG - AbstractPlatformTransactionManager.commit(372) | Initiating transaction commit DEBUG - HibernateTransactionManager.doCommit(456) | Committing Hibernate transaction on session [net.sf.hibernate.impl.SessionImpl@12801c5] DEBUG - AbstractPlatformTransactionManager.triggerAfterCompletion(540) | Triggering afterCompletion synchronization DEBUG - HibernateTransactionManager.doCleanupAfterCompletion(532) | Closing Hibernate session [net.sf.hibernate.impl.SessionImpl@12801c5] after tran saction DEBUG - SessionFactoryUtils.doClose(567) | Closing Hibernate session ERROR - LazyInitializationException.<init>(25) | Failed to lazily initialize a collection - no session or session was closed net.sf.hibernate.LazyInitializationException: Failed to lazily initialize a collection - no session or session was closed Code:
public CorporateUser load(int id)
{
CorporateUser corp = (CorporateUser) getHibernateTemplate().get(CorporateUser.class,
new Integer(id));
if (corp == null)
{
throw new ObjectRetrievalFailureException(CorporateUser.class,
new Integer(id));
}
else
{
return corp;
}
}
public CorporateUser loadOrCreate(int id)
{
CorporateUser corp = null;
try
{
corp = load(id);
}
catch (ObjectRetrievalFailureException e)
{
if (corp == null)
{
corp = new CorporateUser();
corp.setId(id);
save(corp);
}
}
return corp;
}
public CorporateUser save(CorporateUser c)
{
getHibernateTemplate().saveOrUpdate(c);
return c;
}
Code:
<bean id="txProxyTemplate" lazy-init="true"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
>
<property name="transactionManager"><ref local="transactionManager"/></property>
<property name="transactionAttributes">
<props>
<prop key="loadOrCreate">PROPAGATION_REQUIRED</prop>
<prop key="load*">PROPAGATION_SUPPORTS,readOnly,+Throwable</prop>
<prop key="get*">PROPAGATION_SUPPORTS,readOnly</prop>
<prop key="find*">PROPAGATION_SUPPORTS,readOnly</prop>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="create*">PROPAGATION_REQUIRED</prop>
<prop key="delete*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
Thanks Carl-Eric |
|
#4
|
|||
|
|||
|
I tried stepping through a whole request in Tomcat 4 with Eclipse 3 now, and I found out the following:
In OpenSessionInViewFilter initDeferredClose() is called and the deferred close holder set is also created and stored in the appropriate ThreadLocal. When the request gets to my Struts Action and calls the DAO method, weird things happen. I do the DAO call as usual via getHibernateTemplate().load(...). When I continue in the debugger into HibernateTemplate, the getSessionFactory() method returns a valid SessionFactory, but its "id" as displayed in the Eclipse debugger is *not* the same as the one I saw for the SessionFactory that was stored in the deferred close holder. I'm not too familiar with the debugger, but I think this means that this is a different instance. Where does it come from? The problem with this becomes obvious in closeSessionOrRegisterDeferredClose(). The SessionFactory that is passed as an argument here is again this second instance that was also in the HibernateTemplate. The deferred close map contains the *first* instance, so the contains() check returns false and the method believes this session is not registered to be closed later. It closes the session, and then of course I get the LazyInitializationException later on. So my problem now is: Where does this second SessionFactory come from, and what can I do about it? Thanks Carl-Eric |
|
#5
|
|||
|
|||
|
More debugging: It seems that the OpenSessionInViewFilter is getting a different SessionFactory instance than the one that is assigned to the HibernateDaoSupport instances which form my DAO layer. How can this be?
Thanks Carl-Eric |
|
#6
|
|||
|
|||
|
Quote:
from OpenSessionInViewFilter source: Code:
protected SessionFactory lookupSessionFactory() {
if (logger.isDebugEnabled()) {
logger.debug("Using session factory '" + getSessionFactoryBeanName() + "' for OpenSessionInViewFilter");
}
WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
return (SessionFactory) wac.getBean(getSessionFactoryBeanName());
}
I do not know how sitemesh manages page composition, but could you try to inverse the order of your filters and put hibernate first: Code:
<filter-mapping>
<filter-name>hibernate</filter-name>
<url-pattern>/abp/action/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
<filter-mapping>
<filter-name>sitemesh</filter-name>
<url-pattern>/abp/action/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
|
|
#7
|
|||
|
|||
|
I temporarily disabled SiteMesh completely for other reasons today. It did not change the OpenSessionInViewFilter behavior. I am currently out of ideas, but I'll post my config files - maybe you can see what is wrong.
web.xml: Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd"
>
<web-app>
<display-name>Ausbildungsplatzboerse</display-name>
<filter>
<filter-name>sitemesh</filter-name>
<filter-class>com.opensymphony.module.sitemesh.filter.PageFilter</filter-class>
</filter>
<filter>
<filter-name>hibernate</filter-name>
<filter-class>org.springframework.orm.hibernate.support.OpenSessionInViewFilter</filter-class>
<!--init-param>
<param-name>singleSession</param-name>
<param-value>false</param-value>
</init-param-->
</filter>
<!--filter-mapping>
<filter-name>sitemesh</filter-name>
<url-pattern>/abp/action/*</url-pattern>
</filter-mapping-->
<filter-mapping>
<filter-name>hibernate</filter-name>
<url-pattern>/abp/action/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>abploader</servlet-name>
<servlet-class>myproject.web.servlet.LoaderServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>/abp/action/*</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<taglib>
<taglib-uri>/tags/struts-bean</taglib-uri>
<taglib-location>/WEB-INF/lib/struts-bean-el.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>/tags/struts-html</taglib-uri>
<taglib-location>/WEB-INF/lib/struts-html-el.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>/tags/core</taglib-uri>
<taglib-location>/WEB-INF/lib/c-1_0.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>/tags/display</taglib-uri>
<taglib-location>/WEB-INF/lib/displaytag-el-12.tld</taglib-location>
</taglib>
</web-app>
Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
"http://struts.apache.org/dtds/struts-config_1_2.dtd">
<struts-config>
<!-- ======================================== Form Bean Definitions -->
<form-beans>
<form-bean name="jobOfferForm"
type="myproject.struts.form.JobOfferForm"/>
</form-beans>
<!-- =================================== Global Forward Definitions -->
<global-forwards>
<forward name="corpaccessdenied" path="/WEB-INF/pages/welcome.jsp"/>
</global-forwards>
<!-- =================================== Action Mapping Definitions -->
<action-mappings>
<action path="/welcome"
forward="/WEB-INF/pages/welcome.jsp" />
<action path="/corpOverview"
type="org.springframework.web.struts.DelegatingActionProxy">
<forward name="success" path="/WEB-INF/pages/corp/overview.jsp"/>
</action>
<action path="/createOffer"
name="jobOfferForm"
scope="request"
type="org.springframework.web.struts.DelegatingActionProxy">
<forward name="success" path="/WEB-INF/pages/corp/createoffer.jsp"/>
</action>
<action path="/submitOffer"
name="jobOfferForm"
scope="request"
type="org.springframework.web.struts.DelegatingActionProxy">
<forward name="success" path="/WEB-INF/pages/corp/editoffer.jsp"/>
</action>
<action path="/saveOffer"
type="org.springframework.web.struts.DelegatingActionProxy">
</action>
<action path="/requestActivation"
type="org.springframework.web.struts.DelegatingActionProxy">
</action>
</action-mappings>
<!-- ================================ Message Resources Definitions -->
<message-resources parameter="application"/>
<message-resources parameter="job" key="jobResources"/>
<message-resources parameter="region" key="regionResources"/>
<message-resources parameter="jobcategory" key="jobcatResources"/>
<!-- ======================================= Plug Ins Configuration -->
<plug-in className="org.springframework.web.struts.ContextLoaderPlugIn">
<set-property property="contextConfigLocation"
value="/WEB-INF/applicationContext.xml, /WEB-INF/action-servlet.xml"/>
</plug-in>
</struts-config>
Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName"><value>org.hsqldb.jdbcDriver</value></property>
<!--property name="url"><value>jdbc:hsqldb:db/abp</value></property-->
<property name="url"><value>jdbc:hsqldb:mem:abp</value></property>
<property name="username"><value>sa</value></property>
<property name="password"><value></value></property>
</bean>
<!-- Hibernate SessionFactory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean">
<property name="dataSource"><ref local="dataSource"/></property>
<property name="mappingResources">
<list>
<value>de/rpf/customer/ihk/abpboerse/core/CorporateUser.hbm.xml</value>
<value>de/rpf/customer/ihk/abpboerse/core/TraineeUser.hbm.xml</value>
<value>de/rpf/customer/ihk/abpboerse/core/JobOffer.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">net.sf.hibernate.dialect.HSQLDialect</prop>
<prop key="hibernate.hbm2ddl.auto">create</prop>
<prop key="hibernate.show_sql">false</prop>
</props>
</property>
</bean>
<!-- Transaction manager for a single Hibernate SessionFactory (alternative to JTA) -->
<bean id="transactionManager" class="org.springframework.orm.hibernate.HibernateTransactionManager">
<property name="sessionFactory"><ref local="sessionFactory"/></property>
</bean>
<bean id="txProxyTemplate" lazy-init="true"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
>
<property name="transactionManager"><ref local="transactionManager"/></property>
<property name="transactionAttributes">
<props>
<prop key="loadOrCreate">PROPAGATION_REQUIRED</prop>
<prop key="load*">PROPAGATION_SUPPORTS,readOnly,+Throwable</prop>
<prop key="get*">PROPAGATION_SUPPORTS,readOnly</prop>
<prop key="find*">PROPAGATION_SUPPORTS,readOnly</prop>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="create*">PROPAGATION_REQUIRED</prop>
<prop key="delete*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
<!-- Add DAOs here -->
<bean id="corpUserDAO" parent="txProxyTemplate">
<property name="target">
<bean class="myproject.dao.hibernate.CorpUserDAOImpl">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
</bean>
</property>
</bean>
<bean id="traineeUserDAO" parent="txProxyTemplate">
<property name="target">
<bean class="myproject.dao.hibernate.TraineeUserDAOImpl">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
</bean>
</property>
</bean>
<bean id="jobDAO" parent="txProxyTemplate">
<property name="target">
<bean class="myproject.dao.hibernate.JobDAOImpl">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
</bean>
</property>
</bean>
<!-- Add Managers here -->
<bean id="authUtils" class="myproject.web.util.AuthorizationUtils">
<property name="corpUserDAO"><ref bean="corpUserDAO"/></property>
</bean>
</beans>
Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean name="corpActionTemplate"
class="myproject.struts.action.CorpAction"
lazy-init="true">
<property name="authUtils">
<ref bean="authUtils"/>
</property>
<property name="authUtils">
<ref bean="authUtils"/>
</property>
</bean>
<bean name="/corpOverview"
class="myproject.struts.action.CorpOverviewAction"
parent="corpActionTemplate">
<property name="corpUserDAO">
<ref bean="corpUserDAO"/>
</property>
</bean>
<bean name="/createOffer"
class="myproject.struts.action.CreateOfferAction"
parent="corpActionTemplate">
</bean>
<bean name="/submitOffer"
class="myproject.struts.action.SubmitOfferAction"
parent="corpActionTemplate">
</bean>
</beans>
Thanks! Carl-Eric |
|
#8
|
||||
|
||||
|
Quote:
![]() Ok, I can see the following "issues": 1. struts-config.xml: Quote:
I can see that you provided WEB-INF/applicationContext.xml to ContextLoaderPlugIn, this will result in all beans defined in this file configured twice, in the root wac and in the wac created by Struts Plugin... Result: You will be using two sessionFactories!!! The configuration should be: Code:
<plug-in className="org.springframework.web.struts.ContextLoaderPlugIn">
<set-property property="contextConfigLocation"
value="/WEB-INF/action-servlet.xml"/>
</plug-in>
Quote:
3. datasource configuration: (not really an issue) Quote:
HTH |
|
#9
|
|||
|
|||
|
It was the duplicate context in struts-config.xml. I removed it and now it works as expected. Yay!
I will fix both the transaction and the data source configuration later, I'm still rather early in the development and the current setup is only supposed to verify that it all works. Thanks a lot for your help! Carl-Eric |
|
#10
|
|||
|
|||
|
Last edited by robyn; May 14th, 2006 at 10:59 AM. |
![]() |
| Thread Tools | |
| Display Modes | |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| OpenSessionInView and portlet support | garpinc2 | Spring Web Flow | 23 | Today 10:03 AM |
| Loosing my SecureContext | sklakken | Spring Security | 3 | Jul 21st, 2005 02:44 PM |
| Why are new sessions created with OpenSessionInViewFilter? | iksrazal | Data Access | 3 | May 16th, 2005 08:04 AM |
| OpenSessionInViewInterceptor called but session flushed | andrew_null | Data Access | 1 | Mar 12th, 2005 05:33 AM |
| Hibernate Session Per Request Problem with CMT EJB | fgarsombke | Data Access | 3 | Nov 19th, 2004 08:16 PM |