Reputation: 397
I use Spring.NET AOP for transaction and session management with NHibernate. When user makes several requests too quick - lazy loading is failed with exception "no session or session was closed".
I use SpringSessionContext as CurrentSessionContext in NHibernate configuration
public class FluentSessionFactory : LocalSessionFactoryObject
{
protected override ISessionFactory NewSessionFactory(Configuration config)
{
var conf = Fluently
.Configure()
.Database(
MsSqlConfiguration
.MsSql2008
.ConnectionString(c => c.FromConnectionStringWithKey("MyConnection"))
// TODO: use ExposeConfiguration method
.CurrentSessionContext<SpringSessionContext>()
)
.Mappings(
m => m.FluentMappings
.AddFromAssembly(this.GetType().Assembly)
)
.BuildSessionFactory();
return conf;
}
}
In xml config:
<object id="SessionFactory" type="IndustryTracker.NHibernateRepository.FluentSessionFactory, IndustryTracker.NHibernateRepository">
<property name="DbProvider" ref="DbProvider" />
</object>
and OpenSessionInView module
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<modules runAllManagedModulesForAllRequests="true">
<add name="OpenSessionInView" type="Spring.Data.NHibernate.Support.OpenSessionInViewModule, Spring.Data.NHibernate31"/>
</modules>
</system.webServer>
Application implements next workflow for getting entities from db: View -> Controller -> Manager -> Repository and same to other side. So session is created per request, transaction - per call to manager.
<object id="TransactionManager" type="Spring.Data.NHibernate.HibernateTransactionManager, Spring.Data.NHibernate31">
<property name="DbProvider" ref="DbProvider"/>
<property name="SessionFactory" ref="SessionFactory"/>
</object>
<tx:advice id="TxAdvice" transaction-manager="TransactionManager">
<tx:attributes>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<object id="Pointcut" type="Spring.Aop.Support.SdkRegularExpressionMethodPointcut, Spring.Aop">
<property name="patterns">
<list>
<value>MyAppication.Managers.AccountManager</value>
<value>MyAppication.Managers.CompanyManager</value>
</list>
</property>
</object>
<aop:config>
<aop:advisor advice-ref="TxAdvice" pointcut-ref="Pointcut"/>
</aop:config>
What are possible reasons of such behaviour and how can I solve this problem(Not.LazyLoad() and NHibernateUtil.Initialize() are not acceptable variants in my context)?
Upvotes: 1
Views: 1411
Reputation: 397
After some search I found that problem was in configuration. There was spring WebSupportModule missing http module in config, so the correct one is:
<httpModules>
<add name="Spring" type="Spring.Context.Support.WebSupportModule, Spring.Web"/>
<add name="OpenSessionInView" type="Spring.Data.NHibernate.Support.OpenSessionInViewModule, Spring.Data.NHibernate31"/>
</httpModules>
So Marijn was right - it was weak wiring to spring.
Upvotes: 2
Reputation: 10557
1. Session factory configured for OpenSessionInViewModule
?
You might have forgotten to configure the session factory for the OpenSessionInViewModule
:
<appSettings>
<add key="Spring.Data.NHibernate.Support.OpenSessionInViewModule.SessionFactoryObjectName"
value="SessionFactory"/>
</appSettings>
This has to be done in the app settings.
2. Correct FluentNHibernate based spring session factory?
You seem to be configuring your session factory in code. Have you tried configuring the session factory like described in the docs and on BennyM 's blog? Your NewSessionFactory
method returns a session factory from straight from Fluent NHibernate, bypassing all spring.net support.
3. Is your session factory transaction aware?
<object id="SessionFactory"
type="IndustryTracker.NHibernateRepository.FluentSessionFactory, IndustryTracker.NHibernateRepository">
<property name="DbProvider" ref="DbProvider" />
<!-- provides integation with Spring's declarative transaction management features -->
<property name="ExposeTransactionAwareSessionFactory" value="true" />
</object>
4. Does your controller have dependencies with scope="application"
or no scope definition?
I might have been looking in the wrong direction here. If your controller has dependencies of application
scope, it would mean that quick requests could interfere. The default is "scope="application"
; so you'd want to check collaborators without scope definitions too. See the docs on web scopes.
Upvotes: 1