PDA

View Full Version : Spring.net + NHibernate , no CurrentSessionContext configured



kenghaochen
06-15-2007, 03:55 AM
I use Spring.net 1.1 and NHibernate 1.2, but when I query via NHiberante, following exception occured

No CurrentSessionContext configured (set the property hibernate.current_session_
context_class)!
NHibernate.HibernateException: No CurrentSessionContext configured (set the prop
erty hibernate.current_session_context_class)!
於 NHibernate.Impl.SessionFactoryImpl.GetCurrentSessi on()
於 SpringConTest.CUDAO.findAll() 於 C:\code\VB2005\SpringConTest\SpringConTes
t\CUDAO.vb: 行 16
於 SpringConTest.Module1.Main() 於 C:\code\VB2005\SpringConTest\SpringConTest
\Module1.vb: 行 16


and My config like follow
<?xml version="1.0" encoding="utf-8" ?>
<objects xmlns='http://www.springframework.net'>
<object id="cu" type="SpringConTest.CU,SpringConTest">
<property name="name" value="Michael Chen"/>
</object>

<object id="MySessionFactory" type="Spring.Data.NHibernate.LocalSessionFactoryObject,S pring.Data.NHibernate12">
<property name="DbProvider" ref="DbProvider"/>
<property name="MappingAssemblies">
<list>
<value>SpringConTest</value>
</list>
</property>
<property name="HibernateProperties">
<dictionary>
<entry key="hibernate.connection.provider"
value="NHibernate.Connection.DriverConnectionProvider"/>
<entry key="hibernate.dialect"
value="NHibernate.Dialect.MsSql2005Dialect"/>
<entry key="hibernate.connection.driver_class"
value="NHibernate.Driver.SqlClientDriver"/>
<entry key="hibernate.current_session_context_class"
value="thread"/>

</dictionary>
</property>
</object>
<object id="CUDAO" type="SpringConTest.CUDAO,SpringConTest">
<property name="SessionFactory" ref="MySessionFactory"/>
</object>


</objects>



How can I resolve this problem ?

Mark Pollack
06-15-2007, 05:01 PM
Hi,

In your configuration your are specifying the value of 'thread' for the property hibernate.current_session_context_class. This is not a supported value, you should probably see an error message from NHibernate in your log saying 'Unable to construct current session context [thread]'.

Out-of-the-box NHibernate provides an implementation of the ICurrentSessionContext interface which can be used in a web environment and is refered to via the name 'managed_web'. Read the NHibernate docs on this (http://www.hibernate.org/hib_docs/nhibernate/1.2/reference/en/html/architecture.html#architecture-current-session) for more informaiton.

Spring provides an implementation of ICurrentSessionContext that you can use. This will let you use the plain NHibernate 1.2 API in your data access code and participate in Spring's transaction management functionality, in this case you would use a HibernateTransactionManager. You can configure this by setting the property 'ExposeTransactionAwareSessionFactory' to true on LocalSessionFactoryObject. This is just a short-cut for setting the NHibernate property current_session_context_class with the name of the implementation class to use. If you use Spring's HibernateTransactionManager then one session is created for the transaction and bound the thread local storage, which is what will be returned by calls to ISessionFactory.GetCurrentSession()


Cheers,
Mark

Apo007
06-27-2007, 10:39 AM
Hi!

I have the same problem but I don't really understand what you mean... I try this in my DAO.xml:



<object id="sessionFactory" type="Spring.Data.NHibernate.LocalSessionFactoryObject, Spring.Data.NHibernate12">
<property name="DbProvider" ref="dbProvider"/>
<!--<property name="ExposeTransactionAwareSessionFactory" value="true"/>-->
<property name="MappingAssemblies">
<list>
<value>ApoNHSTest.BLL.Domain</value>
</list>
</property>
<property name="HibernateProperties">
<dictionary>

<entry key="hibernate.connection.provider"
value="NHibernate.Connection.DriverConnectionProvider"/>

<entry key="hibernate.dialect"
value="NHibernate.Dialect.MsSql2000Dialect"/>

<entry key="hibernate.connection.driver_class"
value="NHibernate.Driver.SqlClientDriver"/>

<!--<entry key="hibernate.current_session_context_class"
value="managed_web"/>-->

</dictionary>
</property>
</object>

<object id="HibernateTransactionManager"
type="Spring.Data.NHibernate.HibernateTransactionManager , Spring.Data.NHibernate12">

<property name="DbProvider" ref="dbProvider"/>
<property name="SessionFactory" ref="sessionFactory"/>
</object>

<object id="clientDAO" type="ApoNHSTest.DAL.DAO.ClientDAO, ApoNHSTest.DAL">
<property name="sessionFactory" ref="sessionFactory"/>
</object>


and this is my Services.xml:



<object id="clientServices" type="ApoNHSTest.BLL.Services.ClientServices, ApoNHSTest.BLL.Services">
<property name="clientDAO" ref="clientDAO"/>
</object>

<object id="TxProxyConfigurationTemplate" abstract="true"
type="Spring.Transaction.Interceptor.TransactionProxyFac toryObject, Spring.Data">

<property name="PlatformTransactionManager" ref="HibernateTransactionManager"/>

<!--<property name="Target" ref="clientServices"/>-->

<property name="TransactionAttributes">
<name-values>
<!-- Add common methods across your services here -->
<add key="Get*" value="PROPAGATION_REQUIRED"/>
</name-values>
</property>
</object>

<object id="clientServicesUsingTxPFO" parent="TxProxyConfigurationTemplate">
<property name="Target" ref="clientServices"/>
</object>


When I use <property name="ExposeTransactionAwareSessionFactory" value="true"/> and I call in my Main()

IClientServices clientServices = ctx["clientServices"] as IClientServices;
clientServices.GetClient(1);

I get "Process is terminated due to StackOverflowException." with the ExposeTransactionAwareSessionFactory property.

I use DAO based on plain NHibernate API. I know that NHibernate 1.2 just supports managed_web and that Spring.NET offer an additionnal implementation of the current_session_context_class but I don't know its name (thread is for Hibernate...) or how to plug it correctly.


Thanks for the help !

Mark Pollack
06-27-2007, 03:16 PM
Hi,

How embarassing, I made a recursive call when setting the property ExposeTransactionAwareSessionFactory. This fix is in CVS now, I'll trigger a build so you can download an updated dll. Mor e importantly, I'll update the docs (currenlty Sec 19.2.5 (http://www.springframework.net/doc-1.1-M1/reference/html/orm.html#orm-hibernate-straight)) to show the specific configuration XML for this case. The general idea is what you did, i.e. you should set either ExposeTransactionAwareSessionFactory to true on LocalSessionFactoryObject, which is equivalent to registering the key

<entry key="hibernate.current_session_context_class"
value="Spring.Data.NHibernate.SpringSessionContext, Spring.Data.NHibernate"/>

within HibernateProperties.

Let me know if you run into any more issues with this approach, I'll update one of the example apps to use this functionality.

Cheers,
Mark

Apo007
06-27-2007, 03:36 PM
Thanks for the answer !

I try



<object id="sessionFactory" type="Spring.Data.NHibernate.LocalSessionFactoryObject, Spring.Data.NHibernate12">
<property name="DbProvider" ref="dbProvider"/>
<!--<property name="exposeTransactionAwareSessionFactory" value="true" />-->
<property name="MappingAssemblies">
<list>
<value>ApoNHSTest.BLL.Domain</value>
</list>
</property>
<property name="HibernateProperties">
<dictionary>

<entry key="hibernate.connection.provider"
value="NHibernate.Connection.DriverConnectionProvider"/>

<entry key="hibernate.dialect"
value="NHibernate.Dialect.MsSql2000Dialect"/>

<entry key="hibernate.connection.driver_class"
value="NHibernate.Driver.SqlClientDriver"/>

<entry key="hibernate.current_session_context_class"
value="Spring.Data.NHibernate.SpringSessionContext, Spring.Data.NHibernate"/>
</dictionary>
</property>
</object>


but I get :Exception non gérée : NHibernate.HibernateException: No CurrentSessionContext configured (set the property hibernate.current_session_context_class)!

I try with



<entry key="hibernate.current_session_context_class" value="Spring.Data.NHibernate.SpringSessionContext, Spring.Data.NHibernate12"/>


and finally I get

Exception non gérée : NHibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here

Thanks

Mark Pollack
06-27-2007, 03:54 PM
Hi,
Yes, that class is only in the assembly Spring.Data.NHibernate12 (it is a 1.2 feature), my bad. I'll investigate more and get back to you shortly. Thanks for reporting the issue.
Mark

Apo007
06-27-2007, 04:33 PM
OK and thanks for all!

Spring.NET rocks!

Mark Pollack
06-27-2007, 05:18 PM
Hi,

You seemed to indicate in your previous email that there was still an error even after you registered the current_session_context_class from the correct spring namespace. Is that still the case? In my tests I didn't encounter this so it maybe something else if you are experiencing an error.

The DAO code should be accessing the current session like so,


public void Create(TestObject to)
{
SessionFactory.GetCurrentSession().Save(to);
}


and have some transactional advice around that method, say at the service layer.

Cheers,
Mark

Apo007
06-28-2007, 11:27 AM
Hi !

Yes, sorry, you must be right !


I've just testing it whith the TransactionAtribute and a DeclarativeServicesAttributeDriven.xml, it's working great! (I need to use the sessionFactory.GetCurrentSession().Get() instead of Load because the proxy can't be initialize: it depends on the architecture, doesn't it ?)

But if I try a DeclarativeServicesTxProxyFactoryDriven.xml I get the issue I wrote before. Could you just take a look at my services.xml file from my previous post, please ?

I thought we could use two possiblities to weave advices to the code (I tried AspectDNG) by using :
-attributes
-xml weaving mode through:



<property name="TransactionAttributes">
<name-values>
<!-- Add common methods across your services here -->
<add key="Get*" value="PROPAGATION_REQUIRED"/>
</name-values>
</property>


My ClientDAO.cs looks like:



public class ClientDAO : IClientDAO {

private ISessionFactory sessionFactory;

public ISessionFactory SessionFactory {
get { return sessionFactory; }
set { sessionFactory = value; }
}

public Client SelectById(int id) {
return sessionFactory.GetCurrentSession().Get<Client>(id);
}
...
}


and my ClientServices.cs



//using Spring.Transaction.Interceptor;
...
public class ClientServices : IClientServices {

private IClientDAO clientDAO;

public IClientDAO ClientDAO {
get { return clientDAO; }
set { clientDAO = value; }
}

//[Transaction(ReadOnly = false)]
public Client GetClient(int id) {
return clientDAO.SelectById(id);
}
...
}

Thank you for the time and effort you have devoted to look on my problem!

Apo007
06-28-2007, 01:56 PM
I solved my problem, I didn't use the proxy but the clientServices



IClientServices clientServices = ctx["clientServices"] as IClientServices;


instead of



IClientServices clientServices = ctx["clientServicesUsingTxPFO"] as IClientServices;


Sorry

Mark Pollack
06-28-2007, 03:39 PM
Hi,

Glad you are on the right path now. You can avoid getting a reference to the unadvised object by declaring it as an inner-object, i.e,



<object id="clientServicesUsingTxPFO" parent="TxProxyConfigurationTemplate">
<property name="Target">
<object type="ApoNHSTest.BLL.Services.ClientServices, ApoNHSTest.BLL.Services">
<property name="clientDAO" ref="clientDAO"/>
</object>
</property>
</object>


In which case, it would be better to name the object simply 'clientServices' instead of the one with the UsingTxPFO suffice. The docs have some dicussion on this approach. (refs: 1 (http://www.springframework.net/doc-latest/reference/html/objects.html#objects-inline-object),2 (http://www.springframework.net/doc-latest/reference/html/transaction.html#tx-txproxyfactoryobject))

Cheers,
Mark

PainyJames
04-28-2011, 10:47 AM
Sorry for bumping an old thread, but I have exactly this very problem.


Test method Hogaza.DataTests.HogazaIntegrationTests.testOfferD AO threw exception:
NHibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here


Spring.Data.NHibernate.SpringSessionContext.Curren tSession() in c:\_svn\spring-net\tags\spring-net-1.3.1\src\Spring\Spring.Data.NHibernate12\Data\NHi bernate\SpringSessionContext.cs: line 70
NHibernate.Impl.SessionFactoryImpl.GetCurrentSessi on() in d:\CSharp\NH\nhibernate\src\NHibernate\Impl\Sessio nFactoryImpl.cs: line 1002
Hogaza.DAO.NHibernate.AbstractHibernateDAO.get_Cur rentSession() in C:\Documents and Settings\Administrador\mis documentos\visual studio 2010\Projects\Hogaza\Project1\DAO\NHibernate\Abstr actHibernateDAO.cs: line 38
Hogaza.DAO.DAOI.OfferDAO.Create(Offer offer) in C:\Documents and Settings\Administrador\mis documentos\visual studio 2010\Projects\Hogaza\Project1\DAO\DAOI\OfferDAO.cs : line 28
Hogaza.DataTests.HogazaIntegrationTests.testOfferD AO() in C:\Documents and Settings\Administrador\mis documentos\visual studio 2010\Projects\Hogaza\Hogaza.DataTests\DataTests\Ho gazaIntegrationTests.cs: line 54


As I point out with that bolding line, NHibernate guesses I'm using the nhibernate12 assemblies from spring, which I'm not since I'm using NHibernate 3.0.0.4000, the version that matches with the supported by nhibernate30 from spring 1.3.1.

I configured the hibernate properties on the hibernate session factory allocated on the Dao.xml file.
Like this:

<!-- NHibernate Configuration -->
<object id="NHibernateSessionFactory" type="Hogaza.DAO.NHibernate.CustomLocalSessionFactoryObj ect, Hogaza.Data">
<property name="DbProvider" ref="DbProvider"/>
<property name="MappingAssemblies">
<list>
<value>Hogaza.Data</value>
</list>
</property>
<property name="HibernateProperties">
<dictionary>
<entry key="hibernate.connection.provider" value="NHibernate.Connection.DriverConnectionProvider"/>
<entry key="dialect" value="NHibernate.Dialect.MsSql2008Dialect"/>
<entry key="connection.driver_class" value="NHibernate.Driver.SqlClientDriver"/>
<entry key="hibernate.current_session_context_class" value="Spring.Data.NHibernate.SpringSessionContext, Spring.Data.NHibernate30"/>
<entry key="use_proxy_validator" value="false"/>
</dictionary>
</property>

But, yet, Spring.Data.NHibernate.SpringSessionContext, Spring.Data.NHibernate12 is used.

Please, help me out with this one, and thanks in advance.

PainyJames
04-29-2011, 01:11 AM
Ok, this was the problem



using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Spring.Testing.Microsoft;

namespace Hogaza.DataTests
{
/// <summary>
/// Loads the application contexts needed for DAO testing performance
/// </summary>
public abstract class AbstractDaoIntegrationTests :AbstractDependencyInjectionSpringContextTests
{

/// <summary>
/// Configuration to load for the test subclasses
/// </summary>
protected override string[] ConfigLocations
{
get { return new String[] { "assembly://Hogaza.Data/Hogaza.DAO/DAO.xml" }; }
}

}
}



Instead of subclassing from AbstractTransactionalDbProviderSpringContextTests :



using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Spring.Testing.Microsoft;

namespace Hogaza.DataTests
{
/// <summary>
/// Loads the application contexts needed for DAO testing performance
/// </summary>
public abstract class AbstractDaoIntegrationTests : AbstractTransactionalDbProviderSpringContextTests
{

/// <summary>
/// Configuration to load for the test subclasses
/// </summary>
protected override string[] ConfigLocations
{
get { return new String[] { "assembly://Hogaza.Data/Hogaza.DAO/DAO.xml" }; }
}

}
}


Kinda weird error output tho.