Click to search Andy Jarrett.co.uk RSS feed

Loading Twitter

My blog has moved

Please update your bookmarks and feeds for my site.

I now have a Mango Blog at:

http://www.andyjarrett.com/blog

Feed URL: http://feeds.feedburner.com/andyjarrett

Comments Comments (0) | Print Print | Send Send | 1196 Views

Passing Application scoped variables to ColdSpring within Model Glue

Passing defaultProperties in ColdSpring with Model Glue

Or Using defaultProperties with CS and MG. I couldn't figure out which title would be better.

Basically this is a guide on how to pass variables into ColdSpring. In my case from the Application scope. Recently I've been working on a Model Glue, Transfer, and ColdSpring app and came across a problem which I couldn't find a direct answer to online. The application I'm working is only a small part of the site and has some settings in the Application scope which needs to remain there. Usually I put all my variables in a ColdSpring/Model Glue simpleConfig Bean (using the class ModelGlue.Bean.CommonBeans.SimpleConfig) but this time I needed CS to get the variables from the application scope. This actually isn't too hard as you can pass properties(dynamic variables) into the config.xml e.g.

Here's the code for creating the bean factory. You would find this in onApplicationStart or at the top of your Application.cfm.

Code for Application.cfm/cfc

view plain print about
1<!-- First we create our global vars in the Application scope -->
2<cfset application.settings = structNew() />
3<!-- Add our DSN name to the Settings struct -->
4<cfset application.settings.dsn = "myDSN" />
5<!-- If our bean factory doesn't exist then we create it. You could also check for a url.reinit var as well here -->
6<cfif NOT isDefined("application.beanFactory")>
7    <!-- Our struct to hold the variables we are going to pass to ColdSpring -->
8    <cfset properties = structNew() />
9    <!-- Our struct to hold the variables we are going to pass to ColdSpring -->
10    <cfset properties.dsn = "dsn_reference">
11    <!-- Create our bean object -->    
12    <cfset application.beanFactory = createObject("component","coldspring.beans.DefaultXmlBeanFactory").init(structNew(), properties)/>
13    <!-- Pass a fully qualified path to a bean definition xml file -->
14    <cfset application.beanFactory.loadBeansFromXmlFile(expandPath('/config/beans.xml'), true)/>
15</cfif>

In our Beans.xml we need to reference the properties structure by the key.

Code for Beans.xml

view plain print about
1<?xml version="1.0" encoding="utf-8"?>
2<beans>
3 <bean id="myDAO" class="com.myDAO">
4        <!-- ${dsn} comes from the properties struct we passed in from the Application.cfc/cfm code -->
5 <constructor-arg name="dsn"><value>${dsn}</value></constructor-arg>
6 </bean>
7</beans>

Now that we have our beans.xml reading dynamic variable how can we pass this to the default ColdSpring.xml that Model Glue uses?

First off when it comes to Model Glue there is already ColdSpring.xml which holds all the config imformation for the application, ORM etc etc. We're not going to touch that so this method is something you can introduce midway through a project. What we are going to do is introduce Beans.xml as the Parent Bean Factory to the child ColdSpring.xml.

Create a SimpleConfig bean from Model Glue (ModelGlue.Bean.CommonBeans.SimpleConfig) and save this in the Beans.xml file. This config bean will hold details for our email server. The values are going to come from the Application scope.

You xml file should look like:

view plain print about
1<beans>
2    <!-- Put definitions for your own beans and services here using ModelGlue.Bean.CommonBeans.SimpleConfig class -->
3    <bean id="EmailConfig" class="ModelGlue.Bean.CommonBeans.SimpleConfig">
4        <property name="config">
5            <map>
6                <entry key="emailServer">
7                    <value>${emailServer}</value>
8                </entry>    
9                <entry key="emailUName">    
10                    <value>${emailUName}</value>
11                </entry>
12                <entry key="emailPWord">
13                    <value>${emailPWord}</value>
14                </entry>
15            </map>
16        </property>    
17    </bean>
18</beans>

In the Appliacation.cfm add the following code

view plain print about
1<!-- If our bean factory doesn't exist then we create it. You could also check for a url.reinit var as well here -->
2<cfif NOT isDefined("application.beanFactory")>
3    <cfset application.emailServer    ="" />
4    <cfset application.emailUName    ="" />
5    <cfset application.emailPWord    ="" />
6
7    <!--
8        Put the email settings into the properties structure which
9        get passed to a Parent ColdSpring Factory
10    -->

11    <cfset properties = structNew() />
12    <cfset properties.emailServer = application.emailServer />
13    <cfset properties.emailUName = application.emailUName />
14    <cfset properties.emailPWord = application.emailPWord />
15
16    <cfset application.beanFactory2 = createObject("component","coldspring.beans.DefaultXmlBeanFactory").init(defaultProperties=properties)/>
17    <cfset application.beanFactory2.loadBeansFromXmlFile("#expandPath('/config/beans.xml')#",true)/>
18</cfif>

At this point we have our bean factory stored in application.beanFactory2. We are going to reference this in the index.cfm of MG under the HIERARCHIAL BEAN FACTORY SUPPORT area. Look for the commented out <cfset> which sets the variable ModelGlue_PARENT_BEAN_FACTORY. Uncomment the <cfset> and add the following:

view plain print about
1<!--
2    **HIERARCHIAL BEAN FACTORY SUPPORT**
3
4    If you'd like to designate a parent bean factory for the one that powers Model-Glue,
5    simply do whatever you need to do to set the following value to the parent bean factory
6    instance:
7-->
    
8<cfset ModelGlue_PARENT_BEAN_FACTORY = application.beanFactory2 />

At this point the hard work is done. All that is left is to add a bean that uses the config setting. In my case I have a CFC in a Model folder which accepts the constructor argument "EmailConfig" e.g.

view plain print about
1<bean id="email" class="model.emailCFC">
2    <constructor-arg name="EmailConfig">
3        <ref bean="EmailConfig" />
4    </constructor-arg>
5</bean>

Thats it. From your emailCFC you just need to reference variables.emailConfig.getconfigSetting('emailServer') to the get the server etc.

This post couldn't of been done without the help of http://www.danvega.org/blog/index.cfm/2006/11/25/Passing-Properties-To-ColdSpring and http://groups.google.com/group/model-glue/browse_thread/thread/de628a4fb85c6ebd/ so for futher investigation you can start there.

Comments Comments (0) | Print Print | Send Send | 3486 Views

Adding Spry includes in a Model Glue template

As the Spry(and any Ajax framework) files aren't the smallest set of files to add to your page you don't want the user to download them if they don't need to. The way I add the Spry files to a display template in Model Glue is per event via a variable defined in the XML controller. For this example I'm going to include the SpryCollapsiblePanel.js file.

1. The first change we make is to your display(also known as Layout) template. At the very top of the template add the following:

view plain print about
1<!---
2    This sets up the variable needSpryCollapsiblePanel with the value of false if it
3    cannot be found in the viewState
4--->

5<cfset needSpryCollapsiblePanel = viewState.getValue('needSpryCollapsiblePanel', false) />

Then in the <head> section add the following

view plain print about
1<!---
2    If needSpryCollapsiblePanel is True then we include the SpryCollapsiblePanel.js
3    I have omitted the CSS files that also come with this widget as I add my own.
4--->

5<cfif needSpryCollapsiblePanel>
6    <script src="/includes/widgets/collapsiblepanel/SpryCollapsiblePanel.js" type="text/javascript"></script>
7</cfif>

2. In the ModelGlue.xml we are going to modify a basic event i.e Before:

view plain print about
1<event-handler name="page.index">
2    <broadcasts />
3    <views>
4        <inc1ude name="body" template="dspIndex.cfm">
5    </views>
6    <results>
7        <!--
8            Layout template
9        -->
        
10        <result do="view.template" />
11    </results>            
12</event-handler>

After: Using the above event we are going to add a variable to the ViewState

view plain print about
1<event-handler name="page.index">
2    <broadcasts />
3    <views>
4        <!--
5            dspIndex.cfm is the template which needs
6            to use the Spry files
7        -->

8        <inc1ude name="body" template="dspIndex.cfm">
9            <!--
10                This value will be available in the viewState
11            -->

12            <value name="needSpryCollapsiblePanel" value="true" />
13        </include>
14    </views>
15    <results>
16        <!--
17            Layout template
18        -->

19        <result do="view.template" />
20    </results>            
21</event-handler>

And thats it. When you go to index?event=page.index the <views> will include your file that needs Spry while setting a variable to tell your Layout <result> to add the line of script to the <head>

N.B. There is a deliberate spelling mistake in my MG events due to a small small bug in BlogCFC

Comments Comments (3) | Print Print | Send Send | 3078 Views

Frameworks DTD files

I hope this doesn't come across as a moan as its meant to be more of a general question to the community. But with all the main frameworks out there running on XML config files, where are the official DTD's hosted for these? I know there are several around hosted in odd locations (no disrespect), but I was just looking to put together a definitive list of the locations.

I know you can get them via subversion etc but shouldn't/couldn't they be hosted on the respective sites??

Comments Comments (4) | Print Print | Send Send | 3393 Views

Multi-lingual site with Model-Glue and Coldspring

Now and then through my work I get asked to create a site with multi-lingual support. In the past I have usually just created a custom tag or UDF. This time, now that I am on A href="http://model-glue.com/">Model Glue: Unity I wanted something that was a little more integrated so I decided to use Ray Camden modified ResourceBundle.cfc. This cfc was actually created by Paul Hastings and you can find more information here.

There are two reasons I am posting this mini guide, first to share and the second is that knowing me I am probably doing something inefficient and by letting the community see it hopefully someone will point out any errors or an easier way to do things :o)

I've zipped up Pauls/Rays ResourceBundle.cfc that comes with BlogCFC and you can download it by clicking here.

Lets's begin:

  1. Download the file and put it in your projects model directory, so the url to this CFC would be http://yourlocalproject/model/resourcebundle.cfc.
  2. Also in your model directory create new folder called "locale_data" and in there add a file called en_US.properties.
  3. Open up resourceBundle.cfc and change the method(function) "loadResourceBundle" to "init". The reason for this is that we are going to get ColdSpring to inject our required variables into the resource bundle.
  4. Then around line 53 look for the following bit of code
    view plain print about
    1<cfset thisRBfile=arguments.rbFile&".properties">
    and change it to
    view plain print about
    1<cfset thisRBfile = expandPath(arguments.rbFile&".properties")>

  5. Next open up your ColdSpring.xml file and add the following:
    view plain print about
    1<bean id="resourcebundle" class="model.resourcebundle">
    2    <constructor-arg name="rbFile"><value>/model/locale_data/en_US</value></constructor-arg>
    3    <constructor-arg name="rbLocale"><value>en_US</value></constructor-arg>
    4</bean>
    What we are doing here is initiated the resourcebundle.cfc and passing two arguments to the init method. These arguments consist of the:
    rbFile: This must be the path + filename UP to but NOT including the locale. We auto-add .properties to the end. This location is the file we created in point 2.
    rbLocale: The locale.
  6. Then we are going to inject this into our controller and to do this add the following code snippet to your ColdSpring.xml File:
    view plain print about
    1<bean id="controller" class="controller.controller">
    2    <property name="resourcebundle">
    3        <ref bean="resourcebundle" />
    4    </property>        
    5</bean>
    and in your Model Glue controller add
    view plain print about
    1<cffunction name="setResourcebundle" returntype="void" access="public" output="false">
    2     <cfargument name="Resourcebundle" required="true" type="any" />
    3     <cfset variables.Resourcebundle = arguments.Resourcebundle />
    4</cffunction>
    5
    6<cffunction name="getResourcebundle" returntype="any" access="public" output="false">
    7     <cfreturn variables.Resourcebundle />
    8</cffunction>
  7. At this point a lot of the hard work is done. Point 1-3 were just about setting up our environment and 4-6 were about some modification to get everything to play together nicely.
  8. We'll carry on with the controller. Because we have injected the resourcebundle.cfc in the Controller we can access it via the variable "variables.resourcebundle" and assign it to the viewState with the following code in the onRequestStart function:
    view plain print about
    1<cfset arguments.event.setValue('rb', variables.Resourcebundle) />
    By doing this we have the bundle in the application scope and ready. For our view files we'll just need to accees the viewState variable but before we do that.....
  9. Lets populate the en_US.properties file with the following before we go any further:
    view plain print about
    1name=Name
    2dob=Date Of birth
    3elevator=elevator
    4cigarette=cigarette
    5sidewalk=sidewalk
    If you haven't used blogCFC or the resoucebundle then you probably should know that the for each language/region you need to create a new .properties file with the relevant prefix(from the CFMX's locales) and values. So for France the prefix would be fr_FR and UK(English) file would be called en_GB.properties, and the content would be something like:
    view plain print about
    1name=Name
    2dob=Date Of birth
    3elevator=lift
    4cigarette=fag
    5sidewalk=pavement
  10. All we need to do now is get the variable we set earlier in OnRequestStart at point xxxxxxxxxxx. Anyone familiar with MG should know this already
    view plain print about
    1<cfset rb = viewState.getValue('rb') />
  11. Now that the resourcebundle is referenced to the "rb" variable we use the method "getResource" to access our .properties file and retrieve the translations. So in your view file the final code to display the users name and dob will then look something like
    view plain print about
    1<cfset rb = viewState.getValue('rb') />    
    2<cfoutput>
    3    #rg.getResource('name')#: #users_name#<br/>
    4    #rg.getResource('dob')#: #dateFormat(dob, 'dd-mm-yyyy')#<br/>    
    5</cfoutput>

Thats pretty much covered the basics of setting this up. You'll notice in my last code snippet I use the UK date format style, this won't do if you are creating a multilingual site but there is a utilities package that goes with the resource bundle for this and I hope to cover that in another post.

At the moment I just wait feedback/comment with this approach before I continue.

Comments Comments (4) | Print Print | Send Send | 4378 Views

Ant basics: Copying directories

Thanks to Eclipse making Ant so simple to use I've got it doing a few tasks for me. Well I thought I'd show how simple it is to use. Below is a simple Ant build.xml that I use to copy the ModelGlueAppliactionTemplate files over to a new project. In a nutshell it copies a bunch of files and directories from one location into the location the build.xml was ran from.

view plain print about
1<?xml version="1.0" encoding="UTF-8"?>
2<!--
3*
4* Name: is anything you want it to be, for this example its build-mg
5* default: is the first target (method) to run
6* basedir: is the base directory, this can be any local location
7*
8-->

9
10<project name="build-mg" default="deploy" basedir=".">
11
12    
13    <!--
14    *
15    * Description: Describes what the build file does
16    *
17    -->

18    <description>
19 Builds a new ModelGlue project
20 </description>
21
22    
23    <!--
24    *
25    * The property tag is just setting a variable.
26    * name: variable name. You can reference this via ${xxxxx}
27    * value: variable value
28    *
29    -->
    
30 <property name="mgfolder" value="/Path2ModelGlueDirectory/ModelGlue/modelglueapplicationtemplate" />
31
32    
33    <!--
34    *
35    * Target: In effect this is your method
36    * The next set of tags are self explanitory.
37    *    
38    -->

39    <target name="deploy">
40     <copy todir="${basedir}">
41     <fileset dir="${mgfolder}"/>
42     </copy>            
43    </target>
44
45    
46        <!--
47        *
48        * Thats it
49        *
50        -->

51</project>

Comments Comments (3) | Print Print | Send Send | 5903 Views

Coldspring at the UKCFUG

Waiting for the train

Well I'm, writing this on the train home after battling through the ever so friendly people on the london Underground. I'm coming back from the UKCFUG meeting tonight where the topic was Coldspring(CS) and what it does presented my Mark Drew. This is his part 2 speak after the Model Glue(MG) and Reactor(RC) preso the other month.

Though fairly short (about 60/70 minutes) he covered a lot of ground and answered concisely the question of "What the hell does CS do?"

ColdSpring uses Inversion of Control (IOC), dependency injection to wire your CFC's together and is based the Java Spring framework. This still probably hasn't helped you much. To make this simple (maybe to simple) Coldspring runs you init() methods in your components and injects any dependencies. Dependencies can be other other CFC's that are required or even settings. For example a shoppingBasket() is dependant on a taxCalculator(). It doesn't really care about the calculator, but for displaying tax on a product it needs it - its dependant on it. This is where you get Separation of Concern(SOC), component should only needs to know about itself, it doesn't care about its dependencies. So how do you tell shoppingBasket() that it needs taxCalculator(), (as with EVERYTHING nowadays) via a XML config file. Coldspring though can also inject settings as well and you can see this in Model Glue:Unity where's its used to hold(inject) the setting into Reactor and Model Glue.

The Bull in Angel

And this is what Mark broke down over the session. I won't go over the presentation too much as Mark has already hosted his presentation online.

From the last two sessions i've learnt a lot, mainly that Mark Drew can't code when a crowd of people are watching him, but also how MG, RC, and CS all interact, how they all help you separate your code into maintainablem understandable chunks. The other thing i've learnt is to go to your local CFUG when you get a chance. For me its about an hour and 45 minutes+ journey into east London by car/train/tube but its been worth it. I've had the chance to meet some new friends and even managed to get free beer off them - i'll pay ya back next time Alistair. honest ;o)

Also I managed to win my first bit of free swag from a meeting - a cracking Adobe Sim Card Backup keyring. Why its on a keyring i don't know? so far i've never been in a situation where i've need to back my contacts on the move or in an emergency. Either way cheers Nicholas and Adobe.

Plus Mark hinted to look out for CFEclipe 1.3 beta soon, real soon!

Comments Comments (5) | Print Print | Send Send | 2652 Views

Model Glue and Reator at UKCFUG - getAll()

I traveled into London again last night to see the Model Glue and Reactor, a winning combination presentation with Mark Drew as the speaker, compere, organiser and the general setting up guy.

The presentation lasted for 2 hours and covered everything from setting up your development environment, to creating the beginnings of a blog app using both frameworks. Mark started with a slide show presentation detailing the frameworks, explaining their relationships to each other and how they are used in the Model-View-Controller (MVC) pattern.

Model Reactor
View CFMX
Controller Model Glue

After this he went through each of the frameworks separately, starting with MG and breaking down the nodes in the modelglue.xml (config file). This then lead onto Reactor, explaining that it is an Object-relationship modeling (ORM) framework. Basically it helps speeds up development but cutting out the need to create SQL statements, DAO's, and Active Records as it does all this on the fly. Using your reactor.xml file you create the links and relationships between you tables and Reactor does the rest.

After the theory we moved into coding which Mark was doing everything on a Mac Book pro - I gotta mentioned it as I bugged him about running anything and everything on it last night as i'm still thinking about getting one . This also meant that cause of the new intel chips he had to set up an extra mapping in the CF administrator which normally wouldn't actually be needed. Mark then went and setup a MG/Reactor environment straight from the .zip files you can download from the sites. There wasnt actually that much new there but it was nice to see it setup from scratch. The next hour or so was used setting up the MG events and listeners, then onto adding Reactor for the database interaction and I think at this point he really showed the power of Reactor. Using a cfc called formutils.cfc (which you gotta release Mark) he generated a form on the fly using the MySQL tables metadata available through Reactor. So if you deleted a field from you "Comment" table, refreshing the form would remove the field. He then proceed to update/insert blog posts and comments all by just setting up the relationships in the reactor.xml.

My write up I don't think has covered half of it really as Mark went into dumping a lot of the objects that MG and Reactor returned to show and explain what is available. Most of the objects in both frameworks have a getAll() method which Mark seemed to be hunting down and utilising everywhere but it did show and display that there are a lot of functions(methods) in these which are helpful but aren't necessarily in the documentation.

Overall it was a great presentation and well worth the trip up. It was also good to not rush off afterward and get a beer over at The Bull afterwards, shame though I had to go to get back to Waterloo before I could hit the vodka.

 

 

Comments Comments (1) | Print Print | Send Send | 4433 Views

Model-Glue 1.1 now available

Joe has released the next update to the 1.x version of Model Glue.

Included amongst the bug fixes are

  • official support for ColdSpring
  • Unnamed (Implicit) results now obey the redirect attribute
  • Debugging trace is maintained across redirects
  • ....etc

"This is the end of Model-Glue 1.x development. All new releases will be based on the 2.0 "Unity" core."

So if you do like Bleeding Edge Realease (BER), you can check out the MG BER at svn://clearsoftware.net/clearsoftware.net/ModelGlue.

I think im save is saying Joe is always happy for the testers :o)

UPDATE: By the way the current BER is the 1.1 release. If you want to participate in 2.0 Unity then leave a comment at Joes 2.0 Alpha post

Comments Comments (2) | Print Print | Send Send | 1735 Views

MG Bean demo app update

Thanks to Dan Sorensen going through my small multi page demo app I have found a bug. Come the second page of the form there was no check to see if the bean had been created. There is now a check in place so if the bean has not been created it takes you back to the first page of the form.

You can download the app at: http://www.andyjarrett.co.uk/downloads/MG-beans.zip

Comments Comments (0) | Print Print | Send Send | 1811 Views

More Entries

BlogCFC by Raymond Camden + Twitter @AndyJ + ColdFusion jobs + Contact Me + Snippets/Downloads + RSS .