The Grade Schooler's Guide To ColdSpring - Part 1 Naked ColdSpring

Introduction

"ColdSpring is a framework for ColdFusion Components, inspired by the Spring Framework for Java, and its core focus is to manage the dependencies within your CFC "model." (2). ColdSpring has been around for several years now, but I'd not really used it on a project yet. However, recently I took over the maintenance of a very large ColdSpring/Mach-II application and also am working with the Kansas City user group on creating a new user group web site that is using ColdSpring and Model-Glue. So I needed to get smart on ColdSpring and how to use its many features.

A review of the ColdSpring documentation and tutorials on the web showed that there were not many code examples with explanations of how to use ColdSpring at the "grade school" level. If Dave Ross, Chris Scott, Sean Corfield, and others are at the doctorate level, I'm still in 3rd (maybe 4th) grade in my ColdSpring education. Also many of the available examples have ColdSpring wrapped up in a framework such as Mach-II or Model-Glue. Of course, ColdSpring is very useful in complex applications that have lots of inter dependent CFCs, which is when you're also probably going to use one of the common frameworks like Mach-II.

But I think to learn ColdSpring and what it can do, it is helpful for someone at the grade school level to look at the code for a simple application that just uses ColdSpring's basic functions. Trying to learn ColdSpring and Mach-II (or Model-Glue) together can be daunting for our young and delicate minds. Also our attention span as grade schoolers is a bit shorter than those graduate level folks.

So my goal with this blog post is to provide you some very basic code and notes that explain a simple introductory use of ColdSpring. If people find this blog entry useful, I'll build on it in the future with code that shows how to use other ColdSpring features.

What This Blog Entry is Not

This is not the place to debate why we should or should not use ColdSpring. This is also not the place to learn how to create CFCs or the use of Service, Gateway, DAO, and Bean CFCs. There are many excellent resources for those concepts. I'm also not covering why or how a CFC can be dependent on one or more other CFCs (see reference 3 below for a good introduction to that concept and why ColdSpring is useful).

This is most definitely not the place to get answers to your ColdSpring questions. See reference 1 for places you can post your ColdSpring questions and (maybe) get answers from the PhDs of ColdSpring. Remember, I'm just trying to get through ColdSpring grade school right now.

If you have a specific question or comment about this example and my code, please do post a comment. If you know of a good ColdSpring tutorial (not those wrapped up also in another framework) please post a link.

What Do You Need To Have and Know

You need to understand how to write and create CFCs. You should be familiar with the concept of using a Service CFC to be the "front-end" of your model. This basic example uses UserService and UserDAO CFCs. The UserService is our application programming interface (API) and all requests for information about a user or group of users by the CFM pages goes through the UserService CFC. The UserDAO CFC is used for data access. Note that neither the UserService or UserDAO CFCs are complete. There is just enough code in each CFC to illustrate this example.

You need either MySQL or Microsoft Access. The SQL to create and populate the tblUser (the database table used by this example) in a MySQL database is found in the data folder of the code download. There is also a Microsoft Access database with a tblUser in the data folder. You must create a datasource in the ColdFusion administrator that connects ColdFusion to whichever database you use. In my example I called the datasource that connects to the MySQL database "justCSdbMySQL" and the datasource that connects to the Access database "justCSdbAccess."

Of course you need the ColdSpring framework files. Use reference 1 below to download those files and place the ColdSpring folder in your web root.

Setup The Example Code

Download the example code zip file. You will need to extract the files to where you put ColdSpring in your web root. You should extract my code example zip files to the coldspring/examples folder (the examples folder is included in the ColdSpring framework download. If you've done this successfully, you should have a folder named JustColdSpring in ColdSpring/Examples.

Make sure you have a working datasource that connects ColdFusion to either the MySQL or Access database described above. If the name of that datasource is not "justCSdbMySQL" then you'll have to change this line in the file services.xml:

<value>justCSdbMySQL</value>

to <value>your_datasource_name</value>

If you've done everything correctly then you should be able to run the index.cfm file (for example:

http://localhost:8500/coldspring/examples/justcoldspring/index.cfm?reloadapp) and see Bruce Phillips in the rendered page.

Explaining The Example Code

application.cfm


<!---application.cfm--->
<cfapplication name="JustColdSpring" />

<!---setup the ColdSpring bean factory and setup the beans defined in services.xml.
The bean factory object name is beanFactory.
The beanFactory will only be placed into application scope once unless reloadApp URL
variable exists--->

<cfif not structKeyExists(application,"beanFactory") or structKeyExists(url,"reloadApp")>

    <cflock name="JustColdSpring" timeout="25">
    
        <cfif not structKeyExists(application,"beanFactory") or structKeyExists(url,"reloadApp")>
        
         <!---create the beanFactory object in application scope by calling the
            DefaultXMLBeanFactory CFC's init method--->

            <cfset application.beanFactory =
             createObject('component', 'coldspring.beans.DefaultXmlBeanFactory').init()/
>

    
            <!---read the services.xml file and create CFC objects for each bean defined in the
            services.xml file--->

<cfset application.beanFactory.loadBeans(expandPath("services.xml"))/>
            
        </cfif>
        
    </cflock>
    
</cfif>

Let's start by looking at the application.cfm file. After I give the application a name, I need to check whether or not ColdSpring has been used to create the beanFactory object.

Think of a ColdSpring BeanFactory as the container, or holder, for your application's components. It will instantiate, configure, and resolve the dependencies among the components (beans) you place inside it. (4)

The BeanFactory is the heart of ColdSpring. A beanFactory object resides in application scope and we can use it throughout our ColdFusion application to get a reference to our CFC objects (which ColdSpring refers to as beans in the services.xml file [see below]). If the beanFactory object doesn't already exist in application scope (or if the URL variable reloadApp exists) I have the ColdSpring CFC DefaultXmlBeanFactory call its init method to create a BeanFactory object that I store in application.beanFactory. I then call the BeanFactory CFC's loadBeans function, passing it the file name of services.xml.

Remember, all the above is only done the first time the application is run. If I later make changes to one of the CFCs being managed by the beanFactory object, then I need to be sure to have a URL variable named reloadApp in the URL to force the code to redo the creation of the beanFactory object. Otherwise the changes I've made to a CFC will not be available to the running application.

services.xml


<?xml version="1.0" encoding="UTF-8"?>
<!--
services.xml
defines beans (CFC objects)
resolves dependencies between the CFCs
-->


<beans>

<bean id="userService"
class="coldspring.examples.justcoldspring.model.UserService">

<!-- these properties refer to other beans that are (or will be) defined)
        the UserService CFC must have a setUserDAO function. That function will
        receive a userDAO object created by ColdSpring (see bean with id of userDAO
        below -->

<property name="userDAO">
<ref bean="userDAO"/>
</property>

</bean>

<!--ColdSpring will create a userDAO object and pass it to the UserService CFC's
    setUserDAO method (see code above)-->

<bean id="userDAO"
class="coldspring.examples.justcoldspring.model.UserDAO">

        
<!-- we'll explicitly pass in the datasource name to the init constructor
        the init function must have a cfargument named dsn
        justCSdbMySQL should point to the MySQL database or
        you could use justCSdbAccess which should point to the Access database -->

<constructor-arg name="dsn">
<value>justCSdbMySQL</value>
</constructor-arg>

</bean>
    
</beans>

The services.xml file is used to tell ColdSpring what CFC objects (bean) we need for our application and also what dependencies exist between the CFCs.

The second bean above with the id attribute of userDAO tells ColdSpring to create a UserDAO object using the CFC given in the class attribute. The contructor-arg tag tells ColdSpring that the UserDAO's init method has a cfargument with the name of dsn and ColdSpring should send the value justCSdbMySQL to the init method for that dsn argument's value. See the UserDAO (in the model folder) for the init function. ColdSpring expects the UserDAO CFC to have an init method, which acts as a kind of constructor for the CFC.

So the UserDAO is depending upon a value being sent to its init method so that the variables.dsn property gets a value that the rest of the functions in the UserDAO CFC may use. ColdSpring has resolved this dependency for us.

Look over the first bean (id="userService") defined in the services.xml file. This bean definition tells ColdSpring to create a userService object using the UserService CFC given in the class attribute. The property tag tells ColdSpring to call the setUserDAO function in the UserService CFC and send as argument to that function the userDAO object (the one created by the second bean definition and identified by the id value of userDAO).

If you examine the code for UserService CFC you'll see that it is dependent on knowing an object of type UserDAO so that it can call the UserDAO's read function (see function getUserByID). The UserService CFC has a setUserDAO function that is used to provide the variables.m_userDAO property with a UserDAO object that can then be used in all the other functions of UserService. ColdSpring resolves this dependency for us by how we've defined the userService bean in the services.xml file.

Note that when you use the property tag to tell ColdSpring how to resolve a dependency, ColdSpring expects there to be a set function that matches up with the name attribute. So our UserService CFC must have a setUserDAO function.

index.cfm


<cfset userService = application.beanFactory.getBean('userService')>

<cfinvoke component="#userService#" method="getUserByID" returnvariable="user">
    <cfinvokeargument name="userID" value="1">
</cfinvoke>

<cfdump var="#user#" />

To get a reference to a CFC object being managed by ColdSpring you can use the beanFactory method getBean and send it the name (the id value you setup in services.xml) of the CFC object you want. So my userService variable above refers to the userService CFC object being managed by ColdFusion. This UserService object will have had its dependencies resolved as specified in the services.xml file.

Once I have a reference to the CFC object, I can call its methods as normal. So in the above code I use cfinvoke to call the getUserByID method and the query object returned by the getUserByID method is stored in the variable user.

Points to Note

My UserDAO and UserService CFCs are ignorant of ColdSpring. Except for using an init function as a constructor (which is regarded as a CFC best practice), ColdSpring makes no requirements of the CFCs. I could very easily reuse these two CFCs in an application that doesn't use ColdSpring.

Remember, if you change a CFC, then you must include the URL variable reloadApp to force ColdSpring to recreate the beanFactory in application scope.

Summary

ColdSpring is capable of much more than resolving dependencies between CFCs. As we advance from grade school, to middle school and beyond, we'll become better able to use ColdSpring's features. This basic tutorial is just an introduction of how to use ColdSpring naked, outside of another framework like Model-Glue.

Let me know if this tutorial was useful for you, if you'd like me to continue posting basic ColdSpring tutorials, or if something I've written needs better explanation.

Time for recess!

References:

  1. ColdSpring Framework, http://www.coldspringframework.org/
  2. ColdFusion Developer's Journal Special "Frameworks" Focus Issue: ColdSpring; http://coldfusion.sys-con.com/read/176181.htm
  3. The Blog of Andy Jarrett, ColdSpring and Dependency Injection for the beginner part 1
  4. ColdSpring Online Documentation, http://www.coldspringframework.org/docs/
  5. Example Code For This Blog Entry, http://www.brucephillips.name/blog/justcoldspring.zip

Comments (Comment Moderation is enabled. Your comment will not appear until approved.)
yes more, please :)

new to coldspring (by way of being new to model-glue). some good, in-depth beginner level tutorials for CS itself would be very cool, so by all means, please continue the series.

especially the service layer stuff. dealing with the bean, the dao, the gateway, and the service CFCs can be a little too much of "what-goes-where" for a n00b (yes, i speak from experience) :)
# Posted By charlie griefer | 12/30/07 10:10 AM
very informative. thank you very much for this. I've been interested to learn about Coldspring but every article i start to read uses every big word and concept they can find in the opening paragraph and my eyes glaze over. thanks for the "grade school" version. please continue with the series
# Posted By Ed Lamp | 12/30/07 10:23 AM
Thanks for this write up. I look forward to more on the same topic. I'm definitely with you in the gradeschool level with ColdSpring.
# Posted By Derek | 12/30/07 7:13 PM
I had a hard time trying to figure out the concepts at Coldspring website but when I read your article, I understood it easily. You did a great job. Please continue the same for more lessons.
# Posted By siby thomas | 12/31/07 10:00 AM
thanks for the post
# Posted By Lazer Kesim | 1/25/08 1:00 PM
Great article, I landed here trying to understand CS in a Model Glue setting and is already in my del.icio.us page.

I concur with other readers, a CS - Model Glue intro article would be great.

Thanks
Fernando
# Posted By fernando lopez | 2/22/08 11:39 AM
Excellent introductory article. I landed on this page after googling a little bit and going through a couple other articles. I have to say I agree with Ed above in that the other articles I found used all the big words and concepts of AOP and what not, whereas this is truly written with the noobs in mind, simple and straightforward. Keep up the good work and please keep 'em coming.
# Posted By TG | 6/3/08 3:54 PM
Hello,

We can call the directly the userdao.cfc file for retrieving the record set by initializing the methods into userservice.cfc.

But,
We can call the methods directly the userdao.cfc file for retrieving the record set then why should we use the userservice.cfc only for storing the functions.

Can you guide me please
# Posted By Ankit | 11/22/08 4:16 AM
Ankit - It's a very common and useful design to have a Service class that an application communicates with and the Service class calls upon other classes to do the work. This way if we change the userdao.cfc we don't have to change the application that interfaces with the userservice.cfc. Additionally, if we add a usergateway.cfc (used to get collections of users) we just need to add that to the userservice.cfc and the application will still only need to communicate with one class userservice. Google service gateway dao bean coldfusion to see other examples and a more complete explanation.
# Posted By Bruce | 11/22/08 9:05 AM
BlogCFC was created by Raymond Camden. This blog is running version 5.9.1.002. Contact Blog Owner