So you want to create a ModelGlue:Unity application? ( Part 7 )

We are going to break this up into phases starting with the contact types. At the end of this series, our contact types will come from the database and we will have an even greater appreciation for ModelGlue and ColdSpring.

The last article gave the spec for your database tables, Contact and ContactType. Add in 3 dummy records to the ContactType table. I used Friend, Enemy and Co-worker.

Set up your datasource in the ColdFusion administrator. I used the data source name of 'ContactOMatic'. Test the connection and move on.

Now we will need this datasource name inside of our cfqueries. Can anyone guess where we will keep the DSN? Thats right, in ColdSpring. Give yourself a cookie if you got that one right.

Before we begin, change the ColdSpring.xml ModelGlueConfiguration reload setting to true.

ModelGlue has a standard component called a SimpleConfig. The purpose of the simple config is to hold on to a collection of values and this component is easily configured in ColdSpring. The path for SimpleConfig is ModelGlue.bean.CommonBeans.SimpleConfig, so add a configuration to ColdSpring for this. We will refer to this as AppConfig and it will hold our DSN and an AppTitle.

view plain print about
1<bean id="AppConfig" class="ModelGlue.Bean.CommonBeans.SimpleConfig">
2        <property name="Config">
3            <map>
4                <entry key="AppTitle"><value>Contact-O-Matic</value></entry>
5                <entry key="dsn"><value>ContactOMatic</value></entry>                
6            </map>
7        </property>
8    </bean>

Run your application. If you have an error at this point, check the exact path to the SimpleConfig component. No errors? Perfect!

Simple enough so far, right? Now we shall write our ContactTypeGW. This component will pull a query of ContactTypes from the database. There are three functions in the ContactTypeGW.

  1. setAppConfig - this function provides the way for ColdSpring to stick the AppConfig component in the ContactTypeGW
  2. getAppConfig - this function provides a way for us to reference the AppConfig component inside the ContactTypeGW
  3. getContactTypeQuery - this function returns the ContactTypes from the database

Your ContactTypeGW should look like this:

view plain print about
4 <cffunction name="getContactTypeQuery" access="public" output="false" returntype="query">
5 <cfset var ContactTypeQuery = "" />
7 <cfquery name="ContactTypeQuery" datasource="#getAppConfig().getConfig().dsn#">
8 SELECT ContactTypeID, ContactType
9 FROM ContactType
10 </cfquery>
12 <cfreturn ContactTypeQuery />
14 </cffunction>
19 <cffunction name="getAppConfig" access="public" output="false" returntype="any">
20 <cfreturn variables.instance.AppConfig />
21 </cffunction>
23 <cffunction name="setAppConfig" access="public" output="false" returntype="void">
24 <cfargument name="AppConfig" type="any" required="true" />
25 <cfset variables.instance.AppConfig = arguments.AppConfig />
26 </cffunction>

Note for the DSN we used 'getAppConfig().getConfig().dsn', when we want to access the AppTitle later, we'll use 'getAppConfig().getConfig().AppTitle'. (If you haven't seen this syntax before, getAppConfig() returns a reference to the AppConfig Object, which has a getConfig() function returning a struct. Then we access a property of the struct using dot notation.)

Now, adjust the ContactService to call ContactTypeGW. Remove the following functions: init, getContactTypes and setContactTypes. Add get and set functions for our ContactTypeGW. Then add the proper function for getContactTypes. It should return a query so be sure to adjust the returntype to 'query'

Your ContactManangerService should look like this:

view plain print about
4    <!---
6    --->

7    <cfset variables.instance = StructNew() />
10    <cffunction name="getContactTypes" access="public" returntype="query" output="false">
11 <cfset var ContactTypes = getContactTypeGW().getContactTypeQuery() />
12 <cfreturn ContactTypes />
13 </cffunction>
15 <cffunction name="getContactTypeGW" access="public" output="false" returntype="any">
16 <cfreturn variables.instance.ContactTypeGW />
17 </cffunction>
19 <cffunction name="setContactTypeGW" access="public" output="false" returntype="void">
20 <cfargument name="ContactTypeGW" type="any" required="true" />
21 <cfset variables.instance.ContactTypeGW = arguments.ContactTypeGW />
22 </cffunction>
24    <cffunction name="setContactList" access="public" returntype="void" output="false">
25        <cfargument name="ContactList" type="array" required="true" />
26        <cfset variables.instance.ContactList = arguments.ContactList />
27    </cffunction>
28    <cffunction name="getContactList" access="public" returntype="array" output="false">
29        <cfreturn variables.instance.ContactList />
30    </cffunction>

Now adjust ColdSpring to account for the new gateway functionality. Configure the bean definition for ContactTypeGW and add the AppConfig property. Replace the ContactType map with the ContactTypeGW bean The changed lines should look like this:

view plain print about
1<bean id="ContactService" class="ContactManagerMG.model.ContactService">
2        <property name="ContactList">
3            <list></list>
4        </property>
5        <property name="ContactTypeGW"><ref bean="ContactTypeGW" /></property>
6    </bean>
8 <bean id="ContactTypeGW" class="ContactManagerMG.model.ContactTypeGW">
9 <property name="AppConfig"><ref bean="AppConfig" /></property>
10 </bean>

Finally, our contact form was expecting a struct, it will now get a query so adjust the ContactType section accordingly

view plain print about
1<cfloop query="ContactTypes">
2 <option value="#ContactType#" <cfif ContactFormBean.getContactType() IS ContactType>selected</cfif>>#ContactTypes.ContactType#</option>

Remember to reinitialize your application and now run your code. You should now see the ContactTypes defined in your database

It seems like we touched a few files to make this change. We altered the ColdSpring.xml file to have an application configuration object, added in our ContactTypeGW and then stitched them together. We also had to adjust our form to account for a query in place of the struct. Note we did not touch our Controller nor our ModelGlue.xml file. Since the flow of the application did not change, those files remain the same and happily work with the new functionality of the application. This is an example of the benefits of compartmentalized, or encapsulated, code.

A zip of all files is included with this article.

Next, we will create the contact persistance and write our contacts to the database

Download Download

There are no comments for this entry.

Add Comment Subscribe to Comments

1/7/09 4:57 PM # Posted By Sunikumar

Found your site very helpful in learning the framework.
I would have appreciated if you would include some debugging information and how to debug code when using the framework!

3/30/09 1:14 AM # Posted By Joe

Instead of introducing the dsn in each and every GW/DAO object, what do you think about extending some base connection cfc that has the DSN? Is this bad form in your view?

3/30/09 1:18 AM # Posted By Dan Wilson


I would consider extending from a base object, just for the ability to get the dsn stuff automatically, to be bad form.

Inheritance, by using the extends keyword, implies that an object is also of Type 'x'. This has meaning and also has relevance on a much broader aspect and should be used properly.

Keep in mind, Inheritance, (the 'Extends' keyword) is not the same as CFInclude.

My 2 Cents.