WcfIntegration and NHibernateIntegration

24 views
Skip to first unread message

AndyKnight

unread,
Jun 2, 2009, 11:16:56 AM6/2/09
to Castle Project Users
Hi all,
Im trying to get the two facilities, WCFIntegration and
NHibernateIntegration working together so that I can get one session
per wcf request. And I think I'm almost there, just one final hurdle
Im suffering with.

So Ive setup an SessionEndpointBehavior class which has
ISessionManager and IKernel dependencies. It generates a
SessionInstanceProvider like so:
public void ApplyDispatchBehavior(ServiceEndpoint endpoint,
EndpointDispatcher endpointDispatcher)
{
Type serviceType =
endpointDispatcher.ChannelDispatcher.Host.Description.ServiceType;
endpointDispatcher.DispatchRuntime.InstanceProvider = new
SessionInstanceProvider(serviceType, sessionManager, kernel);
}

SessionInstanceProvider implements IInstanceProvider and has the
following GetInstance method:

public object GetInstance(InstanceContext instanceContext,
Message message)
{
session = sessionManager.OpenSession();
kernel.AddComponentInstance(NHibernateSessionKey,typeof
(ISession),session);

return kernel[serviceType.FullName];
}

And lastly, Ive added the SessionEndpointBehaviour as a component in
my web.config. WindsorContainer is initialised in the global.asax
file.
The Wcf service markup references
Castle.Facilities.WcfIntegration.DefaultServiceHostFactory and the
class has an ISession dependency in the constructor.

Everything works, Getinstance() is called and a session is put into
the kernel.
However, my wcf service cant find the ISession dependency:

Can't create component 'WCFHost.TestService' as it has dependencies to
be satisfied.
WCFHost.TestService is waiting for the following dependencies:

Services:
- NHibernate.ISession which was not registered.


I see that SessionManager.OpenSession() returns a SessionDelegate
instance, but this implements ISession, so I dont understand why its
failing.

Im assuming that when I provide IKernel as a dependency to
SessionEndpointBehavior, castle is using the currently instantiated
windsor container, is that correct?

Any suggestions appreciated

Andy

Craig Neuwirt

unread,
Jun 2, 2009, 11:34:02 AM6/2/09
to castle-pro...@googlegroups.com
Would it be possible to create a test case for this?

Andyk

unread,
Jun 2, 2009, 11:50:06 AM6/2/09
to Castle Project Users
Well, I think the problem is simply that Im adding a session generated
by the SessionManager, into the container, but its not resolving it
later on.
A test case might look like:

[Test]
public void Should_resolve_session_provided_by_SessionManager()
{
IKernel kernel = new DefaultKernel();
kernel.Register(Component.For<ITestService>
().ImplementedBy<TestService>());

var session = sessionManager.OpenSession();
kernel.AddComponentInstance("NHibernate.Session",session);

var result = kernel.Resolve<ITestService>();
}

public class TestService:ITestService
{
private readonly ISession session;

public TestService (ISession session)
{
this.session = session;
}

public void DoWork()
{
throw new NotImplementedException();
}
}
public interface ITestService
{
void DoWork();
}

Is this what you mean?

Craig Neuwirt

unread,
Jun 2, 2009, 12:03:16 PM6/2/09
to castle-pro...@googlegroups.com
I can't remember the exact details of the NHib Facility, but it does seem a little unusual to put the ISession in the container.   WHen you resolve the instance, may you should add the ISession in the custom dependnecies collection and do a Resolve with the custom dependencies.

Andyk

unread,
Jun 2, 2009, 12:20:31 PM6/2/09
to Castle Project Users
Actually it seems my original problem was having IKernel as a
dependency.
I changed it to be IWindsorContainer and added the following line in
global:
container = new WindsorContainer(new XmlInterpreter());
container.Register(Component.For<IWindsorContainer>
().Instance(container));

Regarding putting the session in the container, which custom
dependencies collection do you refer to?

Right now I do have a problem with the container releasing the
session:

public void ReleaseInstance(InstanceContext instanceContext,
object instance)
{
if (session != null)
{
container.Release(session);
session.Close();
session = null;
}
}


On Jun 2, 5:03 pm, Craig Neuwirt <cneuw...@gmail.com> wrote:
> I can't remember the exact details of the NHib Facility, but it does seem a
> little unusual to put the ISession in the container.   WHen you resolve the
> instance, may you should add the ISession in the custom dependnecies
> collection and do a Resolve with the custom dependencies.
>

Craig Neuwirt

unread,
Jun 2, 2009, 12:25:54 PM6/2/09
to castle-pro...@googlegroups.com
The kernel has a Resolve<T>(string key, IDictionary customDependencies)  If your service has a ctor arg ISession session, then if you add the ISession to the customDependencies dictionary with key session, the service will use it when resolved.

Andyk

unread,
Jun 3, 2009, 4:36:32 AM6/3/09
to Castle Project Users
So if I want to insert a session per request into the
customDependencies, do I new to new up a fresh instance every time, or
keep the customDependencies dictionary as a static object?


On 2 June, 17:25, Craig Neuwirt <cneuw...@gmail.com> wrote:
> The kernel has a Resolve<T>(string key, IDictionary customDependencies)  If
> your service has a ctor arg ISession session, then if you add the ISession
> to the customDependencies dictionary with key session, the service will use
> it when resolved.
>

Andyk

unread,
Jun 3, 2009, 4:52:46 AM6/3/09
to Castle Project Users
ok I did the following in the InstanceProvider:

public object GetInstance(InstanceContext instanceContext,
Message message)
{
session = sessionManager.OpenSession();
Hashtable dependencies = new Hashtable();
dependencies.Add(NHibernateSessionKey,session);
container.AddComponentProperties<string, Hashtable>
(NHibernateSessionKey, dependencies);
return container[serviceType.FullName];
}

but my service still returns an exception, NHibernate.ISession was not
registered.

Craig Neuwirt

unread,
Jun 3, 2009, 8:07:37 AM6/3/09
to castle-pro...@googlegroups.com
I think it would be more like

         session = sessionManager.OpenSession();
          Hashtable dependencies = new Hashtable();
          dependencies.Add("sessopm", session);
          return container.Resolve(serviceType.FullName, dependencies);

This assumes the serviceType ctor has an argument called session of type ISession

Andyk

unread,
Jun 3, 2009, 9:34:48 AM6/3/09
to Castle Project Users
Thats dont it, its working, fantastic.

Does the dependency object need to be disposed in a certain way.
Currently my ReleaseInstance method just calls session.close and then
session=null
However the session seems to permamently stay closed on any subsequent
requests?

On 3 June, 13:07, Craig Neuwirt <cneuw...@gmail.com> wrote:
> I think it would be more like
>          session = sessionManager.OpenSession();
>           Hashtable dependencies = new Hashtable();
>           dependencies.Add("sessopm", session);
>           return container.Resolve(serviceType.FullName, dependencies);
>
> This assumes the serviceType ctor has an argument called session of type
> ISession
>

Andyk

unread,
Jun 3, 2009, 9:41:17 AM6/3/09
to Castle Project Users
Or alternatively, should a wcf service have a specific lifestyle?
Maybe thats the issue.

Craig Neuwirt

unread,
Jun 3, 2009, 9:49:01 AM6/3/09
to castle-pro...@googlegroups.com
On Wed, Jun 3, 2009 at 8:34 AM, Andyk <andym....@googlemail.com> wrote:

Thats dont it, its working, fantastic.

great!


Does the dependency object need to be disposed in a certain way.
Currently my ReleaseInstance method just calls session.close and then
session=null
However the session seems to permamently stay closed on any subsequent
requests?

I would think doing the close would work.  However, remember that the ISession you
get is a wrapper that has rules for when it can be closed or released.  So repeated
OpenSession is returning a closed session?
 

Craig Neuwirt

unread,
Jun 3, 2009, 10:00:27 AM6/3/09
to castle-pro...@googlegroups.com
WCF Services are typically best handled as singletons

Andyk

unread,
Jun 3, 2009, 10:07:17 AM6/3/09
to Castle Project Users
Thats correct.
One the first request everything is fine, session is opened in the
GetInstance, the wcfservice uses the session fine, then the
ReleaseInstance closes the session.
Upon execution of the 2nd request, a new session is created in the
GetInstance, and its properties show IsOpen=true.
But immediately breaking in the wcf service, the session.IsOpen=false.

Curiously I added a new guid to the customdependency in GetInstance,
and included it on wcf service constructor.
On the 2nd request, despite Getinstance generating a new guid and
inserting it into the customdependency object, the wcf service
received guid is still the origin.

So is the Resolve<T>(type, dependency) not using the latest dependency
collection?

On 3 June, 15:00, Craig Neuwirt <cneuw...@gmail.com> wrote:
> WCF Services are typically best handled as singletons
>

Craig Neuwirt

unread,
Jun 3, 2009, 10:11:05 AM6/3/09
to castle-pro...@googlegroups.com
Yes, so in this case, your service lifestyle should be transient and you should do a Kernel.ReleaseComponent in ReleaseInstance

Andyk

unread,
Jun 3, 2009, 10:34:42 AM6/3/09
to Castle Project Users
Brilliant, works everytime now. Thanks for your time and help Craig!


On 3 June, 15:11, Craig Neuwirt <cneuw...@gmail.com> wrote:
> Yes, so in this case, your service lifestyle should be transient and you
> should do a Kernel.ReleaseComponent in ReleaseInstance
>

Craig Neuwirt

unread,
Jun 3, 2009, 10:43:03 AM6/3/09
to castle-pro...@googlegroups.com
cool

Craig Neuwirt

unread,
Jun 3, 2009, 10:44:30 AM6/3/09
to castle-pro...@googlegroups.com
Are you interested in sending me your wcf integration code.  It would be useful to others and possible something to integrate into WCF Facility

On Wed, Jun 3, 2009 at 9:34 AM, Andyk <andym....@googlemail.com> wrote:

Andyk

unread,
Jun 3, 2009, 7:35:21 PM6/3/09
to Castle Project Users
I can certainly do that. Give me a a few hours and I'll translate it
into a sample project and send it over to you tomorrow!
Reply all
Reply to author
Forward
0 new messages