Problem with OpenSessionInViewFilter and Hibernate sessions
I am currently having problems with the OpenSessionInViewFilter together with Hibernate sessions. I need Hibernate sessions to be open for an entire
HttpRequest as I am most reliant on using the lazy-loading functionality as provided by Hibernate. Currently I am having problems both when running the web-app and through JUnit testcases. In other words, the problem probably lies within the configuration. The application is using Struts in the MVC tier.
I have read numerous postings to the support forums as well as some blogs touching the subject. However, none of the suggestions seem to be helpful for me. Below I have provided snippets from logs, code and configuration that I consider to be relevant. Any help on the matter will be greatly appreciated!
Code:
Log
18:34:56,057 DEBUG TransactionInterceptor:197 - Getting transaction for method 'fetchAllProjects' in class [no.myproj.ProjectService]
18:34:56,067 INFO JdbcTransactionObjectSupport:60 - JDBC 3.0 Savepoint class is available
18:34:56,067 DEBUG HibernateTransactionManager:195 - Using transaction object [org.springframework.orm.hibernate.HibernateTransactionManager$HibernateTransactionObject@4a5c78]
18:34:56,067 DEBUG HibernateTransactionManager:269 - Creating new transaction
18:34:56,067 DEBUG SessionFactoryUtils:311 - Opening Hibernate session
18:34:56,067 DEBUG HibernateTransactionManager:371 - Opened new session [net.sf.hibernate.impl.SessionImpl@1fcf790] for Hibernate transaction
18:34:56,077 DEBUG DataSourceUtils:205 - Setting JDBC connection [org.apache.commons.dbcp.PoolableConnection@1a7789c] read-only
18:34:56,097 DEBUG HibernateTransactionManager:413 - Exposing Hibernate transaction as JDBC transaction [org.apache.commons.dbcp.PoolableConnection@1a7789c]
18:34:56,097 DEBUG TransactionSynchronizationManager:147 - Bound value [org.springframework.jdbc.datasource.ConnectionHolder@51ef4e] for key [org.apache.commons.dbcp.BasicDataSource@14e4e31] to thread [main]
18:34:56,097 DEBUG TransactionSynchronizationManager:147 - Bound value [org.springframework.orm.hibernate.SessionHolder@135f44e] for key [net.sf.hibernate.impl.SessionFactoryImpl@3f4ebd] to thread [main]
18:34:56,097 DEBUG TransactionSynchronizationManager:199 - Initializing transaction synchronization
18:34:56,107 DEBUG TransactionSynchronizationManager:122 - Retrieved value [org.springframework.orm.hibernate.SessionHolder@135f44e] for key [net.sf.hibernate.impl.SessionFactoryImpl@3f4ebd] bound to thread [main]
18:34:56,117 DEBUG TransactionSynchronizationManager:122 - Retrieved value [org.springframework.orm.hibernate.SessionHolder@135f44e] for key [net.sf.hibernate.impl.SessionFactoryImpl@3f4ebd] bound to thread [main]
18:34:56,157 DEBUG SQL:226 - select project0_.PROSJEKTNR as PROSJEKTNR, project0_.PROSJEKTNAVN as PROSJEKT2_, project0_.KRØSUS_PROSJEKT as KRØSUS_P3_, project0_.HP1 as HP1, project0_.HP2 as HP2, project0_.KM_FRA_1 as KM_FRA_1, project0_.KM_TIL_1 as KM_TIL_1, project0_.KM_FRA_2 as KM_FRA_2, project0_.KM_TIL_2 as KM_TIL_2, project0_.DATO_REGISTRERT as DATO_RE10_, project0_.FRIST_TILTREDELSE as FRIST_T11_, project0_.FRIST_KJØPEKONTRAKT as FRIST_K12_, project0_.GODKJENT_PLANDATO as GODKJEN13_, project0_.PLANTYPE as PLANTYPE, project0_.PROSJEKTTYPE as PROSJEK15_, project0_.ANSVARSNR as ANSVARSNR, project0_.ANLEGG_STARTDATO as ANLEGG_17_, project0_.ANLEGG_FERDIGDATO as ANLEGG_18_, project0_.GRUNNEIERMOTE as GRUNNEI19_, project0_.PROSJEKT_AVSLUTTET as PROSJEK20_, project0_.SAKSBEHANDLER_GRUNN as SAKSBEH21_, project0_.LANDMALER as LANDMALER, project0_.SAKSBEHANDLER_PLAN as SAKSBEH23_, project0_.SAKSBEHANDLER_DRIFT as SAKSBEH24_, project0_.SAKSBEHANDLER_OPPGJØR as SAKSBEH25_, project0_.MERKNAD1 as MERKNAD1, project0_.STATUS_ERVERV as STATUS_27_ from prosjekt_hoved project0_
Hibernate: select project0_.PROSJEKTNR as PROSJEKTNR, project0_.PROSJEKTNAVN as PROSJEKT2_, project0_.KRØSUS_PROSJEKT as KRØSUS_P3_, project0_.HP1 as HP1, project0_.HP2 as HP2, project0_.KM_FRA_1 as KM_FRA_1, project0_.KM_TIL_1 as KM_TIL_1, project0_.KM_FRA_2 as KM_FRA_2, project0_.KM_TIL_2 as KM_TIL_2, project0_.DATO_REGISTRERT as DATO_RE10_, project0_.FRIST_TILTREDELSE as FRIST_T11_, project0_.FRIST_KJØPEKONTRAKT as FRIST_K12_, project0_.GODKJENT_PLANDATO as GODKJEN13_, project0_.PLANTYPE as PLANTYPE, project0_.PROSJEKTTYPE as PROSJEK15_, project0_.ANSVARSNR as ANSVARSNR, project0_.ANLEGG_STARTDATO as ANLEGG_17_, project0_.ANLEGG_FERDIGDATO as ANLEGG_18_, project0_.GRUNNEIERMOTE as GRUNNEI19_, project0_.PROSJEKT_AVSLUTTET as PROSJEK20_, project0_.SAKSBEHANDLER_GRUNN as SAKSBEH21_, project0_.LANDMALER as LANDMALER, project0_.SAKSBEHANDLER_PLAN as SAKSBEH23_, project0_.SAKSBEHANDLER_DRIFT as SAKSBEH24_, project0_.SAKSBEHANDLER_OPPGJØR as SAKSBEH25_, project0_.MERKNAD1 as MERKNAD1, project0_.STATUS_ERVERV as STATUS_27_ from prosjekt_hoved project0_
18:34:56,298 DEBUG TransactionSynchronizationManager:122 - Retrieved value [org.springframework.orm.hibernate.SessionHolder@135f44e] for key [net.sf.hibernate.impl.SessionFactoryImpl@3f4ebd] bound to thread [main]
18:34:56,298 INFO DefaultProjectService:? - Fetched [4] projects
18:34:56,298 DEBUG TransactionInterceptor:240 - Invoking commit for transaction on method 'fetchAllProjects' in class [no.myproj.ProjectService]
18:34:56,298 DEBUG HibernateTransactionManager:498 - Triggering beforeCommit synchronization
18:34:56,298 DEBUG HibernateTransactionManager:513 - Triggering beforeCompletion synchronization
18:34:56,298 DEBUG HibernateTransactionManager:375 - Initiating transaction commit
18:34:56,308 DEBUG HibernateTransactionManager:460 - Committing Hibernate transaction on session [net.sf.hibernate.impl.SessionImpl@1fcf790]
18:34:56,308 DEBUG HibernateTransactionManager:543 - Triggering afterCompletion synchronization
18:34:56,308 DEBUG TransactionSynchronizationManager:239 - Clearing transaction synchronization
18:34:56,308 DEBUG TransactionSynchronizationManager:170 - Removed value [org.springframework.orm.hibernate.SessionHolder@135f44e] for key [net.sf.hibernate.impl.SessionFactoryImpl@3f4ebd] from thread [main]
18:34:56,308 DEBUG TransactionSynchronizationManager:170 - Removed value [org.springframework.jdbc.datasource.ConnectionHolder@51ef4e] for key [org.apache.commons.dbcp.BasicDataSource@14e4e31] from thread [main]
18:34:56,308 DEBUG DataSourceUtils:251 - Resetting read-only flag of connection [org.apache.commons.dbcp.PoolableConnection@1a7789c]
18:34:56,318 DEBUG HibernateTransactionManager:542 - Closing Hibernate session [net.sf.hibernate.impl.SessionImpl@1fcf790] after transaction
18:34:56,328 DEBUG SessionFactoryUtils:649 - Closing Hibernate session
18:34:56,338 ERROR LazyInitializationException: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
at net.sf.hibernate.collection.PersistentCollection.initialize(PersistentCollection.java:209)
at net.sf.hibernate.collection.PersistentCollection.read(PersistentCollection.java:71)
at net.sf.hibernate.collection.Set.size(Set.java:106)
at no.myproj.Project.toString(Unknown Source)
at org.apache.log4j.or.DefaultRenderer.doRender(DefaultRenderer.java:26)
at org.apache.log4j.or.RendererMap.findAndRender(RendererMap.java:70)
at org.apache.log4j.spi.LoggingEvent.getRenderedMessage(LoggingEvent.java:288)
at org.apache.log4j.helpers.PatternParser$BasicPatternConverter.convert(PatternParser.java:395)
at org.apache.log4j.helpers.PatternConverter.format(PatternConverter.java:56)
at org.apache.log4j.PatternLayout.format(PatternLayout.java:495)
at org.apache.log4j.WriterAppender.subAppend(WriterAppender.java:292)
at org.apache.log4j.WriterAppender.append(WriterAppender.java:150)
at org.apache.log4j.AppenderSkeleton.doAppend(AppenderSkeleton.java:221)
at org.apache.log4j.helpers.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttachableImpl.java:57)
at org.apache.log4j.Category.callAppenders(Category.java:187)
at org.apache.log4j.Category.forcedLog(Category.java:372)
at org.apache.log4j.Category.info(Category.java:674)
at no.myproj.ProjectTestCase.testGetAll(ProjectTestCase.java:37)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:324)
at junit.framework.TestCase.runTest(TestCase.java:154)
at junit.framework.TestCase.runBare(TestCase.java:127)
at junit.framework.TestResult$1.protect(TestResult.java:106)
at junit.framework.TestResult.runProtected(TestResult.java:124)
at junit.framework.TestResult.run(TestResult.java:109)
at junit.framework.TestCase.run(TestCase.java:118)
at junit.framework.TestSuite.runTest(TestSuite.java:208)
at junit.framework.TestSuite.run(TestSuite.java:203)
at junit.textui.TestRunner.doRun(TestRunner.java:116)
at com.intellij.rt.execution.junit2.IdeaJUnitAgent.doRun(IdeaJUnitAgent.java:57)
at junit.textui.TestRunner.start(TestRunner.java:172)
at com.intellij.rt.execution.junit.TextTestRunner2.startRunnerWithArgs(TextTestRunner2.java:23)
at com.intellij.rt.execution.junit2.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:97)
at com.intellij.rt.execution.junit2.JUnitStarter.main(JUnitStarter.java:31)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:324)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:78)
18:34:56,358 DEBUG TransactionSynchronizationManager:122 - Retrieved value [org.springframework.orm.hibernate.SessionHolder@2b349d] for key [net.sf.hibernate.impl.SessionFactoryImpl@2d7440] bound to thread [main]
18:34:56,358 DEBUG TransactionSynchronizationManager:170 - Removed value [org.springframework.orm.hibernate.SessionHolder@2b349d] for key [net.sf.hibernate.impl.SessionFactoryImpl@2d7440] from thread [main]
18:34:56,358 DEBUG SessionFactoryUtils:649 - Closing Hibernate session
Code:
TestCase
public class ProjectTestCase extends TestCase{
private SessionFactory sessionFactory;
public void setUp() throws Exception {
super.setUp();
sessionFactory = (SessionFactory) findSessionFactory();
Session s = sessionFactory.openSession();
TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(s));
}
public void testGetAll() throws Exception {
List allProjects = service.fetchAllProjects();
assertNotNull("Received null value for projects!", allProjects);
assertTrue("Unexpected project state!", allProjects.size() > 0);
for (Iterator i = allProjects.iterator(); i.hasNext();) {
log.info(i.next());
}
}
public void tearDown() throws Exception {
super.tearDown();
SessionHolder holder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
Session s = holder.getSession();
s.flush();
TransactionSynchronizationManager.unbindResource(sessionFactory);
SessionFactoryUtils.closeSessionIfNecessary(s, sessionFactory);
}
}
Code:
Service implementation
public class DefaultProjectService implements ProjectService {
private ProjectDAO projectDAO;
public void setProjectDAO(ProjectDAO projectDAO) {
this.projectDAO = projectDAO;
}
public List fetchAllProjects() {
return projectDAO.fetchAll();
}
}
Code:
DAO implementation
public class ProjectDAOImpl extends HibernateDaoSupport implements ProjectDAO {
public List fetchAll() {
return getHibernateTemplate().find("from no.myproj.Project");
}
}
Code:
Hibernate mapping
<hibernate-mapping>
<class
name="no.myproj.Project"
table="prosjekt_hoved"
dynamic-update="false"
dynamic-insert="false"
select-before-update="false">
<id
name="projectId"
column="PROSJEKTNR"
type="int">
<generator class="increment">
</generator>
</id>
<property
name="projectName"
type="string"
update="true"
insert="true"
access="property"
column="PROSJEKTNAVN"/>
<set
name="properties"
lazy="true"
inverse="false"
cascade="all"
sort="unsorted">
<key
column="EIENDOMSNR"
>
</key>
<one-to-many
class="no.myproj.Property"
/>
</set>
</class>
</hibernate-mapping>
Code:
spring.xml
<beans>
<bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean">
<property name="mappingResources">
<list>
<value>no/myproj/Project.hbm.xml</value>
<value>no/myproj/Property.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">net.sf.hibernate.dialect.OracleDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
<property name="dataSource">
<ref bean="dataSource"/>
</property>
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName">
<value>oracle.jdbc.driver.OracleDriver</value>
</property>
<property name="url">
<value>jdbc:oracle:thin:@127.0.0.1:1521:ORCL</value>
</property>
<property name="username">
<value>username</value>
</property>
<property name="password">
<value>password</value>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate.HibernateTransactionManager">
<property name="sessionFactory">
<ref local="sessionFactory"/>
</property>
</bean>
<bean id="projectDAO" class="no.myproj.ProjectDAOImpl">
<property name="sessionFactory">
<ref local="sessionFactory"/>
</property>
</bean>
<bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
<property name="transactionManager">
<ref bean="transactionManager"/>
</property>
<property name="transactionAttributeSource">
<value>
no.myproj.ProjectService.fetch*=PROPAGATION_REQUIRED,readOnly,-Exception
no.myproj.ProjectService.save=PROPAGATION_REQUIRED,-Exception
no.myproj.ProjectService.delete=PROPAGATION_REQUIRED,-Exception
</value>
</property>
</bean>
<bean id="projectTarget" class="no.myproj.DefaultProjectService">
<property name="projectDAO">
<ref bean="projectDAO"/>
</property>
</bean>
<bean id="projectService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>no.myproj.ProjectService</value>
</property>
<property name="interceptorNames">
<list>
<value>transactionInterceptor</value>
<value>projectTarget</value>
</list>
</property>
</bean>
</beans>