Strange problem with Nancy + Windsor + Gate #5

Closed
akurdyukov opened this Issue Jul 13, 2012 · 17 comments

8 participants

@akurdyukov

Hi,

I'm trying to run Nancy app without http.sys and IIS. The example https://github.com/ArloL/NancyInGate works perfectly with TinyIoC but fails with Windsor. Steps for test:
1. Pull https://github.com/ArloL/NancyInGate project
2. Add NuGet dependency Nancy.Bootstrappers.Windsor
3. Add empty bootstrapper inherited from WindsorNancyBootstrapper
4. Run application
5. Try to access it by http://localhost:8081

After this steps I get:

Nancy.RequestExecutionException: Oh noes! ---> System.NullReferenceException: Object reference not set to an instance of an object.
   at Castle.MicroKernel.Lifestyle.Scoped.CallContextLifetimeScope.GetCachedInstance(ComponentModel instance, ScopedInstanceActivationCallback createInstance)
   at Castle.MicroKernel.Lifestyle.ScopedLifestyleManager.Resolve(CreationContext context, IReleasePolicy releasePolicy)
   at Castle.MicroKernel.Handlers.DefaultHandler.ResolveCore(CreationContext context, Boolean requiresDecommission, Boolean instanceRequired, Burden& burden)
   at Castle.MicroKernel.Handlers.DefaultHandler.Resolve(CreationContext context, Boolean instanceRequired)
   at Castle.MicroKernel.Handlers.AbstractHandler.Resolve(CreationContext context)
   at Castle.MicroKernel.DefaultKernel.ResolveComponent(IHandler handler, Type service, IDictionary additionalArguments, IReleasePolicy policy)
   at Castle.MicroKernel.DefaultKernel.Castle.MicroKernel.IKernelInternal.Resolve(String key, Type service, IDictionary arguments, IReleasePolicy policy)
   at Castle.MicroKernel.DefaultKernel.Resolve(String key, Type service, IDictionary arguments)
   at Castle.Windsor.WindsorContainer.Resolve[T](String key)
   at Nancy.Bootstrappers.Windsor.WindsorNancyBootstrapper.GetModuleByKey(String moduleKey, NancyContext context)
   at Nancy.Routing.DefaultRouteResolver.GetInitializedModuleForMatch(NancyContext context, Tuple`4 routeMatchToReturn)
   at Nancy.Routing.DefaultRouteResolver.CreateRouteAndParametersFromMatch(NancyContext context, Tuple`4 routeMatchToReturn)
   at Nancy.Routing.DefaultRouteResolver.Resolve(String path, NancyContext context, IRouteCache routeCache)
   at Nancy.Routing.DefaultRouteResolver.Resolve(NancyContext context)
   at Nancy.NancyEngine.ResolveAndInvokeRoute(NancyContext context)
   at Nancy.NancyEngine.InvokeRequestLifeCycle(NancyContext context, IPipelines pipelines)
   --- End of inner exception stack trace ---
   at Nancy.NancyEngine.InvokeOnErrorHook(NancyContext context, ErrorPipeline pipeline, Exception ex)

My brief examination shows that there's problem with private cache in CallContextLifetimeScope instance. On first call for WindsorNancyBootstrapper.GetModuleByKey object of type CallContextLifetimeScope exists and returns with CallContextLifetimeScope.ObtainCurrentScope(). But it seems to be disposed - cache is null already.

@chrisnicola

You're probably the first to really test this bootstrapper without ASP.NET and HttpContext. The CallContext is supposed to scope things to the current call chain, but doesn't look like it got called. I don't see the call to HandleRequest in there, so perhaps something changed in Nancy here.

If you look at the interceptor (https://github.com/NancyFx/Nancy.Bootstrappers.Windsor/blob/master/src/Nancy.BootStrappers.Windsor/NancyRequestScopeInterceptor.cs) you can see that it only wraps HandleRequest in that call context (that is what BeginScope() is supposed to do). You might trace through and see what's happening there and if that is indeed being called to create the CallContextLifetimeScope.

@akurdyukov

Well, I've tested this bootstrapper with Nancy.Hosting.Self and it works perfectly.

Ok, I'll find a way to trace through there projects. Am I right that there should be _container.BeginScope for every route through interceptor that uses scoped modules?

@akurdyukov

I've traced a little bit, but no luck.

I think that I do not completely understand some basic principles, but I see following:
1. Interceptor catches invocation of HandleRequest(Request request, Action<NancyContext> onComplete, Action<Exception> onError) method on Nancy.NancyEngine. This method calls real processing (method NancyContext HandleRequest(Request request) on Nancy.NancyEngine in other thread. I do not think there's a place to intercept second HandleRequest.
2. Method Nancy.NancyEngine.HandleRequest(Request request, Action<NancyContext> onComplete, Action<Exception> onError) is directly called from Gate.Adapters.Nancy.NancyAdapter.App(INancyBootstrapper bootstrapper) at line 78.

Maybe correct solution is using method NancyContext HandleRequest(Request request) instead of void HandleRequest(Request request, Action<NancyContext> onComplete, Action<Exception> onError) in Gate.Adapters.Nancy.NancyAdapter.App(INancyBootstrapper bootstrapper)?

@akurdyukov

Also I check Nancy.Hosting.Owin and got the same problem - call for HandleRequest(Request request) is not intercepted and leads to same exception with same stackdump.

AFAIK idea of using Nancy.NancyEngine.HandleRequest(Request request, Action<NancyContext> onComplete, Action<Exception> onError) method is to run handling async from listening thread. Maybe there's some good solution for getting proxified NancyEngine in Nancy.NancyEngine.HandleRequest(Request request, Action<NancyContext> onComplete, Action<Exception> onError) that do not direct dependency on Windsor?

@chrisnicola

I wish I had more time to dig into this, but unfortunately I'm working on two different startups at the moment and will be for at least the next 6 months. I'll admit I built this to satisfy a specific need, but it was also exceptionally difficult. Windsor is a fairly old (though arguably very stable and reliable) container and is arguably very complex compared with some of the modern light-weight alternatives.

That isn't to say one is better or worse, but Nancy's architecture is designed around these modern containers so it is much harder to integrate Windsor seamlessly with Nancy.

Perhaps @grumpydev or @thecodejunkie might have some time to trace this in the next little while.

@akurdyukov

Thank you for comment. I sent mail to nancy-dev group already. Hope we'll come up with some working solution on this problem.

@thecodejunkie
Custodians of the Super-Duper-Happy-Path member

@asgerhallas since you seem to be comfortable with both Nancy and Windsor, perhaps this would be something you'd be interested in helping us look into? 😄

@asgerhallas

@thecodejunkie Sure! I it's not too much a hurry, I have my office packed in boxed these days :)

@thecodejunkie
Custodians of the Super-Duper-Happy-Path member

@asgerhallas been open for 3 months.. think we can managed a bit longer =)

@akurdyukov

Well, I just postponed attempts to use Nancy without HTTP.SYS. But I think I'll return to it someday.

@LodewijkSioen

Bon, seems I ran into an old bug with Nancy, Windsor and Owin hosting here....

@ccellar

@Lodewijk-S have you made any progress regarding this issue? My Windsor Foo is not strong enough yet, to transfer the result of the SO discussion to a solution

@LodewijkSioen

I have a solution here, but it needs some more testing. I completely changed the way Windsor is used by Nancy.

@ccellar

Thx. I'll give it a try 👍

@LodewijkSioen LodewijkSioen referenced this issue Jun 27, 2013
Closed

Fix Castle Windsor Bootstrapper under Owin #12

2 of 2 tasks complete
@horsdal
Custodians of the Super-Duper-Happy-Path member

Since the closing comment on #12 says this is fixed, I'll close this.

@horsdal horsdal closed this Sep 8, 2014
@Grinderofl

I'm letting you guys know that this is still an actual issue.Nancy + Windsor + owin self host + async = scope gets disposed before the request ends, so awaiting after some EF6 queries fails with disposed objectcontext.

I've solved it for our project in a similar fashion by LifestyleScoped() everything that has to be per request and adding it into the context inside a similar wrapper, rather than nearest INancyModule. It seems to work so all good.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment