How can I add interceptor to an interface registration so that it is executed when I call a method from resolved instance (IoC.Resolve) but not when I use an instance that has been injected (as constructor argument) from the inside of my class/object?
In our infrastructure we add an interceptor that opens/closes nhibernate session for every call but then the injected proxy instance will open a session inside of a session and cause deadlocks if you query the same entity in outer and inner session.
I've had a look at this and I don't see any easy way to change the behavior of the interceptor depending on the context in which it is called.
What you could do is create an interceptor that wraps a component with a singleton lifetime that creates a single session and returns the same session while it is not closed. When trying to create a second session, it returns the initial session and increments a sessionCreated counter. When trying to close a session it decrements the sessionCreated counter and only closes it if it is 0
Related
We are using Autofac 4 for DI and I started experimenting with AI a short while ago. Now I created a IdentityTelemetryInitializer class which needs and IIdentityProvider to be able to get the ID of the current authorized user and set it add it to the context. I cannot find a way in which to inject dependencies into a TelemetryInitializer. If I define a contructor that takes an IIdentityProvider, the custom initializer is skipped altogether.
Any ideas are welcome. I was thinking of having the user ID also set as the Thread Principal so that we can access it this way, but I was hoping I could use DI for this?
You cannot inject dependencies using a constructor as the initializer initialized internally using the default (empty) constructor. When you explicitly defined a new ctor you've actually 'removed' the default one, thus the initializer was skipped altogether, as you've mentioned.
Therefore, the only way is to resolve the dependencies during the 'Initialize' method, after registering them on application startup.
ctx.RegisterType<MyService>().As<IService>().AsSelf(); // on application startup
ctx.Resolve<IService>(); // during initializer 'Initialize' method
You might look at the question I asked here
How to have "Request" events with authenticated user id ?
because I had managed to have the TelemetryInitializer working, passing user id via the HttpContext as suggested by #yonisha.
Off course it's not as lean as what you try to achieve.
The Telemetry Initializer is called each time you instanciate a Telemetry class, so really depending of how you manage them. Btw I am looking for good advice/best pratice on that : for the moment I have one private instance on each Controller that need to track something, but that does not smell good due to lifetime of Controller.
I am new to scaldi. I have a class being used in my cloud environment configuration where I want two things to happen.
bind [EnvironmentInfo] to new EnvironmentInfo initWith(_.init())
First, I want it to be a singleton. It retrieves the runtime information (Google AppEngine in this case) and it should do this once on instantiation. It seems like initWith is a good choice.
Next, I want instantiation to be delayed until first request. Following the execution path it is being instantiated well before the first call.
If I can get delayed instantiation, then initWith should move to the class constructor.
My answer ended up being simple. I abstracted the singleton "state" and accessed it as a 'lazy val ...'.
In my app client uses services backed by Observables. Each service call is session based, so that a session has to be started before a business-service method can be called.
In order to init session I made an Observable that does it. My problem is that whenever client uses more than one business-service in parallel, session initialization gets duplicated. Client code is session-agnostic. I need a way to init session in such a way that the session observable only gets called once(when the first business-service method gets called). Basically all subsequent business-observers have to wait for condition(session initialization). Can you draw a pattern for it?
Client code would look like:
protected void onCreate(Bundle savedInstanceState) {
itemService.getItems(10).subscribe(new Observer<List<Item>>() {..});
userService.getProfile().subscribe(new Observer<List<Profile>>() {..});
}
While there're 2 calls, I need to make the session Observable execute once only and make business Observables wait for the session initialization to complete and then start doing its' job.
Thanks.
If the session initialization is an Observable, then you can delay all other Observables that depend on it, using the delay operator with the session initialization Observable as parameter: http://reactivex.io/RxJava/javadoc/rx/Observable.html#delay%28rx.functions.Func1%29
Since you already have a session Observable implemented, one possible solution would be to convert it to an AsyncSubject. It would execute only once and would emit only the last item (or only item) to each subscriber.
Depending on how your session initialization code works, it may be more elegant to use one of the Async operators such as Async.start() or Async.startFuture() to create your session observable.
I use autofac web integration and it works just great to resolve lifetime bound components. But one piece of code is invoked from timer and I'm getting null reference exception somewhere in Autofac.Integration.Web.ContainerProvider.AmbientRequestLifetime.get(). Obviously it is because in timer there is no HttpContext and lifetime can not be obtained.
According to documentation I need to invoke "container.BeginLifetimeScope" and use this lifetime to resolve my component. But the component is quite low-level (networking, messaging) and it has no access to asp's Global object to access container object. Global object also has no access to so low-level component to inject container manually.
To make the problem more difficult, this component can be invoked from web pages and need web request lifetime and it needs to be invoked from timer with manually constructed lifetime (or IDispose+using would be fine too).
How do I deal with situation when 2 types of life time scope is required?
Two things might help you get started in the right direction.
First, builder.Register(...).InstancePerLifetimeScope() will give you 'per-request' as well as 'per-custom-lifetime' scoping.
Second, if you're kicking things off under a timer, create a new lifetime scope manually at the entry point of the timer method wherever it happens to be:
void OnTimer()
{
using (var timerScope = ApplicationContainer.BeginLifetimeScope())
{
var someComponent = timerScope.Resolve(...);
someComponent.DoWork();
}
}
Here, the ApplicationContainer is the one you built in Global.asax when the web request started up - you need to find some way to get at it when the timer ticks.
"core" refers to the initial piece of the application that is loaded.
In order to bind url to places, GWT uses PlaceTokenizer<P extends Place>. When loading the application from the url, it calls the method P getPlace(String token) to retrieve a new instance of the place to call.
due to the asynchronous nature of code splitting, I can't create the place inside a runAsync in this method. So I have to put all the places of my app in the core.
To link places to activity, GWT callsActivity getActivity(Place place) (from com.google.gwt.activity.shared.ActivityMapper) to retrieve a new instance of the activity.
Once again, i have to put all my activities in the core.
Here's what I want to try: Write a custom com.google.gwt.place.shared.Delegate that
bind itself on PlaceChangeRequestEvent. If the AppPiece corresponding to the requestedPlace isn't loaded, it calls event.setWarning(NEED_TO_LOAD_MODULE)
in the confirm(String message) method, always return false when the message equals NEED_TO_LOAD_MODULE (so it doesn't bother the user), and load the module via RunAsync.
Once the module is loaded, call goTo(requestedPlace)
Each AppPiece of my application contains a bunch of activies and the corresponding views. Since the mappers are only called when PlaceChangeEventis fired, i could generate a new instance of my activity via AppPiece.getSomeActivityInstance().
I'm pretty sure this will work, but what bother me is that
Finding wich AppPiece to load depending on the requestedPlace will force me to write code that will be very similar to my mappers
I would like to have my places inside the corresponding AppPiece
Overriding Delegate for this purpose is tricky, and I'm looking for a better solution
You don't have to put all your activities in the core (as you call it): while an Activity instance is retrieved synchronously, it's allowed to start asynchronously. This is where you'd put your GWT.runAsync call.
See http://code.google.com/p/google-web-toolkit/issues/detail?id=5129 and https://groups.google.com/d/topic/google-web-toolkit/8_P_d4aT-0E/discussion