Chong asks:
The short answer to this question is no. There is no defined way of doing so. In fact, working with Applications and Sessions at a high level is something that ColdFusion doesn't support in general. The ServerMonitor API gives you some access into this, but I've always wished ColdFusion made this more formal. For example, I think I should be able to do the following:I am trying to copy a session variable from one application scope to another. Could you please enlighten me if this is possible and what is the best practise method for doing so?
<cfset someapp = getApplication("someotherapp")>
<cfset thesessios = someapp.getSessions()>
Now you can do this via undocumented API calls, but to me, that isn't a real answer.
So considering that we can't get access at a level like that - how can we solve the problem anyway? Here are a few ideas.
- One possibility is to use cookies. Assuming both applications are on the same site, or perhaps the same root site, then a cookie could be used so the application A could 'speak' to application B. Cookies aren't 100% safe of course, but for sending simple messages it could be used. Technically this only works though if the user returns to B.
- You could use database tables to store the information. Let's say app A and app B share a common DSN. You could easily record a message when in app A that app B will pick up. The issue here is connecting a session in app A to a session in app B. You need some unique value, like an email address, that both applications would be able to use to sync up the users.
- You could use the Server scope in a similar fashion. This has the drawback though of losing the data if the server restarts.
- Another option would be to perhaps consider migrating the separate applications into one main application. Each 'sub app' can handle keeping its own data separate into a particular portion of the Application and Session scope.
Anyone else doing this? In general I've never had to worry about it. I ran into this a bit at RIAForge. RIAForge uses my blogware, forum, wiki, and bug tracker apps. (Geeze, when do I have time to play GTA??) Each of these applications have their own sessions and application scopes. In order to ease the process for users on the site I used my own hacked up SSO (single sign on) code. This doesn't copy session values over, but basically tries to re-authenticate the user in the new Application space. Not the best code I've written, but it works (afaik).
Archived Comments
I wrote an application a few years back that allowed the admin to view and inspect variables in sessions across all the applications on a server. I will see if I can dig up that little bit of code.
But did it use the internal APIs? If so - then that's the same problem I mentioned above. Yes, you can do it - but you can't be sure it's going to actually work.
Unforunately it used undocumented APIs and function calls.
Seeing how you can't directly 'talk' from one application's session to another, you could serialize the whole session scope into a WDDX packet, store it somewhere such as in a dabase, then have the oter app pick up that WDDX packet and deserialize it back into a struct. Now how you would 'stick' that session back to a particular user, well...
"In order to ease the process for users on the site I used my own hacked up SSO (single sign on) code." <- Would you mind sharing this code?
You can download all of RIAForge. Just go to the site- its on the FAQ.
I've use 2 different tricks with mild success. Both of these assume both applications run in the same instance of your favorite CFML engine.
1) Switching application names on a page (only tested on ColdFusion), this is how I integrate blogCFC with out logon framework.
The pseudo code would be something like
Declare Current Application
if NOT session.init()
Declare Application_shared
request.session = session (or duplicate(session))
Redeclare Current Application
append request.session to session
end if
2) This solution requires a rudimentary understanding of what is going on with the Java underpinnings, AND the use J2EE session variables to be check (or at least I have had some issues if this is not checked). Remember that each application you run is a single Java application, remember I am assuming you are using only 1 instance of CFML engine. Since you are running in a Single Java application a user has exactly 1 J2EE session and anything you want to share between CFML applications can be set in the User's J2EE session getContext().getSession().setAttribute()/getAttribute()
Thanks!
If both apps are written by the same person/company, is it fair to say that the very fact that this need exists may expose a flaw in application design? I don't mean that in a mean way.. I just mean, is this solution not the answer, and perhaps the solution fundamentally should be some DB persistence or webservice?
Just a thought. I wish I knew more details of the need. Maybe I just shouldn't write rambling blog comments after coming from the dentist.. :-D
Hi Ray, thanks for answering that question. It seems something to ask for in CF9, out of the box. Perhaps the undocumented API and function calls should be refined and expanded by Adobe, and be made official/documented.
I have an idea that is so uncreative that there is probably a reason why it would not work. You could copy references of applications' internal scopes to server scope in the Application.cfc functions. This could be done through a cfc in server scope or simply structure references.
For example on appstart have:
server.applications["appname"] = application;
in session start have:
server.applications["appname"].session["sessionid"]=session;
then you could access data like so
server.applications["appname"].sessions["sessionid"];
...this would probably require additional work on session and app end to clear out dead references but you get the general idea.
If this could be automatically inherited by, or injected into, Application.cfc without changing existing code that would of course be ideal.
Has a good solution been figured out for this. I ran into this just now.
This is an old post Adrian, but on reading it again - I really think using the database would be the best solution.