request collection (rc): cached?

I'm going crazy... maybe, this is a dumb question... but... On a site,
I changed for production usage the config setting "handlerCaching"
from false to true (as this is a recommendation in the docs). Now, I'm
getting strange issues. On the page http://wiki.coldbox.org/wiki/ColdBox.cfm
it says "The Request Collection is a central repository of information
that is refreshed on every user request with the request's
information." - repeat "refreshed on EVERY user request". But it
doesn't refresh in my case.
For a sample reproduction of the issue, I've taken the sample app, and
changed in General.cfc the "rc.welcomeMessage" to something else
(<cfset rc.welcomeMessage='abcd' />. The output actually didn't
change! Unless I did a "?fwreinit=true" in the URL. Does this mean,
that the "Request Collection" is also cached??? Next, I tried "<cfset
rc.welcomeMessage = 'This is a Test #RandRange(1,10)#' />. In the
output, the number actually DID change on each page reload, so not
everything is cached...
What's wrong here? I'm using 3.0RC1. Any help would be appreciated,
because the site should go live in a week!

I've taken the sample app, and
changed in General.cfc the "rc.welcomeMessage" to something else
(<cfset rc.welcomeMessage='abcd' />. The output actually didn't
change! Unless I did a "?fwreinit=true" in the URL.

The request collection was not cached, but the handler object WAS cached, meaning the old code was still in place. It is expected behavior to have to reinit the framework to pick up a CODE change to a handler if handler caching is turned on because the handler CFC isn't recreated every request-- the CFC is created once and stored in memory. So the rc variable was still being set to the old string every time.

Does that make sense?

I use the environment control to keep handler caching OFF on development and ON for production. That way I can develop without having to continually reinit. However, performance has caused me to keep some things like model caching on for dev because dev was just too slow recreating all my services and their dependencies on every request. (I'm hoping CacheBox and WireBox performance fixes will have helped that)

Thanks!

~Brad

Doesn't explain the Rand version staying the same though, unless I'm
missing something. That said, *nothing* would work if rc was cached --
you couldn't submit forms, for instance.

Dave

The rand version didn't stay the same according to the OP.

" In the output, the number actually DID change on each page reload,"

~Brad

Brad,

I'm still confused... HOW can I set rc variables for each request? Or
will they be set if content is coming from a query for example or from
a session var (see below)?

What I actually do in my app is: Store some settings (for examle site
language) for the user in the session scope (with the SessionStorage-
Plugin). Then, in the RequestStart-Handler (or in an interceptor), I
copy those settings (actually it's a Struct; let's call it
"siteSettings") into the rc-Scope (<cfset rc.siteSettings =
instance.sessionStorage.getVar("siteSettings",StructNew()) />). And
then use that rc.siteSettings-Struct in other parts of the request
flow. Actually, this does seem to work - probably, the
rc.siteSettings is overwritten with the session content like the
RandExample in the example before?. BUT: If the session times out
(what I do to reproducte this ist just delete my cookies), the rc
content stays! (it shout be filled actually with an empty struct if
there's no sessioStorate.siteSettings)
Any ideas?

I think the handler caching has exposed thread issues on your handlers. Meaning I would run a tool like varscoper to make sure your handlers are thread safe.

Luis F. Majano
President
Ortus Solutions, Corp

ColdBox Platform: http://www.coldbox.org
Linked In: http://www.linkedin.com/pub/3/731/483
Blog: http://www.luismajano.com
IECFUG Manager: http://www.iecfug.com

Well, I've just tried the "session stuff" within a "cached"
environment. Actually, I was not able to modify a value of a session
variable - whether in my handler nor in a model (<cfset
instance.sessionstorage.setvar("testvariable",7) /> or <cfset
rc.testvariable = instance.testmodel.testmethod() />.
What does work (but definitly isn't the "right" way) => In a view
<cfset session.cbstorage.testvariable = 12 />, then if I do a <cfset
rc.testvariable = instance.sessionstorage.getvar("testvariable") />
I'll get "12"...
Am I doing something completely wrong? How/where do I have to store
this user settings, and how do I get those variables (in a cached
environment)

HOW can I set rc variables for each request?

I'm not sure what you are asking. The request collection is stored in the session scope and is recreated each request. What you put in there over the course of the request IS specific to that request. Of course, if you put the same data in there for every request, it might have appeared to not have changed.

Or will they be set if content is coming from a query for example or from
a session var (see below)?

It doesn't really matter where you get the data from that you set in, the rc is still per-request. However, keep in mind that complex variables in ColdFusion (with the exception of arrays) are passed reference.

What I actually do in my app is: Store some settings (for examle site
language) for the user in the session scope (with the SessionStorage-
Plugin). Then, in the RequestStart-Handler (or in an interceptor), I
copy those settings (actually it's a Struct; let's call it
"siteSettings") into the rc-Scope (<cfset rc.siteSettings =
instance.sessionStorage.getVar("siteSettings",StructNew()) />). And
then use that rc.siteSettings-Struct in other parts of the request
flow.

Yep, no problems there. Just remember that the struct is only stored once in session, and the rc simply has a reference to it. I say that to point out that if something changes either the reference in session or the reference in rc during the request, the change will be reflected in both places.

Actually, this does seem to work - probably, the
rc.siteSettings is overwritten with the session content like the
RandExample in the example before?.

Are you referring to this line of code:
<cfset rc.siteSettings = instance.sessionStorage.getVar("siteSettings",StructNew()) />
I don't know that you are "overwriting" anything since siteSettings doesn't exist in the rc sctruct prior to this line of code, but yes, that line of code would set a reference to the siteSettings struct in the request collection for that request.

BUT: If the session times out
(what I do to reproducte this ist just delete my cookies), the rc
content stays! (it shout be filled actually with an empty struct if
there's no sessioStorate.siteSettings)

Well, it's hard to say without knowing what's going on, but firstly, are you closing your browser? Some browsers keep cookies in memory even after they've been deleted which might mean that you're actually keeping your session. It's also worth noting that clearing your cookies, doesn't delete the actual session data. It just dis-associates your browser with it in memory. If you also have references to the sessionStruct in a persistent scope like "application", it might be coming from there. Secondly, is there a process setting the siteSettings struct back into the session storage if it doesn't exist? It might be that it's just getting re-created automatically.

Also, one more thing which it looks like Luis just mentioned. Make that EVERYTHING in your handlers is scoped. Any local variables in your handlers need to be varred or they will end up in the variables (private) scope of the persisted CFC and still be laying around on the next request or for concurrent requests.

For instance, the following line is ok:
<cfset var rc = event.getCollection()>

but this line would be VERY bad in your handler:
<cfset rc = event.getCollection()>

Thanks!

~Brad

Well, I've just tried the "session stuff" within a "cached"
environment. Actually, I was not able to modify a value of a session
variable - whether in my handler nor in a model (<cfset
instance.sessionstorage.setvar("testvariable",7) /> or <cfset
rc.testvariable = instance.testmodel.testmethod() />.

How do you know the value was not set in session? If you cfdump out the session scope after running <cfset instance.sessionstorage.setvar("testvariable",7) /> what do you see?

~Brad

I do a <cfdump var="#session#" /> within the view.
When I do a <cfset instance.sessionstorage.setvar("testvariable",7) />
in my handler, I get "7" if I reinit the App. But if I change it from
"7" to "8" and refresh the page (without reinit) I still have the "7".
Also tried using a model, calling the model method, which sets the
session variable to a different value - always get "7". What actually
does work, if I do a <cfset
instance.sessionstorage.setvar("testvariable",RandRange(1,10)) /> -
then I get another value for each page reload...

And - I really took care about the var scoping! Actually, for
reproducing purposes, I took the "very simple app template" from Luis
and just change the <cfset rc.welcomeMessage - Part...

I think your problem is still not understanding how cached cfcs work.

But if I change it from
"7" to "8" and refresh the page (without reinit) I still have the "7".

That is absolutely correct. Even though you have edited the contents of the .cfc file, the previous code with the "7" is still cached in the instance of the handler still in memory. When you create an instance of a cfc and place it in a persistent scope like application or session, changes to the original cfc file are NOT picked up until a NEW instance of the cfc is created. reinitting the framework forces a new instance of your handler to be created. Otherwise the handler in memory has whatever code was in place when it was first created.

Does that make sense now?

~Brad

WOW - probably got it! The same code runs fine with 3.0.0M6, but
DOESN'T with 3.0.0RC1 (Build-ID 201011081052). Could reproduce this
now several times (after restarting ColdFusion Server and renaming the
ColdBox-Directories to change between the releases)
=> Luis, probably your turn? Or has there changed something between M6
and RC1 concerning caching?
ColdFusion btw. is 9,0,1,274733.

... to reproduce it - just take the "SuperSimpleApp" and make sure
that "handlerCaching" and "eventCaching" are set to true. Then in
General.cfc, change the line <cfset rc.welcomeMessage = "Welcome to
ColdBox!"> to another message an reload. New Text appears immediately
in M6, but not in RC1 (until you do a fwreinit=true)

That may well be the case, but if it is, that was a bug in M6.

Just as Brad (and probably others) said, if you have handler caching turned on, it does not matter how many times you change a hard-coded value, it will always be the same unless and until you do a fwreinit.

Ok, probably got it - if handlerCaching is turned on, hardcoded values
won't be changed until reinit. Can anybody tell me, how/where I have
to set and get session values? That my code will get changed values
(and store it in the rc scope)? As I wrote, I want to store user-/
session based information in the session scope (using SessionStorage
Plugin). I've tried to do this in the model layer, but also there -
values won't change if caching is turned on. All this was working in
Pre-RC1. Was this really a bug in all versions before?

Can anybody tell me, how/where I have
to set and get session values?

What you were doing with the sessionStorage plugin looked fine.

"values won't change if caching is turned on."

What do you mean by this? The value doesn't change across multiple page request for a single user or the value doesn't differ between multiple users' sessions?
If you mean the former, that would be correct since a given users' session would persist the same values unless you were changing them. If you mean the latter, then I would have to ask where your session values are coming from and how you know they are different to begin with?

~Brad

Brad,

I mean the former. Each user should have it's own session scope with
his "private data".
Let's say, there's a single page where the user can choose his desired
language for the site - for example "german" and "french". If the user
clicks on a language => a session variable has to be set to the chosen
language (for example 'de' for german). And I must have access to that
value within the whole framework in all subsequent requests

A skeleton could look like this:

In my handler, when a language has been choosen:
<cfset
instance.sessionstorage.setVar("userLanguage",rc.userLanguage) />
<!--- store chosen language in session storage --->

In OnRequestStart Handler:
<cfset rc.siteLanguage =
instance.sessionstorage.getVar("userLanguage","") /> <!--- get
language from session storage; set to "" if not set --->