fully reload fw/1 (including new application scope)

669 views
Skip to first unread message

Brian FitzGerald

unread,
May 6, 2014, 10:39:31 AM5/6/14
to framew...@googlegroups.com
Hey guys,

I have a super simple demo app here and came across something that is confusing to me. I have set up DI/1 in setupApplication like so:

<cffunction name="setupApplication">

<cfset factory = new framework.ioc("/model")>
<cfset setBeanFactory(factory)>

</cffunction>


Works great! However, when I comment out the DI/1 setup, and make a request with reload=true in the url, I expected the application to reinitialize itself without DI/1 and the code which relies on dependency injection to break. It didn't.

<cffunction name="setupApplication">

<!--- <cfset factory = new framework.ioc("/model")>
<cfset setBeanFactory(factory)> --->

</cffunction>


The beanfactory is still in play. It seems that even though I reloaded the application, the application scope was not reset, so I tried doing something like this to try and force the application scope to reload (so the beanfactory would no longer be available).

<cffunction name="setupRequest">

<cfif structKeyExists(url, "reload") and url.reload>
<cflock scope="application" timeout="30" type="exclusive">
<cfset structClear(application)>
</cflock>

<cfset onApplicationStart()>
</cfif>

</cffunction>


This breaks the application however, throwing:

Element org.corfield.framework is undefined in a Java object of type class coldfusion.runtime.ApplicationScope


So the application scope is cleared, but FW/1 is getting hung up on the application reload(?). I was able to "reset" the application scope in another way by setting running:

<cfset this.applicationTimeout = createTimeSpan(0,0,0,0)>


And this successfully reinitializes the framework without DI/1 - but I'm confused as to why I can't reload the application with a fresh application scope by using structClear(application) and then calling onApplicationStart(). Can anyone shed some light on what's going on here? I seem to have a lack of understanding here either related to how the application scope works or how FW/1 initializes itself (probably both).

Thanks for any insight you can share!
Brian

Cameron Childress

unread,
May 6, 2014, 10:59:45 AM5/6/14
to framew...@googlegroups.com
setupApplication() is a FW/1 specific method and by the time it's called, CF's own onApplicaitonStart() has executed. FW/1 uses onApplicationStart() to initialize itself so that's why you can't clear the application scope in setupApplication(), FW/1 has already set a bunch of stuff into the app scope by then.

I am not sure what side effects this could have, but you can clear the default BeanFactory like this in setupApplication():

structDelete(application[ variables.framework.applicationKey ], 'factory');

I didn't look at the FW/1 code to determine if this also would execute some bad thing out of order, and you really shouldn't be tinkering with the FW/1 guts like this... But that's where the bean factory is stored under the covers and that should clear it.

-Cameron


--
--
FW/1 on RIAForge: http://fw1.riaforge.org/
 
FW/1 on github: http://github.com/framework-one/fw1
 
FW/1 on Google Groups: http://groups.google.com/group/framework-one
---
You received this message because you are subscribed to the Google Groups "framework-one" group.
To unsubscribe from this group and stop receiving emails from it, send an email to framework-on...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Cameron Childress
--
p:   678.637.5072
im: cameroncf

Nando Breiter

unread,
May 6, 2014, 11:04:58 AM5/6/14
to framew...@googlegroups.com
Brian,

What I know is that the FW/1 calls setupApplication() on reload, and DI/1 will be reloaded, overwritten, like you have it in your code if you remove it from the comment. If that's what you need to know, then just proceed with development on that basis. I don't understand the practical basis of attempting to clear DI/1 completely. If you really need to figure out how to do that, then it might help to explain your use case.

setupRequest() is called after setupApplication(), so if you clear the application scope in setupRequest() you nuke the framework and it can't continue to run. 





Aria Media Sagl
Via Rompada 40
6987 Caslano
Switzerland

+41 (0)91 600 9601
+41 (0)76 303 4477 cell
skype: ariamedia


--

Chris Blackwell

unread,
May 6, 2014, 11:12:41 AM5/6/14
to framew...@googlegroups.com

On 6 May 2014 15:39, Brian FitzGerald <bmfitz...@gmail.com> wrote:
<cffunction name="setupApplication">

<!--- <cfset factory = new framework.ioc("/model")>
<cfset setBeanFactory(factory)> --->

</cffunction>


if that code doesn't error on setBeanFactory() then it means CF is finding a variable called 'factory' in a scope somewhere. for example, application.factory ?  try dumping the app scope

to be sure that you are using the factory you think you are, try explicitly scoping the variables

<cffunction name="setupApplication">
  <cfset var factory = new framework.ioc("/model")>
  <cfset setBeanFactory(local.factory) />
</cffunction>

Nando Breiter

unread,
May 6, 2014, 11:17:01 AM5/6/14
to framew...@googlegroups.com
Chris, 

I think you misread the code. setBeanFactory() is also commented out.



Aria Media Sagl
Via Rompada 40
6987 Caslano
Switzerland

+41 (0)91 600 9601
+41 (0)76 303 4477 cell
skype: ariamedia


Chris Blackwell

unread,
May 6, 2014, 11:20:53 AM5/6/14
to framew...@googlegroups.com
indeed.  sorry about that.

Chris Blackwell

unread,
May 6, 2014, 11:44:48 AM5/6/14
to framew...@googlegroups.com
apologies for the brain fart earlier.

it looks like setBeanFactory() persists the the factory in the application scope.

So if you want to loose the reference to it you'll have to set it to null

setBeanFactory( javacast('null', 0) );

hope that helps
Chris







Brian FitzGerald

unread,
May 6, 2014, 11:53:43 AM5/6/14
to framew...@googlegroups.com
Thanks a lot for the responses Nando, Cameron, and Chris.

setupRequest() is called after setupApplication(), so if you clear the application scope in setupRequest() you nuke the framework and it can't continue to run. - Nando

After clearing the application scope though, I immediately call onApplicationStart() again, should that not cause CF to completely reinitialize the application scope and FW/1 to reinitialize itself as if it were the very first request to the application?

FW/1 uses onApplicationStart() to initialize itself so that's why you can't clear the application scope in setupApplication() - Cameron

Considering this, if you did indeed want to clear the application scope as a part of your app "reload" process (for whatever reason), what would be the best way to accomplish that?

This is not a practical use case. I'm exploring this because I'm going to be doing a simple demo and I simply wanted to illustrate that if you "take out" the bean factory (and reload the application), the dependency injection will no longer work. When I didn't see the results I expected, I figured this would be an important point to make sure I had straight in my head - to have a better understanding of the framework.

Thanks again,
Brian

Cameron Childress

unread,
May 6, 2014, 12:09:03 PM5/6/14
to framew...@googlegroups.com
On Tue, May 6, 2014 at 11:53 AM, Brian FitzGerald <bmfitz...@gmail.com> wrote:
After clearing the application scope though, I immediately call onApplicationStart() again, should that not cause CF to completely reinitialize the application scope and FW/1 to reinitialize itself as if it were the very first request to the application?

Since I think that FW/1's onApplicationStart() probably calls setupApplication() I think there is probably some sort of loop and maybe some code in there to stop you from doing this. I consider calling onApplicationStart() to be "off limits" in a FW/1 app.

Considering this, if you did indeed want to clear the application scope as a part of your app "reload" process (for whatever reason), what would be the best way to accomplish that?

Doing a structDelete() on the application scope is a blunt tool. I stopped doing this some time ago and started using a Singleton Factory to keep any application scope "stuff". Then I usually had a singletonFactory.reset() method that knows to nuke only the items it's managing. I don't access the application scope outside of this factory so it can be safe and smart.

If you are curious, this is what my standard Singleton Factory looks like:

Having said that, I don't even use my own home grown Singleton Factory anymore. I put everything in DI/1 and it's my Singleton Factory. It has been years since I have written any code that put any variables into the application scope directly outside of whatever Singleton Factory type of thing I am using.

I can't think of a situation where I would need to clear the entire application scope indiscriminately, especially considering how much FW/1 depends on it under the covers.

-Cameron

Sean Corfield

unread,
May 6, 2014, 3:05:23 PM5/6/14
to framew...@googlegroups.com
On May 6, 2014, at 9:09 AM, Cameron Childress <came...@gmail.com> wrote:
> I can't think of a situation where I would need to clear the entire application scope indiscriminately, especially considering how much FW/1 depends on it under the covers.

Yes, just stop fighting the framework and do things "the right way" instead.

Sean Corfield -- (904) 302-SEAN
An Architect's View -- http://corfield.org/

"Perfection is the enemy of the good."
-- Gustave Flaubert, French realist novelist (1821-1880)



signature.asc

Sean Corfield

unread,
May 7, 2014, 1:08:36 AM5/7/14
to framew...@googlegroups.com
This wasn't intended to shut down the conversation, BTW. I do wonder
what you're actually trying to achieve Brian, that you need to do this
- can you elaborate?

You _shouldn't_ need to mess with application scope: reloading the
FW/1 app should be enough. Removing the bean factory seems a weird
edge case.

Your code does not declare factory with var so it'll be in variables
scope instead - and that means in application scope since it happens
in the first request for an application (Application.cfc instantiated
for onApplicationStart() essentially as an application variable, even
tho' subsequent requests have it instantiated as a request scope
variable).

Sean
--
Sean A Corfield -- (904) 302-SEAN
An Architect's View -- http://corfield.org/
World Singles, LLC. -- http://worldsingles.com/

Brian FitzGerald

unread,
May 7, 2014, 1:59:27 AM5/7/14
to framew...@googlegroups.com
Thanks a lot for sharing your Singleton Factory Cameron, it was cool to check that out. I agree that tampering with the application scope in a real world app certainly seems like a bad approach.

I appreciate your follow up too Sean; really my goal was just to turn on and off the beanFactory as I reload the app (with the reload=true) url param for demo purposes (i.e. just to demonstrate on the fly just how cool DI/1 really is, and what would happen if you were to "turn it off").

Not really a big deal, but (and perhaps it was really more of a general cf question than a FW/1 question), but I was always under the impression that clearing the application scope and calling onApplicationStart manually would, in effect, completely "refresh" an application, thus, in the case that we're using FW/1, cause FW/1 to load from scratch, thereby calling setupApplication again and loading with or without the beanFactory (based on whether or not the beanFactory setup code was commented out).

I think I need to setup a dead simple Application.cfc without FW/1 at all and see what happens when I try some of this stuff... again, not because I'm trying to solve anything specific with it, but just because it would be nice to know exactly what's going on in terms of when different scopes are created and what happens when you forcefully clear them and/or call the built in Application.cfc methods directly.

Ok, just rambling now. Thanks again for the insight!

Cameron Childress

unread,
May 7, 2014, 9:26:20 AM5/7/14
to framew...@googlegroups.com
On Wed, May 7, 2014 at 1:59 AM, Brian FitzGerald wrote:
I was always under the impression that clearing the application scope and calling onApplicationStart manually would, in effect, completely "refresh" an application

This is still true. You just have to remember that FW/1 is "the application" here and it already owns onApplicationStart(). So, FW/1 may be allowed to clear the app scope using this method, but since FW/1 "gets there first", you should not.

FW/1 is so thin it's easy to forget that it is really "the application". You are more or less building your app inside it. Since FW/1 "takes over" your Application.cfc, it gets dibs on many of the methods you would otherwise be allowed to use.

You still should be able to do virtually anything, you just have to use the interface FW/1 provides instead and put some of the default Application.cfc methods out of your mind. They are no longer available to you.

-Cameron 

Sean Corfield

unread,
May 7, 2014, 5:03:05 PM5/7/14
to framew...@googlegroups.com
On May 6, 2014, at 10:59 PM, Brian FitzGerald <bmfitz...@gmail.com> wrote:
> I appreciate your follow up too Sean; really my goal was just to turn on and off the beanFactory as I reload the app (with the reload=true) url param for demo purposes (i.e. just to demonstrate on the fly just how cool DI/1 really is, and what would happen if you were to "turn it off").

Well, if the app is relying on the bean factory to autowire things, the answer will be "The app breaks if you turn the bean factory off" so I'm not quite sure what you're trying to demonstrate here?

Looking at setupApplicationWrapper(), I see it does not attempt to remove any existing factories when you reload. That's probably a bug (but a real edge case one), and this may just be one of those "don't do that" situations.

FWIW, here's what I believe the fix would be - you can try this with your local copy Brian and see if it does what you expect:

Inside setupApplicationWrapper(), after this line (in the lock / if block):

application[variables.framework.applicationKey].subsystems = { };

Add these two lines (just before the } else { line):

application[variables.framework.applicationKey].subsystemFactoriess = { };
structDelete( application[variables.framework.applicationKey], "factory" );

I believe this will force bean factories to go away on a reload.

The reason this might be one of those "don't do that" situations is because removing a bean factory is nearly always going to break your app, and if you do have a bean factory, it will be reloaded / rebuilt every time you reload the app anyway (which is the normal use case) when setupApplication() runs (or setupSubsystem() depending on your code).

Make sense?
signature.asc

Nando Breiter

unread,
May 8, 2014, 4:58:04 AM5/8/14
to framew...@googlegroups.com
Something caught my eye:

                                application[variables.framework.applicationKey].subsystemFactoriess = { };
                                structDelete( application[variables.framework.applicationKey], "factory" );

Is there a typo in subsystemFactoriess ?

That said, unless someone comes up with a plausible use case, I don't think this needs to be "fixed". It seems like over-engineering to me.



Aria Media Sagl
Via Rompada 40
6987 Caslano
Switzerland

+41 (0)91 600 9601
+41 (0)76 303 4477 cell
skype: ariamedia


Sean Corfield

unread,
May 8, 2014, 1:28:50 PM5/8/14
to framew...@googlegroups.com
On May 8, 2014, at 1:58 AM, Nando Breiter <na...@aria-media.com> wrote:
Something caught my eye:

                                application[variables.framework.applicationKey].subsystemFactoriess = { };
                                structDelete( application[variables.framework.applicationKey], "factory" );

Is there a typo in subsystemFactoriess ?

Yup. That should only have four 's's in it, not five. Good catch.

That said, unless someone comes up with a plausible use case, I don't think this needs to be "fixed". It seems like over-engineering to me.

That's my sense too but if anyone can convince me that there's a real world need for this fix, please create an issue on Github! :)
signature.asc

Brian FitzGerald

unread,
May 8, 2014, 2:41:52 PM5/8/14
to framew...@googlegroups.com
Well, if the app is relying on the bean factory to autowire things, the answer will be "The app breaks if you turn the bean factory off" so I'm not quite sure what you're trying to demonstrate here?

I guess that's the point though, if I "turn the bean factory off" by commenting out the code which sets up the bean factory and reload the app, I would expect the app to break. But it didn't break since the beanfactory is not cleared out of the application scope on reload=true.

I think the use case is simply that if I'm writing an app, and I'm playing with the bean factory... and I decide, "nah, I'm not going to use the bean factory after all." And then remove the bean factory setup code from setupApplication() ... and reload my app. My app could continue working just fine even if I had accidentally left some references to autowired services in a couple places.

Only later, when I restart my server and the application scope is truly cleared will the bug in my application reveal itself since at that point the bean factory will really be gone. This could make the issue harder to track down since I may have moved on and complete forgotten that I had taken out the bean factory. Or it could be someone else seeing the issue after the server restart who wasn't originally involved in taking out the bean factory.

I'm not necessarily trying to sway either way here, my point is just that, personally, if I removed the bean factory setup code from my app and reloaded the application, I would then expect all code relying on the bean factory to break - which currently does not happen.

FWIW, here's what I believe the fix would be - you can try this with your local copy Brian and see if it does what you expect:

Hey Sean, I tried the code modification you suggested and it did behave as I expected. When I removed the bean factory code and reloaded the app, the bean factory was no longer available within the application.

Certainly not trying to make a mountain out of a molehill here; thanks for hearing me out!

Sean Corfield

unread,
May 8, 2014, 3:01:04 PM5/8/14
to framew...@googlegroups.com
On May 8, 2014, at 11:41 AM, Brian FitzGerald <bmfitz...@gmail.com> wrote:
> I think the use case is simply that if I'm writing an app, and I'm playing with the bean factory... and I decide, "nah, I'm not going to use the bean factory after all."

I'll leave it to others here to decide whether that's a realistic use case in the real world :)

> Hey Sean, I tried the code modification you suggested and it did behave as I expected. When I removed the bean factory code and reloaded the app, the bean factory was no longer available within the application.

Excellent!
signature.asc

Brian FitzGerald

unread,
May 8, 2014, 3:43:20 PM5/8/14
to framew...@googlegroups.com
Thanks Sean! I submitted a pull request with your mod. Feel free to ignore (or not) as you see fit.

Nando Breiter

unread,
May 8, 2014, 4:28:46 PM5/8/14
to framew...@googlegroups.com

> On May 8, 2014, at 21:01, Sean Corfield <se...@corfield.org> wrote:
>
>> On May 8, 2014, at 11:41 AM, Brian FitzGerald <bmfitz...@gmail.com> wrote:
>> I think the use case is simply that if I'm writing an app, and I'm playing with the bean factory... and I decide, "nah, I'm not going to use the bean factory after all."
>
> I'll leave it to others here to decide whether that's a realistic use case in the real world :)

It's a disuse case ;-)

Sean Corfield

unread,
May 8, 2014, 5:25:13 PM5/8/14
to framew...@googlegroups.com
On May 8, 2014, at 12:43 PM, Brian FitzGerald <bmfitz...@gmail.com> wrote:
> Thanks Sean! I submitted a pull request with your mod. Feel free to ignore (or not) as you see fit.

You'll see I closed it with a request that you submit against develop, not master.

The master branch is the current stable release and only critical / blocking issues generally get fixed on master. Everything else flows through the develop branch first.
signature.asc

Brian FitzGerald

unread,
May 8, 2014, 5:33:46 PM5/8/14
to framew...@googlegroups.com
Understood. My mistake Sean, I've just resubmitted the pull request on the "develop" branch. Thanks for the clarification!

Jeremey Hustman

unread,
May 8, 2014, 5:42:58 PM5/8/14
to framew...@googlegroups.com
I also like to sometimes start with a clean slate during development.  I probably restart my ColdFusion service 3 or 4 times a day just to make sure everything is cleaned out.  Sometimes, when I believe it's ready to go up for testing, I'll upload my application, only to find errors because of the fact that the beanFactory "sticks around".  I can't just restart the production server, but to run a full "Application Reload" would be most helpful.

Just for fun, here is what I have in my setupApplication() for this reason.  So my vote is +1 this has real world use.

    public void function setupApplication() {
        // Create bean factory with DI/1
        var bf = new framework.ioc(
            folders = '/proj195/model'
        );
        setBeanFactory(bf);

        if (structKeyExists(url, "stopApp")) {
            writeOutput('in stopApp');
            writeDump(application);
            writeDump(session);
            writeOutput('dumping session...');
            controller('security.removeSession');
            writeOutput('stopping application...');
            applicationStop();
            writeOutput('check empty below?');
            writeDump(application);
            writeDump(session);
            abort;
        }

    


Cameron Childress

unread,
May 8, 2014, 6:08:19 PM5/8/14
to framew...@googlegroups.com
On Wed, May 7, 2014 at 5:03 PM, Sean Corfield <se...@corfield.org> wrote:
FWIW, here's what I believe the fix would be - you can try this with your local copy Brian and see if it does what you expect:

Another approach to this would be to add this structDelete stuff in a new publicly exposed function called something along the lines of clearBeanFactory().

This would allow the developer to programmatically choose wether or not this was needed per request. A bit more granular control for what may be an edge case.

-Cameron

Sean Corfield

unread,
May 8, 2014, 7:42:32 PM5/8/14
to framew...@googlegroups.com
Merged! Thank you!
signature.asc
Reply all
Reply to author
Forward
0 new messages