Categories
Contact Doug!
Learn About Doug!
View Doug Boude's online resume
updated 11/18/2009

View Doug Boude's profile on LinkedIn
Link to me!

Follow Doug Boude on Twitter
Follow me!

Be Doug's friend on Facebook
Befriend me!
(I promise not to follow you home)
OO Lexicon
Chat with Doug!
Recent Entries
You may also be interested in...
Web Hosting

<< October, 2014 >>
SMTWTFS
1234
567891011
12131415161718
19202122232425
262728293031
Search Blog

Recent Comments
Re: My Top 20 Life Lessons for Boys and Young Men (by jeffrey scott berry at 9/16 2:42 PM)
Re: Equivalent of SQL "TOP X" in Oracle (by Mark Foster at 7/07 4:04 PM)
Re: SQL Forward Engineering with Visio 2003 Professional (by Thomas at 6/26 4:41 AM)
Re: One Shot Query to Recalculate Orderby Field - MySQL (by gary at 6/17 6:46 PM)
Re: DON'T GET SICK IN ARKANSAS! (by r. wood at 5/25 12:00 AM)
Re: SQL Forward Engineering with Visio 2003 Professional (by Andrew at 4/30 6:14 AM)
Re: Basic Ajax Select List Filter in PHP (by good at 2/04 5:26 AM)
Re: Family Law: The Weapon of Choice for Woman Scorned (by swalker at 2/03 2:15 AM)
Re: Approaches to Building Strings: The Imploding Array (by bantal silikon at 2/01 9:44 PM)
Re: Disappearing IE Popup Window During Save/Open Dialog (by AddisonDean at 1/15 9:59 AM)
Re: My Top 20 Life Lessons for Boys and Young Men (by Alex at 1/13 8:45 PM)
Re: Array Loop Modifications in CFSCRIPT (by Alex at 11/25 11:18 AM)
Re: Array Loop Modifications in CFSCRIPT (by Abram at 11/14 11:32 PM)
Re: Recursive Functions in ColdFusion (by Dwayne at 10/25 3:47 PM)
Re: Porting Coldfusion Code to Mura (by dh at 10/16 10:14 AM)
Re: Viewing Option Text (in IE7) that's Wider than the Select List (by Devil May Cry at 9/26 1:38 AM)
Re: Why I Hate ORMs (a solicited rant) (by guideX at 9/12 11:38 PM)
Re: Recursive Functions in ColdFusion (by KP at 8/08 7:13 PM)
Re: American Airlines, YOU SUCK! (by Alison at 7/23 4:48 PM)
Re: SQL Forward Engineering with Visio 2003 Professional (by Harshad at 7/11 9:17 AM)
Archives
Photo Albums
Funnies (5)
Family (3)
RSS

Powered by
BlogCFM v1.11

10 June 2007
Global Configuration Settings in Model-Glue:Unity
Some Suggestions
When making the transition from procedural CF to OO, sometimes what was SO simple before can become a challenge (at least the first time). For instance, the way we used to pass around our app's DSN value was probably something along the lines of setting an application variable in our application.cfm or cfc, thus making it accessible throughout our app while consolidating the value to a single location for ease of change later. But now that we've decided to force ourselves to learn to do things in an OO fashion, where on earth is the "correct" place, or what is the "correct" way to perform this same action?

In our procedural apps, common sense told us to "find a place within the execution path that always gets called, no matter what, and check for and set your global value there...". Let's use that same line of thinking for our OO app, too, and find an appropriate spot in which to set our global variable.

Even in an OO approach, CF still respects application.cfc/cfm, so setting the value there could be an option. However, one of the chief tenets of OO is encapsulation, meaning that we try to make each aspect of the application as non-dependent as possible on the rest of the application. Setting our DSN in application.cfc/cfm then means that likely our urge would be to stuff it into the application scope:

<cfset application.dsn = "Horton" />

If I want to use that value within any of my model CFCs then, SOMEWHERE I'd have to write a line of code that talks to the application scope; not a best practice, and indeed immediately makes my CFC dependent on the existence of some value outside of itself. No bueno.

How 'bout instead we utilize a configuration bean...a tiny object whose sole purpose in life is to pack around global values I might need here and there, and to make itself available anywhere within my app? Now that makes my common sense tingle with delight. Utilizing Model-Glue:Unity, let me share a couple of ways I have done this very thing.

At this juncture, if you aren't familiar with the member of the Model-Glue: Unity trinity called Coldspring, it's time you two met. Coldspring is an expert bean handler, and is quite a versatile fellow when it comes to creating beans and making them available wherever you'll be needing them. Coldspring does all of what it does based on the content of its XML configuration file (Coldspring.XML), so it is within that file where we will 'instruct' it regarding our configuration values.

At this point you're probably thinking to yourself, "okay self, all I need to do then is create a CFC that handles configuration values for my app. I'll make a getter and setter method for my DSN, one for my images directory path, one for....". Hey, that is definitely a good way of thinking. HOWEVER, Coldspring has a surprise for you, O Best Beloved. Coldspring can automagically create that configuration bean for you, and all you gotta do is tell it what you want it to contain via the Coldspring.XML file! Allow me to
elucidate.

In order to auto-create one of these configuration beans, let's define it within Coldspring.XML, like so:
  <bean id="AppConfiguration" class="ModelGlue.Bean.CommonBeans.SimpleConfig">
    <property name="Config">
      <map>
    <!-- this is the DSN used throughout the app... -->
        <entry key="DSN"><value>Horton</value></entry>
    <!--  path the CSS directory -->
        <entry key="CSSPath"><value>/appCSS/</value></entry>
      </map>     
    </property>
  </bean>
(Note: Notice the class of our configuration bean...we're leveraging a built-in class of model-glue)

Now that we've defined it, from this moment onward we'll maintain our app settings RIGHT THERE. If the DSN changes, I'll change the value of the DSN entry key.

Making this configuration bean available throughout the app is a purposeful endeavor, meaning that you have to explicity tell Coldspring to make it available to a specific CFC. We do this by "injecting" it into other CFCs that we've told Coldspring about. Looky here:

  <bean id="EmailService" class="model.EmailService">
    <constructor-arg name="AppConfiguration">
      <ref bean="AppConfiguration" />
    </constructor-arg>
  </bean>

I've told Coldspring "I have an EmailService.CFC, and it is expecting an argument value named 'AppConfiguration', so when you instantiate EmailService for me, please go ahead and pass in an instance of my AppConfiguration bean as that value. Thanks man."

Okay, the only other thing you have to do in order for this to work smoothly is to ensure that the object you're wanting to inject the configuration bean into is prepared to receive it. With the approach we're taking, the proper way to do this is to make sure your CFC has an init method, and within that init method create a required argument named exactly the same as your constructor-arg name. Like so:

<cffunction name="init" returntype="EmailService" output="false" hint="Constructor">
    <cfargument name="AppConfiguration" required="true" />
    <cfset variables._config = arguments.AppConfiguration />
    <cfreturn this />
</cffunction>

Okay, so now we have our Coldspring simple config object injected. Pay attention, this is important: for every value we defined for this config object, you will access it via the following method: getConfigSetting([value name]). For instance, if within our EmailService object we have a method that needs the DSN value, we'll grab it with
<cfset myDSN = variables._config.getConfigSetting("DSN") />

Alternatively (and this is what I did), you can create a generic "GetConfigSetting" method within your recipient object, like so:

<cffunction name="GetConfigSetting" access="private" returntype="string" output="false">
    <cfargument name="name" required="true" type="string" />
    <cfreturn variables._config.getConfigSetting(arguments.name) />
</cffunction>

With that method present in your recipient object, you would access the DSN like this:

<cfset myDSN = GetConfigSetting("DSN") />


It's a little cleaner, I suppose.

Now, you could be thinking that since your config object contains values that may also be needed within a view, such as a CSS path, or an images directory path, that you'll need a way to make it available there, too. Let me toss out a suggestion based on the way I have done it.

Everytime a MG:U event is called, you can have listeners that execute beforehand based on the fact that they're listening for a call to "OnRequestStart", as in this snippet from my modelglue.XML file:


<controller name="MyController" type="controller.Controller">
   <message-listener message="OnRequestStart" function="loadConfiguration" />
</controller>

You can, within the method being referenced in onRequestStart, stuff the configuration bean into the event object, thus making it available to every other object referencing that event, INCLUDING your views! Let's look at the controller object mentioned in this example:

<cfcomponent displayname="Controller" extends="ModelGlue.unity.controller.Controller" output="false">
    <!--- Autowire / private getter --->
    <cffunction name="setAppConfiguration" access="public" returntype="void" output="false">
        <cfargument name="AppConfiguration" required="true" type="any" />
        <cfset variables._config = arguments.AppConfiguration />
    </cffunction>
    <cffunction name="getAppConfiguration" access="private" returntype="any" output="false">
        <cfreturn variables._config />
    </cffunction>


    <!--- Place the configuration bean into the viewstate --->
    <cffunction name="loadConfiguration" access="public" returnType="void" output="false">
      <cfargument name="event" type="any">
      <cfset arguments.event.setValue("appConfiguration", getAppConfiguration()) />
    </cffunction>
</cfcomponent>

A few things to point out here:
1. Because this object is a controller object, Coldspring gives us the privilege of autowiring in beans that it knows about by simply providing it with a "get" and "set" method named according to the bean we want to inject. In this instance, Coldspring already had created for us a bean called AppConfiguration, so by virtue of the fact that Coldspring saw our controller object had a method named "getAppConfiguration" and "setAppConfiguration", it assumed we wanted it to inject an instance of the AppConfiguration bean. Coool.
2. On request start, Model-Glue is calling our "loadConfiguration" method, which is taking the injected configuration bean and placing it into the Event bucket (some like to call it the event 'bus', but thinking of it as a bucket makes more sense to me). This automatically means that the configuration bean will be available in our viewstate as well, and from within any view can be referenced like


<cfset appConfig = viewstate.getValue("appConfiguration") />

<link rel="stylesheet" type="text/css" href="<cfoutput>#appConfig.getConfigSetting("CSSPath")#</cfoutput>styles.css" media="screen" />

Now, having shared all of that, I will tell you that if you're using Reactor within your app, you were already defining the DSN within the Coldspring Reactor Bean, and may not want to define the DSN twice, but rather would like to use Reactor's DSN value throughout your app. This can be done just as easily, only you'll be injecting not your appConfiguration bean into the CFCs that need the DSN value, but the "reactorConfiguration" bean instead (already exists within your Coldspring.xml file). Once injected, you'll get at your DSN value with a method called "getDSN()".

Here's something else to chew on that may be helpful to you (as it was for me): Besides just a global application config bean, you can also define configuration beans for different services that your app has. For instance, my app performs image manipulation, so within my Coldspring.xml file I defined a configuration bean called "ImageServiceConfig" that contains settings for thumbnail dimensions, large image dimensions, naming conventions, pathing information, etc., then I inject that bean into my ImageService.cfc. I do the same thing for my EmailService.cfc. This allows me to truly consolidate all of my application settings within my Coldspring.xml, simplifying maintenance in that regard.

That, Boys and Girls, is injection at its finest, and it allows me to maintain my app's global values in one place, just like I used to do with application.cfc/cfm.

Doug out.



Posted by dougboude at 9:58 AM | PRINT THIS POST! |Link | 8 comments
Subscription Options

You are not logged in, so your subscription status for this entry is unknown. You can login or register here.

Re: Global Configuration Settings in Model-Glue:Unity
Doug,

These helpful hints, tips, and tutorials are great for those of us (killing themselves) trying to make the transition from procedural to OO. Please keep it coming. No tidbit is too small. =)

Thanks again...

Josen Ruiseco
Member of KCCFUG (KCDEVCORE)
Posted by Josen Ruiseco on June 10, 2007 at 4:46 PM

Re: Global Configuration Settings in Model-Glue:Unity
I need to get more into this.
Posted by blackberry on June 13, 2007 at 11:37 AM

Re: Global Configuration Settings in Model-Glue:Unity
Its very good until "the only other thing you have to do in order for this to work smoothly"
at this point i scratching my head (for a long time) as it wont work. Then you give autowiring details. Might seem daft to you but it would have helped if they were given before the " Okay, the only other thing you have to do in order for this to work smoothly" was written.

Not being picky just might help others who read it.
Posted by Paul Stewart on September 5, 2007 at 9:14 AM

Re: Global Configuration Settings in Model-Glue:Unity
Sorry to hear you're having trouble getting it to work, Paul. I read back through it and I'm really not sure how I could change the wording. If you email me offline I'd be glad to troubleshoot with you. There can be a lot of factors that come into play sometimes (like, having to re init the app, making sure your OTHER coldspring settings are conducive to showing your changes...things like that)...things I can't necessarily anticipate about another person's setup. Anywho, give me a shout (see my resume for a contact form) and I'll give you whatever assistance I can from here. :)
Posted by dougboude on September 5, 2007 at 10:38 AM

Re: Global Configuration Settings in Model-Glue:Unity
Hi Doug,
The global config explanation is great and I was able to incorporate that already into a couple MG apps I'm trying to update with newer config approaches.

In the last paragraph you touched on using service beans. Do you have any examples of how to incorporate that usage, including instantiation in the controller?

Basically, right now for each of my models I have corresponding bean/DAO/gateway cfcs set up (i.e. userBean.cfc -- which uses instances/getters/setters, userDAO.cfc, userGateway.cfc, and so on for each model). This is an approach I picked up on through various other blogs and has helped me a great deal.

But over the last few months as I research more into how I can better my CF OOP approaches I've noticed (and I'm probably WAY late on this, but better late than never!) that ColdSpring is really the way to go instead of the method I just stated above with the bean/DAO/gateway cfcs. Is this correct? If so, could you possibly point me in the direction of any good tutorials (especially if you have one) that take ColdSpring bean factories specifically within Model-Glue more in depth?

To clarify further, I guess I'm trying to find something that would help me translate my current model setup into the ColdSpring realm so I can start leveraging the DI benefits. I've found some articles that sound like they're what I'm looking for but end up not being helpful for my particular case and specifically using it within MG:Unity environment (I'll be using MG Gesture for some newer apps coming up, most likely).

Your article on global configuration has been the closest so far so I was hoping you had even more I could look into.

Thanks in advance for any suggestions you might have!

Best,
Tony
Posted by Tony Piscotti on July 27, 2008 at 10:30 PM

Re: Global Configuration Settings in Model-Glue:Unity
Doug,

Thanks for the great tutorial. Hadn't thought of approaching it that way. I've implemented it on one of my MG apps and I'm liking the way it's setup now.

Thanks!

- Josh
Posted by Josh Grauer on January 20, 2009 at 3:41 PM

Re: Global Configuration Settings in Model-Glue:Unity
No problemo, Josh! Glad you found it useful. :)
Posted by dougboude on January 20, 2009 at 4:59 PM

Re: Global Configuration Settings in Model-Glue:Unity
Hi,

I've incorporated (read pasted) your instructions into the sample application "translator" and I am getting

"the parameter APPCONFIGURATION to function init is required but was not passed in"

Any help would be greatly appreciated.

--------------------- BEGIN ColdSpring.xml-------------------------------------------






Horton

/appCSS/









--------------------END COLDSPRING.XML-----------------------

--------------------BEGIN EmailService.cfc-------------------

The CFC translator/model/EmailService.cfc:


















--------------------END EmailService.cfc-----------------------

--------------------BEGIN Contoller (part)------------------
Controller:

This is where the debugger says the problem is:
Posted by joegensh on March 23, 2009 at 9:59 PM

Name:   Required
Email:   Required your email address will not be publicly displayed.

Want to receive notifications when new comments are added? Login/Register for an account.

Time to take the Turing Test!!!

Sixteen plus Seventeen equals
Type in the answer to the question you see above:

Your comment:

Sorry, no HTML allowed!