RE: [coldbox:22362] [coldbox-3.6.0] Flash plugin adding prc data to rc upon reinflation

You are doing it the hard way :slight_smile: check out the “persist” parameter in setnextwvent which does all that for you.

Thanks for the reply. Here’s some more info. I have to apologize - I gave a much simplified example in the original post, but our actual code is quite a bit more complex and involves using runEvent. One reason we wanted to use the flash object is that we’ll frequently have a setup like the following and we’d like the persistence to be encapsulated in the ‘run’ event:

`

<cfset runEvent(“commonCheck”) />

<cfset setNextEvent(“alpha”) />

`

We want to avoid having the concerns of an event called via runEvent be duplicated everywhere we call setNextEvent and outside the encapsulation of the run event. I’ve greatly simplified here, but we’ll frequently have code in a single handler (like ‘a’ above) that may contain multiple setNextEvent calls, each to a different location and within different conditional logic. If there were only 2 events that had runEvent(‘commonCheck’) and each had a single setNextEvent call we may be able to get away with using persist in the setNextEvent calls, but we have several cases where a private event is run by quite a few public events, some of which will conditionally redirect to one of several different events via setNextEvent (see event ‘c’ above).

In addition, the docs here http://wiki.coldbox.org/wiki/FlashRAM.cfm#Flash_Scope_Object say that using the flash scope object is a best practice and more performant. But I think my main concern is where it appears that using ‘inflateToPRC=true’ with the flash object ends up inflating the data to the rc and clobbering anything being persisted by persistRC that happened to have the same key. We will sometimes have code that will default to what’s in the prc if there’s not data in the rc by that key, and we use the same key since it’s the same thing (for example, person_id). It would be nice to be able to persist both the rc and prc in their entirety between setNextEvent redirection, since it’s all a single HTTP request from the client (even if it’s something like a cflocation under the hood). It would be nice to have something like a flash.persistCollections that internally does something like:

<cfset flash.persistRC() /> <cfset flash.persistPRC() /> <!--- so that this inflates things from the current prc only to the prc on the other side --->

anywho… :slight_smile:

thanks again
Jon

Just remember that setNextEvent() is a completely new event, as if a user add typed that into the url, where as runEvent() doesn’t have the overheads of all the other preProcess() etc running around the event call.

Right. We use runEvent for code that needs to be run in more than one handler (for example, runEvent(“checkShoppingCartExists”) at the top of all our registration/checkout events), and setNextEvent for things like redirecting to a completely different event (for example, if a shopping cart for some reason is empty when we go to pay for it, we will setNextEvent(“beginRegistration”) that will get them back on track). We use setNextEvent when we definitely want to do a full redirect.

Mostly I’m looking for how to get flash.put(… inflateToPRC …) to not also inflate the data into the rc.

thanks again

I am confused, why are you using a runEvent() for code that needs to be run in more than one event. runEvent() is for running another eventhandler, what you’re doing is best suited to event patterns on your handler via AOP or even an around handler or interceptor maybe.

Hell even an inject MODEL would be better than what your’re doing.

But to go back to your issue, as Brad has stated your doing it the hard way. For example this

Would be better as

This will send the user to the next event, with the defined variables as persisting to the that event. Hence no need for your flash.put as this is all done for you.

runEvent, lets talk about that for a minute.

When there is a need to call more than one handler, we generally use the runEvent() so as to build up all that is needed for the request and private request, as well as maybe for viewletts so we can encapsulate them into more managable widgets so to speak.

So if we have a handler like this

public function myHandler(event, rc, prc) {
rc.test = “123”;

}

We can call it like this

setNextEvent(), which when run will redirect the browser to that event or we can use runEvent() to run some hidden events to the user, before going to the final destination that the user will see. Good for multiple steps or handlers that you don’t want the end user to see.

In your case, if your only doing that to pull up the flash scope, then like Brad stated, you’re going about it the long way.

There are some cases in our code where the code we’re calling via runEvent is the first thing in the event and always called that could stand to be moved to a pre-handler AOP point. However, much of the time this ‘common code’ is called part-way through an event’s code, or is only conditionally called, where the conditions are an integral part of the individual handler and aren’t something that would be appropriate or feasable to pull out into a pre-handler. (The logic in our handlers deals with event/rc/prc and is application flow control rather than domain/business logic.)

In the ‘commonCheck’ example function I posted earlier, there is indeed more than just the flash.put call - the <!— some processing, and then —> comment is a placeholder for the logic of the function and the flash.put is just storing the results. That logic will be things like calling services and inspecting the results to know whether to do things like throw exceptions, setNextEvent, or continue and put results in prc for later use - basically whatever application flow logic is in the purview of the ‘commonCheck’ function.

The reason we don’t inject a model here to run the ‘commonCheck’ code is that it will contain really only controller logic that’s needed in more than one ‘top level’ event (events hit by the user via URL). We have avoided passing the event/rc/prc objects down into the model for manipulation. And much of the ‘commonCheck’ code will, in addition to calling service models, do things like inspect values in rc/prc or call setNextEvent or event.renderData (for our AJAX calls) - maybe even other runEvent calls, although we haven’t gotten that hairy yet.

I was intrigued by the <cfset setNextEvent(route = “myNextEvent”, persist=“rc,prc”) /> idea to see if that would indeed persist the whole rc and prc and reinflate them correctly to their respective structs in the next event. I tested code like this:

<cfset setNextEvent(event = “b”, persist=“rc,prc”) />

with b.cfm coded like

but foo and baz were missing from the rc and prc in the ‘b’ view’s dump.

We could explicitly list out each key in the rc or prc we wanted to persist in the persist argument to setNextEvent, but since a function like commonCheck may be called from 10 different events, each of which may want to setNextEvent to different destinations depending on their expected behavior, we’d then have to maintain that list on every one of the 10 setNextEvent calls which would be non-DRY and a pain to maintain. We had hoped to use flash.put within the commonCheck function itself to encapsulate the persistence behavior there for things it was putting in the prc, and let the 10 calling events do likewise with anything they may have put in prc that was needed in the next event.

We also have the need to keep separate data from the rc and prc so that we can tell what was, for example, a user_id from the form (rc.user_id) and what was a user_id we set in the prc. In the event we redirect to we’ll want to do things like event.getValue(“user_id”, prc.user_id). I also see a note in the docs that say that the persist argument refers to items already in the request collection. When I swap out persist=“rc,prc” in the above sample for something like persist=“foo,baz” I see that foo is correctly persisted in ‘b’ in the rc, but baz is not persisted in prc, so it looks like persist is only for rc. We definitely need to persist data from both rc and prc.

Sorry - I know this is a lot, and I’m half shooting in the dark with my questions and exploration. Thanks to both of you for the replies as I continue up the learning curve (which is a sight better than the learning curve was for model glue!)

The persist argument takes a list of names of variables in the rc scope so you can’t pass in “rc” or “prc” unless you actually have variables defined called rc.rc or rc.prc.

Now, there is a persistStruct argument that allows you to pass in an actual struct of values to persist. So you could potentially do persistStruct=rc though the last time I did that, I think I ran into issues with an endless loop where the rc.eventname or something was getting carried over.

The persist functionality only applies to rc though, not prc. Perhaps you could put in a ticket to support prc too.

Thanks!

~Brad

ColdBox Platform Evangelist
Ortus Solutions, Corp

E-mail: brad@coldbox.org
ColdBox Platform: http://www.coldbox.org
Blog: http://www.codersrevolution.com

Sorry, but that is not how I have seen how runEvent is used. You are free to do that, but you have to remember that runEvent() is used to run another handler without going through the normal redirection that a handler would do if going through NextEvent(), as I explained earlier. What you are doing, sounds like it belongs to either a Service or a model.

I mulled it over some more and discussed the whole deal with our system architect and we ended up deciding to write our code so that anything we call via setNextEvent will only expect data in the rc. If anything from a previous event’s prc will be needed, we’ll pass it via the persistStruct argument and the event we redirect to will simply expect it in rc. This works well and feels a lot less like “fighting the framework”.

Our underlying problem, I think, is that we’re coming from a model-glue mindset and code base. We had initially thought to try to maintain equivalent behavior, but the two frameworks are different (thankfully! model-glue is a bear) and we need to not try to impose MG methodologies on our Coldbox code as we convert it.

Thanks again both Andy and Brad for you help - it is much appreciated.

You’re welcome.

I know how frustrating it can be to have a mind set with one way, going to something different and re-learning that application flow. I have spent the last 3 days trying to find a simple intermittent bug in a Unity Game I have been playing around with, when the penny drops and I have to switch my thinking at times with Unity.