Sorry I led you astray about interceptors not always being singletons. I forgot that can’t be changed.
I don’t know if I 100% follow the code you posted below, but thanks for providing it. As far as the specific question, “How do I inject a short-lived (ie, session) object into an eternal (ie singleton) object?”, here’s you’re answer. The trick with scope-widening injection is that if you just put a straight reference to your session-scoped object into your singleton, then not only with ALL users get whatever the first session object that was passed in (bad), but when that session expires, the hard reference in your singleton will keep it from being collected from memory which is why you say you “widened” the scope of the session object. (also bad)
Three suggestions have been given so far to avoid giving your interceptor a hard reference to a specific session-scoped object:
- Inject another singleton service object into your interceptor which has a method that will return the current session-scoped object
- Inject WireBox itself in (actually it’s already available as variables.wireBox because CB is awesome like that) and simply ask WireBox for the session-scope object when you need it
- Inject a WireBox provider that is essentially a dummy object that doesn’t reference anything, but it “knows” how to get it when you ask. If it is providing a session-scoped object it will always return the appropriate one when you ask it based on the current session.
All three of those options really boil down to the same principle: Inject another object with the same scope of the interceptor that can “find” the object you really need when you ask for it each time.
- The first option is my least favorite simply because it seems like an unnecessary service method. Of course, that could change if your service has some “extra” massaging it wants to do to the session-scoped object prior to returning it. Then it might make perfect sense.
- The second option is probably what I would do if I were coding this. Basically in your WireBox binder config you’d have map(“mySesionObject”).to(“path.to.object”).into(this.SCOPES.SESSION); and in your interceptor you’d simply do wireBox.getInstance(“mySessionObject”) every time you want to use it. Just never store the session-scoped object in the variables or this scope of the interceoptor-- always keep it in a locally-scope variable so it doesn’t bleed over to other people’s session.
- The third option is one of the extra-cool features of WireBox which was designed exactly for this sort of thing. Basically, instead of autowiring mySessionObject directly into the variables scope of the interceptor, you’d do this: property name=“mySessionProvider” inject=“provider:mySessionObject”; This will inject an instance of coldbox.system.ioc.Provider. Then you can call variables.mySessionProvider.get() any time you want the actual object. Even cooler is that the provider class will proxy any method calls via onMissingMethod so variables.mySessionProvider.sessionObjectMethod() will also seamlessly work.
Hopefully that helps a bit.
Thanks!
~Brad
ColdBox Platform Evangelist
Ortus Solutions, Corp
E-mail: brad@coldbox.org
ColdBox Platform: http://www.coldbox.org
Blog: http://www.codersrevolution.com