HI All The other day I was glancing at my feed reader and this post from Sean caught my eye - http://corfield.org/blog/index.cfm/do/blog.entry/entry/Leave_that_code_alone. I scanned the first couple of sentences and thought "hmm wise advice indeed. I've been burnt by doing that in the past, but I'll never fall into that trap again..."
Well a day later my DefaultXmlBeanFactory.cfc has a new method called
removeFromSingletonCache()!
Ah the irony....
I'll take a couple of steps back and explain.
We're working on a large Mach-II, ColdSpring and Reactor based
project. We have recently hit the 1000 cfc mark. Granted, lots of
these are reactor generated XYZGateway.cfc, XYZGatewaymysql4.cfc,
XYZrecord.cfc and so on, but there is still a *lot* of code in the
app.
We run everything in production mode and have put together a mechanism
that lets us pass a parameter through a URL which reloads all the
components. The trouble with this is that it's taking about 3 minutes
to run... This is an extremely annoying, frustrating, inefficient
gumption trap. Change one things in a component, reload, wait 3
minutes, get error, change again, reload, wait 3 minutes..
There has to be a better way.
So yesterday I came up with an idea - dig around in
application.serviceFactory and see if there is some way to selectively
refresh specific objects in ColdSpring. My idea was to list out
everything in application.serviceFactory.getBeanDefinitionList() and
output it with links next to it saying "reconstruct". Clicking this
link on an object then removes it from the singletonCache, runs
createBeanDefinition using the existing properties and then triggers
configure() on the ColdSpringPlugin.
I ran into 101 issues with doing this but was eventually able to
wrangle it (the entire file is attached) - it works and only takes
about 7 seconds to run a reconstruction.
I did however get completely stuck on clearing the object from the
singletonCache - I can't see anyway to do this in the framework code
as it stands. To work around this I wrote the following method and
added it to the DefaultXmlBeanFactory.cfc:
<cffunction name="removeFromSingletonCache" access="public"
output="false" returntype="void">
<cfargument name="beanName" type="string" required="true" />
<cfset var error = false />
<cflock name="bf_#variables.beanFactoryId#.SingletonCache"
type="exclusive" timeout="5">
<cfif StructKeyExists(variables.singletonCache,
beanName)>
<cfset
structDelete(variables.singletonCache,beanName)>
<cfelse>
<cfset error = true />
</cfif>
</cflock>
<cfif error>
<cfthrow message="Cant find #arguments.beanName# in singleton
cache.">
</cfif>
</cffunction>
Now I realise I have sinned, but I only need this in the dev
environment, not production and I'm confessing here in public, so
maybe I'll be forgiven.
What I want to know is:
- Is there a better way to achieve this result? I thought of writing
my own BeanFactory that extends DefaultXmlBeanFactory, but this would
also mean writing my own ColdSpringPlugin (Mach-ii plugin) as
DefaultXmlBeanFactory is hardcoded in there.
- Could this method make it into future versions of ColdSpring?
Feedback welcome.
Mark
--
Mark Stanton
Gruden Pty Ltd
http://www.gruden.com
object-constructor.cfm
Description: application/cfm
