The Implications of Design for Multiple Controllers on the Model API and the use of Session State
The first thing that comes to mind is how and whether you use session scope. If you're writing an app that'll only ever be called by HTML pages, you may well have things like a shopping cart implemented in session scope. But what happens if you also need to be able to offer a shopping cart to users calling your app using some kind of truly stateless call that doesn't support session scope?
The first thought is just to not use session scope at all. Naively that is fine. There is nothing you can achieve with session state that you couldn't achieve with a more persistent mechanism such as database storage with some kind of automated stored procedures in the database to handle garbage collection on "expired sessions".
Of course, the problem with this is that accessing and mutating data within the session scope is way more performant that database calls. The immediate next thought would be to replicate a session style hash table in the application scope. You'd be able to create a "session" with a UUID within application.sessions (you'd actually wrap this in a Singleton to encapsulate the process and would store the hashtable in the variables scope of "SessionService.cfc") and it'd be easy enough to create and update a time stamp for "LastModified" for each record within the hashtable and a routine that ran every minute to kill expired sessions. Of course, the problem with this approach is that to my knowledge there is no easy way to share the application scope across a web farm so if you wanted to scale using a web farm you'd either need to implement sticky sessions or go back to persisting the "sessions" either in the db or using some kind of independent "session server" that SessionService would call via a remote API.
That said, everything I've read to date (it's not a problem I've had to handle personally) is that sticky sessions make more sense for scaling than sharing session state across servers most of the time, so I think I'm willing to live with this as different implementations could be encapsulated by a SessionService so it shouldn't be too hard to try different approaches if performance became an issue.
What does this mean in practice? It means that before you depend on ANYTHING is the session scope, if you're ever going to consider a truly stateless API for your app (and most of the time you won't - this is a very specific use case), you think carefully whether that data will need to be persistable between remote API calls.
For instance, if you're storing my records per page preferences for list queries in session state, that may be something you can happily leave in session scope and handle within your HTML controller, but if you want to implement a shopping cart, you might want to think twice (depending on your use case) about persisting it in session state as opposed to calling a CartService.getUserCart(UserID:int) or even a CartService.getSessionCart(CartUUID:UUID).
Thoughts?


Probably just a rephrase of what you've said: the database session data mechanism is functionally equivalent to the use of the session scope, you'd just be doing the work yourself. Assuming you have a stateful app, you need to persist session data across requests. How you do that is an implementation detail, and the only reason you wouldn't go with the path of least resistance (the session scope) is because you have a technical impedance mismatch that prevents it .
However, given that you will need to pass a session identifier of some kind, is there any reason to make it anything other than a CF session identifier and go ahead and use the session scope? It's easy enough to take an identifier from an arbitrary transmission type (doesn't have to be cookie or URL) and use it to access the CF session scope. Then you have a DRY mechanism that is effortless for browser-type clients, and you can provide a translation for any other kind of client - and session expiry is taken care of for you.
Jaime
So in short, I'm suggesting building a session scope because in these use cases, the ColdFusion one isn't available. Make sense?
If you turn session management on, there is always a session scope. If you access the session using the same key across multiple requests, you share the session scope across the requests. ColdFusion has a built-in mechanism for keeping the session key hanging around between requests (usually a cookie), and then a nice mechanism for automatically populating the global Session variable by using the key from that cookie to look up its session cache.
As you point out, the cookie/automatic lookup part of it won't work for some clients. So if and when you have a non-cookie aware client, you provide a facade that takes the session key transmitted by whatever means, and uses it to lookup up the CF session cache. If the key is found, populate the Session variable from the CF session cache. If not, issue a new key and insert a blank structure into the CF session cache.
CF handles timeout and cache management for you, and as a bonus cookie-aware clients just work out of the box. Your code just continues to use the Session scope, and doesn't know or care where it came from. And some apps won't need the non-cookie facade at all.
Jaime
Interesting. I'm not sure that it'll work only because I don't know of any mechanism in CF to say "I'm really session 7311462 - go give me my data". That said, I will *definitely* check this out as you are right that it'd be much nicer to let CF take care of the plumbing and garbage collection if possible . . .
If you're in the scenario where you're accessing CFM templates (or CFC endpoints) with a client that lacks cookie support, would it be possible to simply pass the session identifiers (CFID/CFTOKEN, or jsessionid if on JRun) as URL parameters? I'm pretty sure that's mentioned in LiveDocs.
http://www.adobe.com/cfusion/knowledgebase/index.c...