While I've used Model-Glue for many years now, I've only recently begun to seriously drink the ColdSpring kool-aid. The more I use ColdSpring, the more I appreciate how well it works with Model-Glue. I'm writing up some recommendations for Model-Glue application design, and one of the things that occurred to me is that while I typically recommend breaking up the ModelGlue.xml file into multiple files, it might also make sense to break up the ColdSpring.xml file. Right now this file contains the settings for your Model-Glue application (reload, debug, etc) and any custom beans you want defined.
So I spoke with Scott Stroz about this and he clued me in to the fact that this is actually already possible! So big thanks to him for teaching me this tip, and hopefully it will help others as well.
To begin, create your custom beans.xml file. I'd keep it in config with the rest of the config files. Remember, this is the file that will store all the beans for your application. Your ColdSpring.xml file will only be used to configure the Model-Glue settings for the application.
Next, you create a new instance of ColdSpring and store it within the Application scope. I modified the Model-Glue default Application.cfc like so:
<cffunction name="onApplicationStart" output="false">
<cfset application.cs = createObject("component", "coldspring.beans.DefaultXmlBeanFactory").init()>
<cfset application.cs.loadBeansFromXmlFile("/mgtest/config/beans.xml", true)>
</cffunction>
Ok, one last step. When it comes to working with ColdSpring, there is a setting you can override in the main index.cfm file:
<!---
**HIERARCHIAL BEAN FACTORY SUPPORT**
If you'd like to designate a parent bean factory for the one that powers Model-Glue,
simply do whatever you need to do to set the following value to the parent bean factory
instance:
<cfset ModelGlue_PARENT_BEAN_FACTORY = ??? />
--->
I never really paid attention to this before, but this is what we need to change. Simply add:
<cfset ModelGlue_PARENT_BEAN_FACTORY = application.cs />
And bam - you're done. My biggest concern was that this wouldn't be as "tied" as when you just use ColdSpring.xml. However, that proved to be completely incorrect. I was able to define beans within my controller just fine:
<cfcomponent output="false" hint="I am a Model-Glue controller." extends="ModelGlue.gesture.controller.Controller" beans="userService">
And then use it within a controller mehtod:
<cfset event.setValue("message", beans.userService.helloWorld())>
Woot. Thanks Scott, thanks Model-Glue, and thanks ColdSpring.
Archived Comments
Ray,
This is great, but why not just break them up this way right inside your coldspring.xml file?
<!-- IMPORT COMMON BEANS -->
<import resource="/SymphonyCore/config/beans/ReactorFactory.xml" />
<import resource="/SymphonyCore/config/beans/CommonBeans.xml" />
I have done this for a long time and it is a lot easier than the method you mentioned.
Am I wrong?
Josh
2 things.
a) This isn't mentioned in the reference guide at all. :( I need to bug Chris Scott on it.
b) I'd still probably prefer a separate set of files for this. So while I can see using the IMPORT directive, I'd do it from my custom beans.xml file, just to keep things segregated between my services and my MG settings. But that's just my opinion.
I see your first point. As to your second point, that is exactly how I use the import directive I keep my mg stuff separate. In either case, I am glad to know of another way to do it.
Thanks for all of your helpful blog posts.
Josh
Ray, in your setup, my hunch would be that a reload of the ModelGlue framework would not reload the factory in application.cs, but instead just create a new ColdSpring instance containing the MG settings, and use the existing application.cs beanFactory as the parent bean factory as is.
Is that correct?
Um... not 100% sure if I'm reading you right, but my understanding is that it would make a new pointer again, so it wouldn't take any more (or less) RAM.
You do bring up a good side point though. If I edit my beans.xml, I'd have to ensure I rerun onApplicationStart(). I'd just add a hook to onRequestStart that does that, and uses the same URLs hooks as ModelGlue.
@Ray The "side point" was my main concern. ;) Setting reload to true in MG settings would have no effect on the parent bean factory. You would have to pass a url variable every time you want a reload. Could be a little (admittedly, just a litte :)) inconvenient during development.
But my guess would be that the <import> technique mentioned by Josh WOULD do a re-instantiate the imported bean factories. Can you confirm that Josh?
Yes. Using thing import method all bean factories are re-instantiated. I have used this method on a bunch of different projects and have never had a problem.
- JS
Thanks Josh. I did not know about this either. Nice stuff!
@Raymond: Maybe it's really just a peanut, but the MG-Settings in the CS-Config are project-based too. In other words, they belong these are rather project-settings than framework-settings to me. And it's up to ColdSpring to manage it's Config. That't why I use the same technique as Josh. But I also see your point - separation isn't bad at all. By the way: In which reference should it be mentioned? CS or MG?
@Josh: I do it the same way and never ever noticed any problems with it. So I'm very happy with it.
Hope, my points aren't lost in translation...
The include directive should be mentioned in the CS ref as it is a CS directive, not MG. (Well MG supports INCLUDE as well, and it is the same idea, but its another product.)
A Tip: This drove me batty today. My MG application is set to autoreload. I noticed though that changes to my controllers were showing up, but not changes to my model. Doh. I had forgot that I was storing the CS factory in the app scope, which was NOT auto-reloading.