As the list may be aware, I've been struggling for some time to push code repeatedly with zero interruptions to users while under heavy load as we inch closer to the holy grrrrrrrrrrail of continuous deployment. To recap, my objectives are:
* To be able to refresh the beanfactory/model (application.cs, a model-glue parent bean factory) independent of model-glue
* To be able to refresh model-glue (including sub apps) independently of the beanfactory
I saw something in some code from Doug Hughes which led me to experiment today and I believe I've discovered something important and would like to get some confirmation/feedback on the approach.
First, this is the code I saw (from
https://github.com/dhughes/ColdBooks/blob/master/Application.cfc):
<cfif structKeyExists( application, this.realName ) AND structKeyExists( application[this.realName], "framework" ) >
<cfset application[this.realName].framework.getBeanFactory().setParent( application.cs ) />
</cfif>
Woah! Swapping out the parent beanfactory without deleting and recreating Model-Glue?? Now THAT is interesting. I've always wanted to be able to reinit my bean factory but ModelGlue always just plods along, blissfully ignorant of my shiny new model. This code snippet got me suspicious it might be possible. That code is pretty old (and undocumented) MG syntax but this works in MG 3.1.299:
<cfset application[this.realName].getInternalBeanFactory().setParent(application.cs) />
I can do the reverse and getParent() and (by adding in a unique value to my application.cs) I have confirmed that it is indeed getting updated. But here's the rub, my controllers don't pick up any of the changes because they are autowired by Coldspring at init time so they are holding on to references to the old model. SO, I tried three different approaches to accessing my service layer from inside my controllers:
1. autowire (set{beanname})
2. beans scope (defined in the modelglue.xml)
3. getModelGlue().getBean("beanname") in the controler
And after refreshing application.cs and running the setParent(), guess what? #3 returns the updated model bean!! Unless I'm missing something, I believe by changing all service layer references in my controllers to use syntax #3, I can seamlessly recreate coldspring and replace it in Model-Glue without anyone being the wiser! This almost seems too good to be true which is why I'm writing you here:
Question: getModelGlue().getBean() appears to be deprecated in favor of the beans scope but is it just because it's shorter to write? Technically it's one less method call because they are cached in the beans scope but are there any other downsides to using getModelGlue().getBean()?
In small apps, I recognize that you can just delete the application key for the MG app and let it re-init which would accomplish a similar thing. However, I have a pretty massive app. Hundreds of beans in ColdSpring and three MG apps with dozens of controllers and hundreds of methods. Combined with Transfer, which absolutely hates restarting under any kind of load, I'm trying to tease apart and reduce the requirement to refresh everything all at once. Even on beefy production hardware, my app takes 60s to reinit from coldspring to model-glue, thus, my desire to march closer to continuous deployment where nobody is the wiser that I'm upgrading code in real-time.
Hope this all makes sense - I'm excited in a very nerdy way tonight so I appreciate your feedback.
Brian