<?xml version="1.0" encoding="utf-8"?>
			
			<rss version="2.0">
			<channel>
			<title>CounterMarch Systems Blog - ColdFusion</title>
			<link>http://www.countermarch.com/blog/index.cfm</link>
			<description>CounterMarch Systems is a software consulting firm specializing in Adobe technologies</description>
			<language>en-us</language>
			<pubDate>Tue, 07 Sep 2010 00:05:55 -0400</pubDate>
			<lastBuildDate>Thu, 29 Jul 2010 16:21:00 -0400</lastBuildDate>
			<generator>BlogCFC</generator>
			<docs>http://blogs.law.harvard.edu/tech/rss</docs>
			<managingEditor>helpdesk@countermarch.com</managingEditor>
			<webMaster>helpdesk@countermarch.com</webMaster>
			
			<item>
				<title>Mach-II is (still) awesome</title>
				<link>http://www.countermarch.com/blog/index.cfm/2010/7/29/MachII-is-still-awesome</link>
				<description>
				
				&lt;p&gt;Mach-II rocks. It is one of the more &quot;mature&quot; surviving ColdFusion application frameworks, and as such doesn&apos;t get nearly the amount of buzz that the new (interesting, different, creative, awesome-in-their-own-way) frameworks get. If you&apos;re looking at frameworks, I encourage you to take a look at the amazingly capable &lt;a href=&quot;http://www.mach-ii.com&quot;&gt;Mach-II&lt;/a&gt; - we&apos;ve had fantastic success with it!&lt;/p&gt;

&lt;p&gt;Things I really, really like about Mach-II:&lt;/p&gt;

&lt;h3&gt;Backwards compatibility&lt;/h3&gt;
&lt;p&gt;Take an old (Mach-II 1.1 app, circa 2006) and update the framework to 1.8 (released 2009). Replace the application.cfm file with application.cfc, comment out everything in index.cfm and *boom*...you&apos;re done. I can&apos;t really assess how challenging it is for the team to maintain backwards compatibility, but I sure do appreciate how simple it is to upgrade. Instant feature add with zero headaches.&lt;/p&gt;

&lt;h3&gt;Coldspring integration&lt;/h3&gt;
&lt;code&gt;&lt;include file=&quot;./mach-ii_coldspringProperty.xml&quot; /&gt;&lt;/code&gt; 

&lt;p&gt;and in your listeners:&lt;/p&gt;

&lt;code&gt;&lt;cfcomponent name=&quot;mpListener&quot; extends=&quot;MachII.framework.Listener&quot; 

depends=&quot;howConfigManager,mpManager,reportManager,notificationManager&quot;&gt;&lt;/code&gt;

&lt;p&gt;I don&apos;t think it gets much easier than that. Instant Coldspring integration for dependency injection (and more), radically simplifying the configuration of all of my listener and model cfcs.  Now we&apos;ve got all the power of Coldspring cleanly available to our Mach-II application.&lt;/p&gt;

&lt;h3&gt;Faster Fixes&lt;/h3&gt;
&lt;p&gt;Knowing where to find things is one of the hallmarks of any good framework.  Some do it by convention, some by configuration. Mach-II falls into the latter camp but that&apos;s perfectly fine by me.  Getting back into the mental model of an application months (or years) after deployment is a challenge but by simply cracking open mach-ii.xml I can see what happens where within seconds and bend it to my will.  I love this.&lt;/p&gt;

&lt;h3&gt;Modularity&lt;/h3&gt;
&lt;p&gt;This wasn&apos;t in the framework back in the 1.0 and 1.1 days (when we created some mammoth apps), but by 1.5 (which came out in 2008) the ability to break up large Mach-II applications into separate modules was baked in and oh-so-handy. It&apos;s two years later and we&apos;ve been able to make the easy changes to break those older apps into a collection of modularized sub-apps for much easier maintenance.  Perfect example is an extranet: lots of only slightly related apps put under one common umbrella sharing security or UI components. This is easy to implement and support in a well-designed Mach-II application. All of our more recent apps make use of this feature.&lt;/p&gt;

&lt;h3&gt;The Team&lt;/h3&gt;
&lt;p&gt;The people who created and have since improved and evolved Mach-II are some of the smartest folks who are or have been involved in the ColdFusion community.  &lt;a href=&quot;http://www.mach-ii.com/index.cfm/go/contributors/&quot;&gt;Look at this list&lt;/a&gt;.  Not only have they created something awesome, but they&apos;re incredibly responsive on the &lt;a 
href=&quot;http://trac.mach-ii.com/machii/wiki&quot;&gt;wiki&lt;/a&gt;, &lt;a href=&quot;http://groups.google.com/group/mach-ii-
developers&quot;&gt;development Google group&lt;/a&gt;, and &lt;a href=&quot;http://groups.google.com/group/mach-ii-for-
coldfusion&quot;&gt;framework users Google group&lt;/a&gt;.  They use this framework at their day jobs so you know that each release has been painstakingly designed, implemented, tested, re-tested, piloted and then released.  Plus, they&apos;re open to new ideas (even if you personally have no idea how to make them happen!).  Code is great, but the people are the best.&lt;/p&gt;

&lt;h3&gt;The View Loader&lt;/h3&gt;
&lt;p&gt;This is where some of those &quot;convention-based&quot; concepts have crept in to Mach-II much to the benefit of the users.  Back in the &quot;bad old days&quot; your mach-ii.xml file would contain a block that looked sorta like this, except far longer:&lt;/p&gt;

&lt;code&gt;
	&lt;page-views&gt;
		&lt;page-view name=&quot;showWelcome&quot; 		page=&quot;views/showWelcome.cfm&quot; /&gt;
		&lt;page-view name=&quot;showHome&quot; 		page=&quot;views/home.cfm&quot; /&gt;
		&lt;page-view name=&quot;baseTemplate&quot; 		page=&quot;views/baseTemplate2010.cfm&quot; /&gt;
		&lt;page-view name=&quot;blankTemplate&quot; 	page=&quot;views/blankTemplate.cfm&quot; /&gt;
		&lt;page-view name=&quot;welcomeLanding&quot; 	page=&quot;views/welcome_landing.cfm&quot; /&gt;
		&lt;page-view name=&quot;showSendPassword&quot; 	page=&quot;views/showSendPassword.cfm&quot; /&gt;
		&lt;page-view name=&quot;showAppHelp&quot; 		page=&quot;views/showAppHelp.cfm&quot; /&gt;
	(and so on)
&lt;/code&gt;

&lt;p&gt;Each page would have a page-view defined. Someone called shenanigans on it and now we have the PatternViewLoader to replace ALL of it!&lt;/p&gt;

&lt;code&gt;
&lt;page-views&gt;
	&lt;!-- This would load all views with the pattern of &quot;/views/**/*.cfm&quot; which is the most basic and common pattern --&gt;
    &lt;view-loader type=&quot;MachII.framework.viewLoaders.PatternViewLoader&quot; /&gt;
&lt;/page-views&gt;
&lt;/code&gt;

&lt;p&gt;So, so simple. Love this line of the config file more than any other.&lt;/p&gt;

&lt;h3&gt;Better apps, faster.&lt;/h3&gt;
&lt;p&gt;Take Mach-II off the shelf and use it as your &quot;glue.&quot;  Add Coldspring to manage your model.  Use ColdFusion 9&apos;s new Hibernate ORM capabilities to cut the lines of code in your model by a huge factor. Redirect some of the saved time into building a better UI using jQuery, improving your cross-browser capabilities with clean CSS and making your client happier by communicating more frequently.  Result: a better app, designed to be maintainable and much more in line with your client&apos;s spoken and unspoken expectations. How could any craftsman not feel good about that? Mach-II is a key component to that successful formula for us.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.mach-ii.com/&quot;&gt;Try Mach-II&lt;/a&gt;. Need help? &lt;a href=&quot;http://groups.google.com/group/mach-ii-for-coldfusion&quot;&gt;Talk to the team on the list&lt;/a&gt;.  Build great things.&lt;/p&gt; 
				</description>
				
				<category>mach-ii</category>				
				
				<category>ColdFusion</category>				
				
				<pubDate>Thu, 29 Jul 2010 16:21:00 -0400</pubDate>
				<guid>http://www.countermarch.com/blog/index.cfm/2010/7/29/MachII-is-still-awesome</guid>
				
			</item>
			
			<item>
				<title>Mobile Apps for Alumni Relations - Cornell Compass</title>
				<link>http://www.countermarch.com/blog/index.cfm/2010/6/22/cornell-compass</link>
				<description>
				
				&lt;p&gt;We recently had the privilege of working with &lt;a href=&quot;http://twitter.com/agossen&quot;&gt;Andrew Gossen&lt;/a&gt; in Cornell&apos;s office of &lt;a href=&quot;http://alumni.cornell.edu/&quot;&gt;Alumni Affairs&lt;/a&gt; on a sweet little mobile project.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://www.countermarch.com/blog/images/0041.png&quot; align=&quot;right&quot;/&gt;The &lt;a href=&quot;http://www.cornellcompass.com&quot; target=&quot;new&quot;&gt;Cornell Compass&lt;/a&gt; web application uses geolocation features exposed through mobile browsers to determine the distance and bearing from where you&apos;re standing to the center of Cornell&apos;s campus. It&apos;s fun! It would be way more fun if the orientation of the device was exposed as well (then we could make the compass dynamically spin in real time).&lt;/p&gt;

&lt;p&gt;Once your location is determined you have the opportunity to &quot;Check In&quot; and drop a marker on a map with your name and class year (both optional).  The map is visible both on the mobile device and via the &lt;a href=&quot;http://www.cornellcompass.com/map.cfm&quot;&gt;website&lt;/a&gt; (we do some browser sniffing so the content is device-appropriate). All visitors are encouraged to share the link to the site via Facebook and Twitter.&lt;/p&gt; 

&lt;p&gt;The Compass app is optimized for iPhone, but is functional on both Blackberry and Android devices as well. The backend (which is trivially simple) is ColdFusion with Microsoft SQL Server.  The bulk of the front end work was done using jQuery and a few assistive javascript libraries for doing the bearing calculations.&lt;/p&gt;

&lt;p&gt;We&apos;re working with Cornell to design the next version of this application with more features that make it useful to Cornellians all over the world looking to deepen their relationships with each other. Interested in learning more? Please &lt;a href=&quot;mailto:helpdesk@countermarch.com&quot;&gt;drop me an email&lt;/a&gt;!  We&apos;re interested in working with other organizations to enhance the usefulness of the app including integration with alumni online communities and CRM systems.&lt;/p&gt; 
				</description>
				
				<category>ColdFusion</category>				
				
				<category>alumni relations</category>				
				
				<category>mobile</category>				
				
				<pubDate>Tue, 22 Jun 2010 10:10:00 -0400</pubDate>
				<guid>http://www.countermarch.com/blog/index.cfm/2010/6/22/cornell-compass</guid>
				
			</item>
			
			<item>
				<title>ColdFusion 9 Security Lockdown Guide</title>
				<link>http://www.countermarch.com/blog/index.cfm/2010/5/26/ColdFusion-9-Security-Lockdown-Guide</link>
				<description>
				
				&lt;p&gt;&lt;a href=&quot;http://bit.ly/cf9secure&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;http://www.countermarch.com/blog/images//cf9_security_cover1.JPG&quot; align=&quot;right&quot; /&gt;&lt;/a&gt; Adobe published the work of &lt;a href=&quot;http://www.petefreitag.com/&quot;&gt;Pete Freitag&lt;/a&gt; today - a 35 page guide to &lt;a href=&quot;http://bit.ly/cf9secure&quot; target=&quot;_blank&quot;&gt;secure installation and configuration of ColdFusion&lt;/a&gt;. Even if you feel like your ColdFusion server(s) are tightened up, it&apos;s always a good idea to take a moment to do a review. 
&lt;/p&gt;
&lt;p&gt;While the guide does not go into detail on building secure applications, Pete&apos;s PDF is a step-by-step tutorial that even someone not familiar with ColdFusion administration could follow.  Grab the PDF and spend the 15 minutes to check up on all of your servers (including your local development environment) - it&apos;s well worth it.&lt;/p&gt;

&lt;p&gt;When you&apos;re done with that, check out the Security section of the &lt;a href=&quot;http://www.adobe.com/devnet/coldfusion/security.html&quot;&gt;ColdFusion Developer Center&lt;/a&gt; on the Adobe Developer Connection for lots of articles on how to write safe and solid code too!&lt;/p&gt; 
				</description>
				
				<category>ColdFusion</category>				
				
				<pubDate>Wed, 26 May 2010 17:06:00 -0400</pubDate>
				<guid>http://www.countermarch.com/blog/index.cfm/2010/5/26/ColdFusion-9-Security-Lockdown-Guide</guid>
				
			</item>
			
			<item>
				<title>CFSpreadsheet presentation and samples</title>
				<link>http://www.countermarch.com/blog/index.cfm/2010/1/15/CFSpreadsheet-presentation-and-samples</link>
				<description>
				
				&lt;p&gt;I&apos;d like to thank &lt;a href=&quot;http://fusiongrokker.com/&quot;&gt;Adam Tuttle&lt;/a&gt; and the &lt;a href=&quot;http://www.phillycfug.org&quot;&gt;Philadelphia CFUG&lt;/a&gt; for inviting me to speak last night on CFSpreadsheet.  While the thought of listening to someone talk about spreadsheet generation from an hour would only make a true techie&apos;s heart race, I think those who were there got a good overview of what this new functionality can do for them. If anything I hope that I lowered the bar for many in attendance while simultaneously increasing pressure on their bosses to &lt;a href=&quot;https://store1.adobe.com/cfusion/store/html/index.cfm?event=displayProduct&amp;categoryOID=3254038&amp;store=OLS-US&quot;&gt;buy those licenses&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;My preso focused on the basics (here&apos;s the tag, here are the functions) up front and followed up with 6 examples of how these new functions can be used to manage spreadsheet creation and editing no matter how mangled or ugly. If you want the &lt;a href=&quot;http://www.countermarch.com/cfspreadsheet&quot;&gt;CFSpreadsheet presentation assets and (commented) sample code&lt;/a&gt;, feel free to pull this ZIP.  &lt;strong&gt;I will be updating it this weekend&lt;/strong&gt; with Derby databases so you can just unzip and run everything. For now, unpack the zip into a folder in your webroot. You may need to comment out the ORM settings in Application.cfc to make it run. Ping me with any questions either here or via twitter (@scrittler).&lt;/p&gt;


&lt;p&gt;I also had the opportunity to touch (very lightly) on the new ORM features of ColdFusion 9 during the presentation.  One of my demos (not in the zip file) is the start of an app that is intended to replace a spreadsheet with a web app.  After 90 minutes of work I had the spreadsheet imported to a db using Hibernate, a quick add/edit form put together and a re-export (since the end users still cling to Excel) of the current db.  If I had to write all that SQL it could have easily taken far longer. Finishing the app should be trivial from here, so props to Adobe for putting all the right pieces in the box for me to play with!&lt;/p&gt;

&lt;p&gt;It&apos;s pretty clear that the whole concept of using an ORM engine is very, very new to most of the ColdFusion world and is definitely holding back adoption.  You don&apos;t need to know terribly much to use Hibernate with ColdFusion but letting go of having to write SQL is certainly showing to be more difficult than expected.  It&apos;s a different way of thinking, one that the user group community can definitely help to encourage. The time savings and maintainability improvements alone are well worth starting the trip. I know the Philly CFUG calendar is pretty well packed, but I hope we can put together some talks on this topic (preferably hands on) soon.&lt;/p&gt;

&lt;p&gt;Again, thank you to the CFUG for inviting me to speak. I look forward to seeing everyone at the next meeting on Feb. 25!&lt;/p&gt; 
				</description>
				
				<category>ColdFusion</category>				
				
				<pubDate>Fri, 15 Jan 2010 14:20:00 -0400</pubDate>
				<guid>http://www.countermarch.com/blog/index.cfm/2010/1/15/CFSpreadsheet-presentation-and-samples</guid>
				
			</item>
			
			<item>
				<title>CFSpreadsheet and Conditional Formatting</title>
				<link>http://www.countermarch.com/blog/index.cfm/2010/1/11/CFSpreadsheet-and-Conditional-Formatting</link>
				<description>
				
				&lt;p&gt;CFSpreadsheet pretty much rocks the house when it comes to simplifying the task of creating spreadsheets (Excel and Open Office compatible) from ColdFusion.  On Thursday January 14 I&apos;ll be giving a talk at the &lt;a href=&quot;http://www.phillycfug.org/post/january-meeting-you-got-your-db-in-my-spreadsheet-you-got-your-spreadsheet-in-my-db&quot;&gt;Philadelphia CFUG meeting&lt;/a&gt; on this topic, but something I was working on last night has me particularly excited and requires a blog post.&lt;/p&gt;

&lt;p&gt;Several of the spreadsheets we currently generate for clients have some degree of pretty formatting associated with them.  The way we&apos;ve typically done it is to export a decorated &quot;source&quot; Excel file in Excel&apos;s XML spreadsheet format, chop it up and jack the appropriate data into the document, setting style attributes on the cell tags appropriately based on server-side logic.  But what if you wanted to create the spreadsheet such that the conditional logic was built in to the spreadsheet itself?  The people that use these spreadsheets like to play with the data and it would be awesome if the conditional formatting (highlight in some color, change font size, whatever you like) would apply to their edited data.&lt;/p&gt;

&lt;p&gt;It didn&apos;t seem immediately possible using CFSpreadsheet or any of the 37(!) functions exposed in ColdFusion...but then I remembered that this functionality is built on top of &lt;a href=&quot;http://poi.apache.org/&quot;&gt;Apache POI&lt;/a&gt;, so there had to be a way to get down and dirty with the Java internals. It&apos;s not hard to get there, but whoa the code to implement conditional formatting is definitely verbose.&lt;/p&gt;

&lt;p&gt;What I want to do is set up a conditional formatting rule on the 6th column (F) such that if the value is greater than 10 the background is set to yellow.&lt;/p&gt;

&lt;code&gt;
&lt;cfset objSS = spreadsheetNew(&quot;faculty&quot;) /&gt;
	
&lt;!--- get a handle on the underlying POI object ---&gt;
&lt;cfset objWorkbook = objSS.getWorkbook() /&gt;

&lt;cfset objSheet = objWorkbook.getSheetAt(objWorkbook.getActiveSheetIndex()) /&gt;
	
&lt;!--- get a handle on the conditional formatting property of the sheet ---&gt;
&lt;cfset objCF = objSheet.getSheetConditionalFormatting() /&gt;
	
&lt;!--- now add the format rule that we want on the doc ---&gt;
&lt;!--- formatting rule: 
&lt;cfset HSSFConditionalFormattingRule = objCF.createConditionalFormattingRule(
    																		5, &lt;!--- org.apache.poi.hssf.record.CFRuleRecord.ComparisonOperator.GT ---&gt;
    																		&quot;10&quot;, &lt;!--- the value i want the cell to be greater than for the format to kick in ---&gt;
     																		javacast(&quot;null&quot;, &quot;&quot;)     &lt;!--- 2nd formula is not used for GT/GE ---&gt;
 																		) /&gt;

 
&lt;!--- Create yellow background format definition ---&gt;
&lt;cfset HSSFPatternFormatting = HSSFConditionalFormattingRule.createPatternFormatting() /&gt;

&lt;cfset HSSFPatternFormatting.setFillBackgroundColor(createObject(&apos;java&apos;, &apos;org.apache.poi.hssf.util.HSSFColor$LIGHT_YELLOW&apos;).getIndex()) /&gt;
 
&lt;!--- Define a region that only impacts the &quot;tenure&quot; column (which we know to be the 5th (zero based)) ---&gt;
&lt;cfset regions = arrayNew(1) /&gt;
&lt;cfset regions[1] = createObject(&apos;java&apos;, &apos;org.apache.poi.ss.util.CellRangeAddress&apos;).init(1,1000,5,5) /&gt;
&lt;!--- CellRangeAddress(firstrow, lastrow, firstcol, lastcol) ---&gt;
	     
&lt;!--- Apply Conditional Formatting rule defined above to the regions  ---&gt;
&lt;cfset objCF.addConditionalFormatting(regions, HSSFConditionalFormattingRule) /&gt;
&lt;/code&gt;
&lt;p&gt;Then it&apos;s just a matter of inserting the spreadsheet contents as usual.&lt;/p&gt;
&lt;code&gt;
&lt;!--- generate the new worksheet ---&gt;
&lt;cfquery name=&quot;qFaculty&quot; datasource=&quot;#application.datasource#&quot;&gt;
	select 
			facultyID, pidm, loginID, firstName, lastName, startYear, department, title
	from 
	 		coe_faculty
	order by
			lastName
&lt;/cfquery&gt;


&lt;!--- headers are considered friendly ---&gt;
&lt;cfset spreadsheetAddRow(objSS, &quot;ID,PIDM,Login,First Name,Last Name, tenure, startYear, title, department&quot;) /&gt;

&lt;!--- i hate columns that show up as #### or truncated ---&gt;
&lt;cfset spreadsheetSetColumnWidth(objSS, 2, 13) /&gt;
&lt;cfset spreadsheetSetColumnWidth(objSS, 3, 8) /&gt;
&lt;cfset spreadsheetSetColumnWidth(objSS, 8, 20) /&gt;
&lt;cfset spreadsheetSetColumnWidth(objSS, 9, 25) /&gt;

&lt;!--- loop over the data - calc the tenure and style accordingly ---&gt;
&lt;cfloop query=&quot;qFaculty&quot; startrow=&quot;2&quot;&gt;

	&lt;cfset excelFormula = &quot;(year(today())-G&quot; &amp; qFaculty.currentRow &amp; &quot;)&quot; /&gt;

	&lt;cfset spreadsheetSetCellValue(objSS, qFaculty.facultyID , qFaculty.currentRow, 1) /&gt;
	&lt;cfset spreadsheetSetCellValue(objSS, qFaculty.pidm, qFaculty.currentRow, 2) /&gt;
	&lt;cfset spreadsheetSetCellValue(objSS, qFaculty.loginID, qFaculty.currentRow, 3) /&gt;
	&lt;cfset spreadsheetSetCellValue(objSS, qFaculty.firstName, qFaculty.currentRow, 4) /&gt;
	&lt;cfset spreadsheetSetCellValue(objSS, qFaculty.lastName, qFaculty.currentRow, 5) /&gt;
	&lt;cfset spreadsheetSetCellFormula(objSS, excelFormula, qFaculty.currentRow, 6) /&gt;
	&lt;cfset spreadsheetSetCellValue(objSS, qFaculty.startYear, qFaculty.currentRow, 7) /&gt;
	&lt;cfset spreadsheetSetCellValue(objSS, qFaculty.title, qFaculty.currentRow, 8) /&gt;
	&lt;cfset spreadsheetSetCellValue(objSS, qFaculty.department, qFaculty.currentRow, 9) /&gt;

&lt;/cfloop&gt;

&lt;!--- append the worksheet to a new spreadsheet file ---&gt;
&lt;cfspreadsheet action=&quot;write&quot; filename=&quot;#request.rootDirectory#\sheets\faculty_style_cf.xls&quot; name=&quot;objSS&quot; sheet=&quot;1&quot; overwrite=&quot;true&quot; /&gt;
&lt;/code&gt;
&lt;p&gt;The end result:&lt;/p&gt;
&lt;img src=&quot;http://www.countermarch.com/blog/images//coe_faculty_ss_example.png&quot; /&gt;&lt;br /&gt;
&lt;p&gt;Checking the conditional formatting panel in Excel we see that it&apos;s legit and not hard coded.&lt;/p&gt;
&lt;img src=&quot;http://www.countermarch.com/blog/images//coe_faculty_ss_example2.png&quot; /&gt;

&lt;p&gt;I&apos;ll post more as I dig in and build more complex examples.  This is a simple expression, but it should be enough to get you started if you need to do this kind of thing with ColdFusion and a generated spreadsheet!&lt;/p&gt; 
				</description>
				
				<category>ColdFusion</category>				
				
				<pubDate>Mon, 11 Jan 2010 10:28:00 -0400</pubDate>
				<guid>http://www.countermarch.com/blog/index.cfm/2010/1/11/CFSpreadsheet-and-Conditional-Formatting</guid>
				
			</item>
			
			<item>
				<title>Presenting at the Philadelphia CFUG</title>
				<link>http://www.countermarch.com/blog/index.cfm/2009/12/15/Presenting-at-the-Philadelphia-CFUG</link>
				<description>
				
				&lt;p&gt;&lt;a href=&quot;http://www.fusiongrokker.com/&quot;&gt;Adam&lt;/a&gt; posted the January 2010 meeting announcement to the &lt;a href=&quot;http://www.phillycfug.org&quot;&gt;CFUG website&lt;/a&gt; today -- I&apos;ll be doing a presentation on the &quot;powerful simplicity&quot; that is CFSpreadsheet (and associated functions) on the 14th at Penn.&lt;/p&gt;

&lt;p&gt;I&apos;m especially excited about this topic because of the frequency with which I generally have to work with(against) Excel.  Pretty much every project of ours uses Excel as a report output format and we&apos;ve tried everything from building tabular data in HTML and &quot;faking it&quot; to &lt;a href=&quot;http://www.countermarch.com/blog/index.cfm/2007/4/4/Creating-Excel-XML-files-with-ColdFusion&quot;&gt;saving Excel files in XML format&lt;/a&gt; and rebuilding on the server side.  Both of these options had limitations (the first being stylistic, the second being fragility), so now that ColdFusion has a simple way to build them I&apos;m a happy camper.  I didn&apos;t really want to get in to messing with POI.&lt;/p&gt;

&lt;p&gt;Long story short: we will always have to work with spreadsheets because that&apos;s what &quot;business users&quot; understand (read: as flat as possible).  ColdFusion 9 has built-in features that make reading and creating spreadsheets much easier than it&apos;s ever been.  I&apos;m excited about this and think you should come out to the &lt;a href=&quot;http://www.phillycfug.org/post/january-meeting-you-got-your-db-in-my-spreadsheet-you-got-your-spreadsheet-in-my-db&quot;&gt;next meeting on January 14, 2010&lt;/a&gt; to learn more!&lt;/p&gt; 
				</description>
				
				<category>ColdFusion</category>				
				
				<category>cfug</category>				
				
				<pubDate>Tue, 15 Dec 2009 17:20:00 -0400</pubDate>
				<guid>http://www.countermarch.com/blog/index.cfm/2009/12/15/Presenting-at-the-Philadelphia-CFUG</guid>
				
			</item>
			
			<item>
				<title>Benchmarking and Analytics Toolkit for Higher Education powered by Adobe ColdFusion and Flex</title>
				<link>http://www.countermarch.com/blog/index.cfm/2009/8/25/Benchmarking-and-Analytics-Toolkit-for-Higher-Education-powered-by-Adobe-ColdFusion-and-Flex</link>
				<description>
				
				&lt;p&gt;Earlier this year one of our projects went from soft-launch mode to officially &quot;live&quot; mode: The &lt;a href=&quot;http://benchmarking.case.org&quot; title=&quot;CASE Benchmarking Toolkit&quot;&gt;CASE Benchmarking Toolkit&lt;/a&gt;, a system we designed and implemented for &lt;a href=&quot;http://www.case.org/&quot; target=&quot;_blank&quot; title=&quot;CASE&quot;&gt;CASE, the Council for Advancement and Support of Education&lt;/a&gt;. CASE represents over 2000 institutions of higher education worldwide with over 75,000 members.&lt;/p&gt;

&lt;div style=&quot;width:250px; padding:1em; float:right;&quot;&gt;
&lt;fieldset style=&quot;background-color:#eeeeee;&quot;&gt;
	&lt;legend&gt;Technical Specs&lt;/legend&gt;
	&lt;p&gt;
		&lt;strong&gt;Interface&lt;/strong&gt;: Flex 3.3&lt;br /&gt;
		&lt;strong&gt;Backend&lt;/strong&gt;: ColdFusion 8&lt;br /&gt;
		&lt;strong&gt;Database&lt;/strong&gt;: Microsoft SQL Server 2000
	&lt;/p&gt;
	&lt;p&gt;
		Integration with their member management and AMS/CRM system, iMIS.&lt;br /&gt;
		Consumes data provided by IPEDS.&lt;br /&gt;
	&lt;/p&gt;
&lt;/fieldset&gt;
&lt;/div&gt;
&lt;p&gt;The Toolkit enables the CASE research division and interested communities of practice&lt;sup&gt;1&lt;/sup&gt; to build quantitative benchmarking surveys, collect data, generate reports (text and graphical) and design summary dashboards through an easy-to-use interface. We wanted to share a little bit about what it does, why this is great for the alumni relations and advancement profession and why we as Adobe fans are so proud to have built it.&lt;/p&gt;

&lt;h4&gt;History&lt;/h4&gt;
&lt;p&gt;The origins of this project start back in 2005 with our friends at &lt;a href=&quot;http://www.pcuad.org/&quot; title=&quot;PCUAD: Association of Private College and University Alumni Directors&quot; target=&quot;_blank&quot;&gt;PCUAD&lt;/a&gt;.  We implemented a surveying and benchmarking system for them that reduced the amount of time required to collect, output and analyze the data gathered from thirty higher education institutions. The &quot;&lt;a href=&quot;http://www.pcuad.org&quot; title=&quot;PCUAD ARAMP&quot; target=&quot;_blank&quot;&gt;Alumni Relations Assessment and Measurement Program&lt;/a&gt;&quot; (ARAMP) was the first attempt by any community of practice organization to quantitatively measure the performance of an alumni relations operation. It was an overnight success and continues to be used by PCUAD. About a year later we replaced the HTML UI with a Flex-based UI for use by the &lt;a href=&quot;http://www.nearweb.org&quot; title=&quot;NEAR&quot; target=&quot;_blank&quot;&gt;North East Alumni Relations&lt;/a&gt; group (NEAR).&lt;/p&gt;
&lt;p&gt;Word got out pretty fast that PCUAD had not only created a great survey to &apos;measure&apos; Alumni Relations but also the software to back it up. PCUAD was all too happy to help us get connected with the team at CASE to see if we could push this forward as a global benchmarking system. Once the decision was made to move ahead, we set about redesigning everything - the data model, the middleware and especially the user interface to work seamlessly with the CASE CRM system (iMIS - also a ColdFusion-powered product!)- using the experience we gained supporting PCUAD and NEAR to inform our decision making.&lt;/p&gt;
&lt;p&gt;We delivered the system to CASE in February 2008 for beta testing, flipping the &quot;go-live&quot; switch in May.&lt;/p&gt;
&lt;p&gt;Perhaps more importantly, we delivered the system to them &lt;em&gt;&lt;u&gt;on time and under budget&lt;/u&gt;&lt;/em&gt;. &lt;/p&gt;

&lt;h4&gt;Fast, integrated survey creation&lt;/h4&gt;
&lt;p&gt;Administrators can whip up a survey in next to no time. The CBT supports a wide variety of question types including question matrices. The system strongly encourages question reuse and enables the cloning of questions, sections and even entire surveys. It is through this capability that year-over-year data can be compared and analyzed. Since the user directory is fully integrated with iMIS, assigning permissions can be done anywhere within CASE which makes provisioning and access control a piece of cake.&lt;/p&gt;

&lt;h4&gt;Pain-free survey taking&lt;/h4&gt;
&lt;p&gt;For starters, this product is not Survey Monkey.  Responses to surveys are intended to reflect institutional (not individual) performance; for any given survey many people from an institution can work on it but there is only one submission per school.  This allows us to aggregate and filter the reports by specific institutional characteristics. Assistive text is available for each question in a survey, which when it comes to financial reporting is absolutely crucial. There are many ways to tabulate donations, donors, volunteers and many other aspects of a modern-day advancement organization.&lt;/p&gt;

&lt;h4&gt;Reporting and Exporting&lt;/h4&gt;
&lt;p&gt;Reporting is also a breeze. We know that advancement professionals use a lot of Word and Powerpoint documents in their line of work so we made it really simple to get exactly what they want from the available survey data. Not only can you select which of the available criteria to filter on, but you can view charts and graphs, calculate aggregate values and export it all to Excel (report data) and jpg (charts). We found that using ColdFusion to generate the appropriate data and Flex to render it was a very efficient, powerful combination. &lt;/p&gt;
&lt;p&gt;Filtering report data was done through a very straightforward interface based on research and design we did for our RecruitWeb product. Criteria are displayed down the left side of the screen for selection; each item carries with it additional parameters that are user-defined. Use of colors to indicate active filters and the translation of selections to &amp;quot;plain English&amp;quot; gives the user a very good idea of what they can expect to see in the requested report.&lt;/p&gt;
&lt;p&gt;Aggregate values are calculated for multi institution reports and privacy is protected for specific types of surveys under certain circumstances. We learned just how protective advancement professionals are of their financial data yet found a way to present actionable and useful information without compromising privacy. &lt;/p&gt;

&lt;h4&gt;Screenshots&lt;/h4&gt;
&lt;a href=&quot;http://www.countermarch.com/blog/images/cbt/1_login.png&quot; 					class=&quot;lightbox&quot; title=&quot;The CBT login screen&quot;&gt;&lt;img src=&quot;http://www.countermarch.com/blog/images/cbt/scroll/1_login.jpg&quot; width=&quot;150&quot; height=&quot;113&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;
&lt;a href=&quot;http://www.countermarch.com/blog/images/cbt/2_creation1.png&quot; 				class=&quot;lightbox&quot; title=&quot;Admin: Survey list&quot;&gt;&lt;img src=&quot;http://www.countermarch.com/blog/images/cbt/scroll/2_creation1.jpg&quot; width=&quot;150&quot; height=&quot;113&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;
&lt;a href=&quot;http://www.countermarch.com/blog/images/cbt/3_editsurvey1.png&quot; 			class=&quot;lightbox&quot; title=&quot;Admin: Editing a survey&quot;&gt;&lt;img src=&quot;http://www.countermarch.com/blog/images/cbt/scroll/3_editsurvey1.jpg&quot; width=&quot;150&quot; height=&quot;113&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;
&lt;a href=&quot;http://www.countermarch.com/blog/images/cbt/4_editsurvey2.png&quot; 			class=&quot;lightbox&quot; title=&quot;Admin: Editing a survey section&quot;&gt;&lt;img src=&quot;http://www.countermarch.com/blog/images/cbt/scroll/4_editsurvey2.jpg&quot; width=&quot;150&quot; height=&quot;113&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;
&lt;a href=&quot;http://www.countermarch.com/blog/images/cbt/5_editsurvey3.png&quot; 			class=&quot;lightbox&quot; title=&quot;Admin: Editing a survey question. Many question types are supported.&quot;&gt;&lt;img src=&quot;http://www.countermarch.com/blog/images/cbt/scroll/5_editsurvey3.jpg&quot; width=&quot;150&quot; height=&quot;113&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;
&lt;a href=&quot;http://www.countermarch.com/blog/images/cbt/6_reports1.png&quot; 				class=&quot;lightbox&quot; title=&quot;Reporting: Raw data, conditioned on user selections and precompiled dashboards&quot;&gt;&lt;img src=&quot;http://www.countermarch.com/blog/images/cbt/scroll/6_reports1.jpg&quot; width=&quot;150&quot; height=&quot;113&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;
&lt;a href=&quot;http://www.countermarch.com/blog/images/cbt/7_reports.png&quot; 				class=&quot;lightbox&quot; title=&quot;Raw data reports can be generated for multiple institutions or multiple years&quot;&gt;&lt;img src=&quot;http://www.countermarch.com/blog/images/cbt/scroll/7_reports.jpg&quot; width=&quot;150&quot; height=&quot;113&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;
&lt;a href=&quot;http://www.countermarch.com/blog/images/cbt/8_reportcriteria1.png&quot; 		class=&quot;lightbox&quot; title=&quot;Report filter criteria&quot;&gt;&lt;img src=&quot;http://www.countermarch.com/blog/images/cbt/scroll/8_reportcriteria1.jpg&quot; width=&quot;150&quot; height=&quot;113&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;
&lt;a href=&quot;http://www.countermarch.com/blog/images/cbt/9_reportcritera2.png&quot; 		class=&quot;lightbox&quot; title=&quot;Selecting allowable values for a specific data point&quot;&gt;&lt;img src=&quot;http://www.countermarch.com/blog/images/cbt/scroll/9_reportcritera2.jpg&quot; width=&quot;150&quot; height=&quot;113&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;
&lt;a href=&quot;http://www.countermarch.com/blog/images/cbt/10_reportcritera3.png&quot; 		class=&quot;lightbox&quot; title=&quot;Report filter criteria showing active criteria and the plain-english translation of the selections&quot;&gt;&lt;img src=&quot;http://www.countermarch.com/blog/images/cbt/scroll/10_reportcritera3.jpg&quot; width=&quot;150&quot; height=&quot;113&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;
&lt;a href=&quot;http://www.countermarch.com/blog/images/cbt/11_report.png&quot; 				class=&quot;lightbox&quot; title=&quot;Single institution report; icon in right most column generates a chart for this datapoint&quot;&gt;&lt;img src=&quot;http://www.countermarch.com/blog/images/cbt/scroll/11_report.jpg&quot; width=&quot;150&quot; height=&quot;113&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;
&lt;a href=&quot;http://www.countermarch.com/blog/images/cbt/12_reportchart.png&quot; 			class=&quot;lightbox&quot; title=&quot;Single datapoint chart; sorry we don&apos;t have comparative data to share!&quot;&gt;&lt;img src=&quot;http://www.countermarch.com/blog/images/cbt/scroll/12_reportchart.jpg&quot; width=&quot;150&quot; height=&quot;113&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;
&lt;a href=&quot;http://www.countermarch.com/blog/images/cbt/13_reportmulityear.png&quot; 		class=&quot;lightbox&quot; title=&quot;Selecting sister years for a multiyear report&quot;&gt;&lt;img src=&quot;http://www.countermarch.com/blog/images/cbt/scroll/13_reportmulityear.jpg&quot; width=&quot;150&quot; height=&quot;113&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;
&lt;a href=&quot;http://www.countermarch.com/blog/images/cbt/14_reportmulityear.png&quot; 		class=&quot;lightbox&quot; title=&quot;A generated multiyear report&quot;&gt;&lt;img src=&quot;http://www.countermarch.com/blog/images/cbt/scroll/14_reportmulityear.jpg&quot; width=&quot;150&quot; height=&quot;113&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;
&lt;a href=&quot;http://www.countermarch.com/blog/images/cbt/20_surveytaker.png&quot; 			class=&quot;lightbox&quot; title=&quot;Survey taker: first screen showing available surveys&quot;&gt;&lt;img src=&quot;http://www.countermarch.com/blog/images/cbt/scroll/20_surveytaker.jpg&quot; width=&quot;150&quot; height=&quot;113&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;
&lt;a href=&quot;http://www.countermarch.com/blog/images/cbt/21_surveytaker2.png&quot; 			class=&quot;lightbox&quot; title=&quot;Home screen of the survey showing instructional text, links to export (printable!) and all survey sections&quot;&gt;&lt;img src=&quot;http://www.countermarch.com/blog/images/cbt/scroll/21_surveytaker2.jpg&quot; width=&quot;150&quot; height=&quot;113&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;
&lt;a href=&quot;http://www.countermarch.com/blog/images/cbt/22_surveypreview.png&quot; 		class=&quot;lightbox&quot; title=&quot;Downloading a survey preview report&quot;&gt;&lt;img src=&quot;http://www.countermarch.com/blog/images/cbt/scroll/22_surveypreview.jpg&quot; width=&quot;150&quot; height=&quot;113&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;
&lt;a href=&quot;http://www.countermarch.com/blog/images/cbt/23_surveypreviewexport.png&quot; 	class=&quot;lightbox&quot; title=&quot;The survey preview report in Excel&quot;&gt;&lt;img src=&quot;http://www.countermarch.com/blog/images/cbt/scroll/23_surveypreviewexport.jpg&quot; width=&quot;150&quot; height=&quot;113&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;
&lt;a href=&quot;http://www.countermarch.com/blog/images/cbt/24_takingsurvey.png&quot; 			class=&quot;lightbox&quot; title=&quot;Taking a survey - showing inline assistive text&quot;&gt;&lt;img src=&quot;http://www.countermarch.com/blog/images/cbt/scroll/24_takingsurvey.jpg&quot; width=&quot;150&quot; height=&quot;113&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;
&lt;br /&gt;

&lt;h4&gt;What&apos;s ahead&lt;/h4&gt;
&lt;p&gt;Overall, we&apos;re extremely pleased with what we were able to deliver. ColdFusion made the middleware and business logic a snap. Flex allowed us to prepare a rich, responsive user interface. Using Flex also provides the server with some additional scalability. Similar to an ajax-powered application, the less we have to generate and send over the wire the more resources are available to support a larger number of connected clients. &lt;/p&gt;
&lt;p&gt;Thinking ahead, it would be great if we could deliver an AIR application to enable push messaging - new survey notifications, even faster desktop reporting and possibly even survey completion alerts. The more data this system contains the more valuable it becomes to all of the CASE member institutions. The more tools we can provide that encourage people to participate the better!&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;



&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;1. A &amp;quot;community of practice&amp;quot; is an assembly of peer institutions connected by similar characteristics like alumni population, annual fund budget, or undergraduate population - not the traditional groupings like &amp;quot;Ivy League&amp;quot; or &amp;quot;Big 10.&amp;quot; This ensures an &amp;quot;apples to apples&amp;quot; comparison of data for each discipline represented by the toolkit.&lt;/p&gt; 
				</description>
				
				<category>RIAs</category>				
				
				<category>ColdFusion</category>				
				
				<category>Flex</category>				
				
				<pubDate>Tue, 25 Aug 2009 17:27:00 -0400</pubDate>
				<guid>http://www.countermarch.com/blog/index.cfm/2009/8/25/Benchmarking-and-Analytics-Toolkit-for-Higher-Education-powered-by-Adobe-ColdFusion-and-Flex</guid>
				
			</item>
			
			<item>
				<title>ColdFusion 9: ORM, Part 2</title>
				<link>http://www.countermarch.com/blog/index.cfm/2009/8/3/ColdFusion-9-ORM-Part-2</link>
				<description>
				
				&lt;p&gt;In &lt;a href=&quot;http://www.countermarch.com/blog/index.cfm/2009/8/2/ORM_Part_1&quot;&gt;part one&lt;/a&gt; I dipped my toes into the world of ORM in ColdFusion 9.  Today I&apos;m diving in...and I know there&apos;s far more to this than what I&apos;m about to try, so there may be a Part 3 yet to come.  As with part one, I&apos;m writing this as I go...mistakes and all.&lt;/p&gt;

&lt;p&gt;Today&apos;s challenge: get the rest of the spreadsheet imported into a more relational format.&lt;/p&gt;

&lt;p&gt;The source data has a set of columns for payment information, which is great if you only want to keep the most recent payment information.  Likewise, there&apos;s one column called &quot;comments&quot; that looks like it&apos;ll grow to be kinda nasty over time.&lt;/p&gt;

&lt;img src=&quot;http://www.countermarch.com/blog/images//orm_6.png&quot; width=&quot;550&quot;&gt;

&lt;p&gt;Ideally there&apos;s a one-to-many relationship between a person and payments and a person and comments. So how do we do that in an ORM configuration?&lt;/p&gt;

&lt;p&gt;Step one is to create a CFC for a comment, as that is somewhat more simple.&lt;/p&gt;

&lt;code&gt;

&lt;cfcomponent output=&quot;false&quot; persistent=&quot;true&quot;&gt;

	&lt;cfproperty name=&quot;commentID&quot; type=&quot;numeric&quot; fieldtype=&quot;id&quot; generator=&quot;increment&quot; /&gt;
	&lt;cfproperty name=&quot;person&quot; cfc=&quot;chiomega.mms.person&quot; fkcolumn=&quot;personID&quot; fieldtype=&quot;many-to-one&quot; lazy=&quot;true&quot; /&gt;
	&lt;cfproperty name=&quot;note&quot; type=&quot;string&quot; /&gt;
	&lt;cfproperty name=&quot;createDate&quot; type=&quot;date&quot; /&gt;

&lt;/cfcomponent&gt;

&lt;/code&gt;

&lt;p&gt;Once again we&apos;ve defined the CFC as &quot;persistent&quot; so Hibernate knows about it. As before we set the primary key field by defining the fieldtype and generator attributes on it.&lt;/p&gt;

&lt;p&gt;The second property is the fun one.  Usually when we&apos;re building a database, we&apos;d reflexively put &quot;personID&quot; as a foreign key on the table.  Remember, though, that what we&apos;re trying to capture here is the relationship between two objects. A comment &quot;belongs to&quot; a person.&lt;/p&gt;

&lt;p&gt;Deconstructing the attributes:
&lt;ul&gt;
	&lt;li&gt;&lt;strong&gt;cfc&lt;/strong&gt;: the actual cfc object that this property references (person is in the /chiomega/mms folder)&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;fkcolumn&lt;/strong&gt;: I like to use the PK of the referenced object as the FK column name in the database.&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;fieldtype&lt;/strong&gt;: truly magical - there are &quot;many&quot; comments for &quot;one&quot; person.&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;lazy&lt;/strong&gt;: don&apos;t get the data for the person until I ask for it&lt;/li&gt;

&lt;/ul&gt;
&lt;/p&gt;

&lt;p&gt;The options for &lt;a href=&quot;http://help.adobe.com/en_US/ColdFusion/9.0/Developing/WSE01EDE03-6E6B-4669-8C54-358460778450.html&quot;&gt;Lazy Loading&lt;/a&gt; are many...and extremely worth the read.  Any code where I can include an attribute &lt;strong&gt;lazy=&quot;extra&quot;&lt;/strong&gt; is beyond awesome to me!  Quite honestly, though, how many times have you written a very large SQL statement with many join conditions, knowing full well you won&apos;t use most of the data but prefer to use one &quot;getter&quot; statement?  Too many, right? No more. Let Hibernate take care of getting the data for you at the appropriate time.  I could write a blog post purely on the subject of lazy loading and how great this is.&lt;/p&gt;


&lt;p&gt;Back to the topic at hand: now that we&apos;ve got a &quot;comment&quot; object with a relationship to &quot;person&quot; defined, let&apos;s look at the &quot;person&quot; and set the inverse relationship.&lt;/p&gt;

&lt;code&gt;
&lt;cfcomponent displayname=&quot;person&quot; hint=&quot;person object&quot; output=&quot;false&quot; persistent=&quot;true&quot;&gt;

	&lt;cfproperty name=&quot;personID&quot; type=&quot;numeric&quot; fieldtype=&quot;id&quot; generator=&quot;increment&quot; /&gt;
	&lt;cfproperty name=&quot;firstName&quot; type=&quot;string&quot; /&gt;
	&lt;cfproperty name=&quot;lastName&quot; type=&quot;string&quot; /&gt;
	&lt;cfproperty name=&quot;address1&quot; type=&quot;string&quot; /&gt;
	&lt;cfproperty name=&quot;address2&quot; type=&quot;string&quot; /&gt;
	&lt;cfproperty name=&quot;city&quot; type=&quot;string&quot; /&gt;
	&lt;cfproperty name=&quot;state&quot; type=&quot;string&quot; /&gt;
	&lt;cfproperty name=&quot;postalCode&quot; type=&quot;string&quot; /&gt;
	&lt;cfproperty name=&quot;phoneNumber&quot; type=&quot;string&quot; /&gt;
	&lt;cfproperty name=&quot;emailAddress&quot; type=&quot;string&quot; /&gt;
	&lt;cfproperty name=&quot;profession&quot; type=&quot;string&quot; /&gt;
	&lt;cfproperty name=&quot;chapterName&quot; type=&quot;string&quot; /&gt;
	&lt;cfproperty name=&quot;initiationYear&quot; type=&quot;numeric&quot; /&gt;

	&lt;cfproperty name=&quot;comments&quot; singularName=&quot;comment&quot; type=&quot;array&quot; fieldtype=&quot;one-to-many&quot; cfc=&quot;chiomega.mms.comment&quot; fkcolumn=&quot;personID&quot; cascade=&quot;all&quot; /&gt;

&lt;/cfcomponent&gt;
&lt;/code&gt;

&lt;p&gt;That last property says that each person has a property called &quot;comments&quot; that is an array of &quot;comment&quot; entities of type &quot;chiomega.mms.comment&quot;.&lt;/p&gt;

&lt;p&gt;Whoa. Break it down:&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;&lt;strong&gt;singularName&lt;/strong&gt;: in a &quot;one-to-many&quot; scenario, what we&apos;re referencing is plural...but there&apos;s also a need (which I&apos;ll clarify momentarily) to reference the items individually. &lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;type&lt;/strong&gt;: valid types are array and struct. An array makes sense for this example.&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;fieldtype&lt;/strong&gt;: the reverse of what we had on the &quot;comment&quot; entity. Each person can have 0 or more &quot;comment&quot; objects.&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;cfc&lt;/strong&gt;: the type you&apos;re referencing, in this case the cfc we just created&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;fkcolumn&lt;/strong&gt;: the column in the &quot;child&quot; table that will represent this &quot;person&quot;; recall that we set fkColumn in the &quot;comment&quot; entity to &quot;personID&quot;&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;cascade&lt;/strong&gt;: When I save a &quot;person&quot;, save any child comment records that exist (insert or update) on the person. Also goes for delete operations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;singularName is incredibly useful: this is used to define the auto-generated add/remove methods for the related objects. Read more on what&apos;s created for you in the &lt;a href=&quot;http://help.adobe.com/en_US/ColdFusion/9.0/Developing/WSf0ed2a6d7fb07688310730d81223d0356fc-7fff.html&quot;&gt;ColdFusion 9 docs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The &quot;cascade&quot; attribute was a trial-by-error discovery.  There&apos;s a &lt;a href=&quot;http://help.adobe.com/en_US/ColdFusion/9.0/Developing/WS5FFD2854-7F18-43ea-B383-161E007CE0D1.html&quot;&gt;cascade options&lt;/a&gt; section in the docs on your choices here - basically it defines how the relationship behaves on save/update operations.  If you get a &lt;strong&gt;object references an unsaved transient instance - save the transient instance before flushing&lt;/strong&gt; error, this is why -- go back and set a cascade on your parent entity so that child operations work properly.&lt;/p&gt;

&lt;p&gt;That should do it for configuration.  Let&apos;s tie it together and import people and comments from the spreadsheet again.&lt;/p&gt;

&lt;code&gt;
&lt;!--- reload the Hibernate config (great for development, DO NOT use for production!) ---&gt;
&lt;cfset ormReload() /&gt;

&lt;cfspreadsheet action=&quot;read&quot; src=&quot;master.xls&quot; query=&quot;sheet&quot; headerrow=&quot;1&quot; /&gt;

&lt;cfloop query=&quot;sheet&quot; startrow=&quot;2&quot;&gt;

	&lt;cfscript&gt;
		obj = EntityNew(&quot;person&quot;);
		obj.setFirstName(sheet[&quot;FIRST NAME&quot;][sheet.currentRow]);
		obj.setLastName(sheet[&quot;LAST NAME&quot;][sheet.currentRow]);
		obj.setAddress1(sheet[&quot;ADDRESS&quot;][sheet.currentRow]);
		obj.setAddress2(sheet[&quot;APT&quot;][sheet.currentRow]);
		obj.setCity(sheet[&quot;CITY&quot;][sheet.currentRow]);
		obj.setstate(sheet[&quot;STATE&quot;][sheet.currentRow]);
		obj.setPostalCode(sheet[&quot;ZIP&quot;][sheet.currentRow]);
		obj.setPhoneNumber(sheet[&quot;PHONE ##&quot;][sheet.currentRow]);
		obj.setEmailAddress(sheet[&quot;EMAIL&quot;][sheet.currentRow]);
		obj.setProfession(sheet[&quot;PROFESSION&quot;][sheet.currentRow]);
		obj.setChapterName(sheet[&quot;CHAPTER&quot;][sheet.currentRow]);
		obj.setInitiationYear(val(sheet[&quot;INITIATION YEAR&quot;][sheet.currentRow]));

		if(sheet[&quot;COMMENTS&quot;][sheet.currentRow] is not &apos;&apos;)
		{
			commentObj = entityNew(&quot;comment&quot;);
			commentObj.setNote(trim(sheet[&quot;COMMENTS&quot;][sheet.currentRow]));
			commentObj.setCreateDate(now());
			obj.addComment(commentObj);
		}
		
		entitySave(obj);
	&lt;/cfscript&gt;
	
&lt;/cfloop&gt;

&lt;/code&gt;

&lt;p&gt;&quot;obj&quot; is my person.  If we want to import a comment, we&apos;ll create a new entity of type &quot;comment&quot;.  Recall that these entities have getters and setters automagically created for us, so I populate the note and createDate properties of the comment with values from the spreadsheet.&lt;/p&gt;

&lt;p&gt;Once the comment is populated, I &quot;addComment&quot; to the person - the addComment is one of those &lt;a href=&quot;http://help.adobe.com/en_US/ColdFusion/9.0/Developing/WSf0ed2a6d7fb07688310730d81223d0356fc-7fff.html&quot;&gt;automatically generated methods&lt;/a&gt;.  Something I learned since the last post is that calling &lt;strong&gt;ormFlush()&lt;/strong&gt; isn&apos;t necessary - at the end of the request it&apos;s called implicitly.&lt;/p&gt;

&lt;p&gt;That was easy!  Following the same pattern, I added an entity for payments:&lt;/p&gt;

&lt;code&gt;
&lt;cfcomponent persistent=&quot;true&quot;&gt;

	&lt;cfproperty name=&quot;paymentID&quot; type=&quot;numeric&quot; fieldtype=&quot;id&quot; generator=&quot;increment&quot; /&gt;
	&lt;cfproperty name=&quot;person&quot; fieldtype=&quot;many-to-one&quot; fkcolumn=&quot;personID&quot; cfc=&quot;chiomega.mms.person&quot; lazy=&quot;true&quot; /&gt;
	&lt;cfproperty name=&quot;amount&quot; type=&quot;numeric&quot; /&gt;
	&lt;cfproperty name=&quot;paymentType&quot; type=&quot;string&quot; /&gt;
	&lt;cfproperty name=&quot;note&quot; type=&quot;string&quot; /&gt;
	&lt;cfproperty name=&quot;paymentDate&quot; type=&quot;date&quot; /&gt;
	
&lt;/cfcomponent&gt;
&lt;/code&gt;

&lt;p&gt;...and configured my &apos;person&apos; to reference them...&lt;/p&gt;

&lt;code&gt;
&lt;cfcomponent displayname=&quot;person&quot; hint=&quot;person object&quot; output=&quot;false&quot; persistent=&quot;true&quot;&gt;

	&lt;cfproperty name=&quot;personID&quot; type=&quot;numeric&quot; fieldtype=&quot;id&quot; generator=&quot;increment&quot; /&gt;
	&lt;cfproperty name=&quot;firstName&quot; type=&quot;string&quot; /&gt;
	&lt;cfproperty name=&quot;lastName&quot; type=&quot;string&quot; /&gt;
	&lt;cfproperty name=&quot;address1&quot; type=&quot;string&quot; /&gt;
	&lt;cfproperty name=&quot;address2&quot; type=&quot;string&quot; /&gt;
	&lt;cfproperty name=&quot;city&quot; type=&quot;string&quot; /&gt;
	&lt;cfproperty name=&quot;state&quot; type=&quot;string&quot; /&gt;
	&lt;cfproperty name=&quot;postalCode&quot; type=&quot;string&quot; /&gt;
	&lt;cfproperty name=&quot;phoneNumber&quot; type=&quot;string&quot; /&gt;
	&lt;cfproperty name=&quot;emailAddress&quot; type=&quot;string&quot; /&gt;
	&lt;cfproperty name=&quot;profession&quot; type=&quot;string&quot; /&gt;
	&lt;cfproperty name=&quot;chapterName&quot; type=&quot;string&quot; /&gt;
	&lt;cfproperty name=&quot;initiationYear&quot; type=&quot;numeric&quot; /&gt;

	&lt;cfproperty name=&quot;payments&quot; singularName=&quot;payment&quot; type=&quot;array&quot; fieldtype=&quot;one-to-many&quot; cfc=&quot;chiomega.mms.payment&quot; fkcolumn=&quot;personID&quot; cascade=&quot;all&quot; /&gt;
	&lt;cfproperty name=&quot;comments&quot; singularName=&quot;comment&quot; type=&quot;array&quot; fieldtype=&quot;one-to-many&quot; cfc=&quot;chiomega.mms.comment&quot; fkcolumn=&quot;personID&quot; cascade=&quot;all&quot; /&gt;

&lt;/cfcomponent&gt;
&lt;/code&gt;

&lt;p&gt;Then tweaked the importer to add those as well:&lt;/p&gt;

&lt;code&gt;
&lt;cfspreadsheet action=&quot;read&quot; src=&quot;master.xls&quot; query=&quot;sheet&quot; headerrow=&quot;1&quot; /&gt;

&lt;cfloop query=&quot;sheet&quot; startrow=&quot;2&quot;&gt;

	&lt;cfscript&gt;
		obj = EntityNew(&quot;person&quot;);
		obj.setFirstName(sheet[&quot;FIRST NAME&quot;][sheet.currentRow]);
		obj.setLastName(sheet[&quot;LAST NAME&quot;][sheet.currentRow]);
		obj.setAddress1(sheet[&quot;ADDRESS&quot;][sheet.currentRow]);
		obj.setAddress2(sheet[&quot;APT&quot;][sheet.currentRow]);
		obj.setCity(sheet[&quot;CITY&quot;][sheet.currentRow]);
		obj.setstate(sheet[&quot;STATE&quot;][sheet.currentRow]);
		obj.setPostalCode(sheet[&quot;ZIP&quot;][sheet.currentRow]);
		obj.setPhoneNumber(sheet[&quot;PHONE ##&quot;][sheet.currentRow]);
		obj.setEmailAddress(sheet[&quot;EMAIL&quot;][sheet.currentRow]);
		obj.setProfession(sheet[&quot;PROFESSION&quot;][sheet.currentRow]);
		obj.setChapterName(sheet[&quot;CHAPTER&quot;][sheet.currentRow]);
		obj.setInitiationYear(val(sheet[&quot;INITIATION YEAR&quot;][sheet.currentRow]));
		
		if(sheet[&quot;COMMENTS&quot;][sheet.currentRow] is not &apos;&apos;)
		{
			commentObj = entityNew(&quot;comment&quot;);
			commentObj.setNote(trim(sheet[&quot;COMMENTS&quot;][sheet.currentRow]));
			commentObj.setCreateDate(now());
			obj.addComment(commentObj);
		}
		
		if(sheet[&quot;DATE&quot;][sheet.currentRow] is not &apos;&apos;)
		{
			paymentObj = entityNew(&quot;payment&quot;);
			cleanAmount = trim(sheet[&quot;PAYMENT&quot;][sheet.currentRow]);
			cleanAmount = replace(cleanAmount, &quot;$&quot;, &quot;&quot;);
			paymentObj.setAmount(val(cleanAmount));
			paymentObj.setPaymentType(&apos;check&apos;);
			paymentObj.setNote(trim(sheet[&quot;CHK ##&quot;][sheet.currentRow]));
			paymentObj.setPaymentDate(sheet[&quot;DATE&quot;][sheet.currentRow]);
			
			obj.addPayment(paymentObj);
		}
		
		entitySave(obj);
	&lt;/cfscript&gt;
	
&lt;/cfloop&gt;
&lt;/code&gt;

&lt;p&gt;And, best of all, I haven&apos;t written a single line of SQL nor have I gone in and created tables/columns/relationships/constraints in the database, yet I have this ready and waiting for use:&lt;/p&gt;

&lt;img src=&quot;http://www.countermarch.com/blog/images//orm_8.png&quot;&gt;

&lt;p&gt;Up next: building an actual application using what we&apos;ve just created.  I&apos;m pumped...this is working out great so far!&lt;/p&gt; 
				</description>
				
				<category>ColdFusion</category>				
				
				<pubDate>Mon, 03 Aug 2009 11:56:00 -0400</pubDate>
				<guid>http://www.countermarch.com/blog/index.cfm/2009/8/3/ColdFusion-9-ORM-Part-2</guid>
				
			</item>
			
			<item>
				<title>ColdFusion 9: ORM, Part 1</title>
				<link>http://www.countermarch.com/blog/index.cfm/2009/8/2/ORM_Part_1</link>
				<description>
				
				&lt;p&gt;So the challenge tonight is to bang out a quick little member management system using the ColdFusion 9 ORM tools.  Basically, a test of the &quot;look, ma, no code!&quot; approach to software development.&lt;/p&gt;

&lt;p&gt;Step 1: create blank database:&lt;/p&gt;

&lt;img src=&quot;http://www.countermarch.com/blog/images/orm_1.png&quot;&gt;

&lt;p&gt;Ok, so that was boring.  Next step: make a basic CFC using ColdFusion Builder&apos;s CFC generator.  All I specified were properties that I expected to map to columns in the database.  Still haven&apos;t written code - here&apos;s what was generated for me.&lt;/p&gt;

&lt;code&gt;
&lt;cfcomponent displayname=&quot;person&quot; hint=&quot;person object&quot; output=&quot;false&quot;&gt;

	&lt;cfproperty name=&quot;personID&quot; type=&quot;numeric&quot;  /&gt;
	&lt;cfproperty name=&quot;firstName&quot; type=&quot;string&quot; /&gt;
	&lt;cfproperty name=&quot;lastName&quot; type=&quot;string&quot; /&gt;
	&lt;cfproperty name=&quot;address1&quot; type=&quot;string&quot; /&gt;
	&lt;cfproperty name=&quot;address2&quot; type=&quot;string&quot; /&gt;
	&lt;cfproperty name=&quot;city&quot; type=&quot;string&quot; /&gt;
	&lt;cfproperty name=&quot;state&quot; type=&quot;string&quot; /&gt;
	&lt;cfproperty name=&quot;postalCode&quot; type=&quot;string&quot; /&gt;
	&lt;cfproperty name=&quot;phoneNumber&quot; type=&quot;string&quot; /&gt;
	&lt;cfproperty name=&quot;emailAddress&quot; type=&quot;string&quot; /&gt;
	&lt;cfproperty name=&quot;profession&quot; type=&quot;string&quot; /&gt;
	&lt;cfproperty name=&quot;chapterName&quot; type=&quot;string&quot; /&gt;
	&lt;cfproperty name=&quot;initiationYear&quot; type=&quot;numeric&quot; /&gt;

&lt;/cfcomponent&gt;
&lt;/code&gt;

&lt;p&gt;So far, pretty simple. Had to fight the urge to create getters and setters for each property...we&apos;ll let the ORM engine take care of that for us.  I saved this CFC in person.cfc under the application&apos;s home directory in my webroot.&lt;/p&gt;

&lt;p&gt;Next step: setting up Application.cfc.&lt;/p&gt;

&lt;code&gt;
&lt;cfcomponent&gt; 

	&lt;cfset this.name = &quot;ChiOApp&quot;&gt; 

	&lt;cfset this.ormenabled = &quot;true&quot;&gt; 
	&lt;cfset this.datasource = &quot;chiomega&quot;&gt; 
	&lt;cfset this.ormsettings={dbcreate=&quot;update&quot;, logsql=&quot;true&quot;}&gt;

	&lt;cfset this.clientmanagement=&quot;false&quot;&gt; 
	&lt;cfset this.sessionmanagement=&quot;true&quot;&gt; 
	&lt;cfset this.sessiontimeout=&quot;#createtimespan(0,0,10,0)#&quot;&gt; 
	&lt;cfset this.applicationtimeout=&quot;#createtimespan(5,0,0,0)#&quot;&gt;

&lt;/cfcomponent&gt;

&lt;/code&gt;

&lt;p&gt;The only three lines that are different from our &quot;usual&quot; config are &lt;strong&gt;this.ormenabled&lt;/strong&gt;, &lt;strong&gt;this.datasource&lt;/strong&gt; and &lt;strong&gt;this.ormsettings&lt;/strong&gt;.  The first tells ColdFusion to pay attention to our CFCs and automagically configure the ORM mappings for us.  The second is another new feature of ColdFusion 9 - it sets a &quot;default&quot; dsn for all cfquery and cfstoredproc tags so we don&apos;t have to type datasource=&quot;#request.dsn#&quot; anymore. Rock! Also, the ORM engine uses this value as the database to persist CFC data in.  The third tells the ORM engine that I want it to create the necessary database tables and (when the time comes) log all the sql statements fired by the generated code.  You&apos;ll see those log entries fly by if you start up CF from the command line.&lt;/p&gt;

&lt;p&gt;Total code CF code written so far: three lines.  Awesome.&lt;/p&gt;

&lt;p&gt;Consulting the docs, I now need to add a few attributes to the cfcomponent tag to have the table created in the database for me.&lt;/p&gt;

&lt;code&gt;
&lt;cfcomponent displayname=&quot;person&quot; hint=&quot;person object&quot; output=&quot;false&quot; persistent=&quot;true&quot; &gt;
   &lt;cfproperty name=&quot;personID&quot; type=&quot;numeric&quot; fieldtype=&quot;id&quot; generator=&quot;increment&quot; /&gt;
   ...
&lt;/code&gt;

&lt;p&gt;Let&apos;s look at what I added:
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;persistent=&quot;true&quot;&lt;/strong&gt; - think of it to mean &quot;please store the properties of this cfc as columns in a table you create for me&quot;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;fieldtype=&quot;id&quot;&lt;/strong&gt; - this is the primary key field&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;generator=&quot;increment&quot;&lt;/strong&gt; - I want it to auto increment for each new record (I&apos;m using MSSQL05 for this example)&lt;/li&gt;
&lt;/ul&gt;
so far so good, I think.&lt;/p&gt;

&lt;p&gt;So let&apos;s take a peek at what happens when I run a simple script.&lt;/p&gt;

&lt;code&gt;
&lt;cfscript&gt;
	obj = EntityNew(&quot;person&quot;);
&lt;/cfscript&gt;

&lt;cfdump var=&quot;#obj#&quot; /&gt; 
&lt;/code&gt;

&lt;img src=&quot;http://www.countermarch.com/blog/images/orm_3.png&quot;&gt;

&lt;p&gt;Nothing too special - it&apos;s just a cfc.  But this is where the new hotness resides: &lt;/p&gt;

&lt;img src=&quot;http://www.countermarch.com/blog/images//orm_2.png&quot;&gt;

&lt;p&gt;So let&apos;s jack some data into the db using this new hotness.  Please note: the spreadsheet I&apos;m using has the typical &quot;not created by a programmer&quot; column names with spaces, so I&apos;m using array syntax to extract the field data.&lt;/p&gt;

&lt;code&gt;
&lt;cfspreadsheet action=&quot;read&quot; src=&quot;master.xls&quot; query=&quot;sheet&quot; headerrow=&quot;1&quot; /&gt;

&lt;cfloop query=&quot;sheet&quot; startrow=&quot;2&quot;&gt;

	&lt;cfscript&gt;
		obj = EntityNew(&quot;member&quot;);
		obj.setFirstName(sheet[&quot;FIRST NAME&quot;][sheet.currentRow]);
		obj.setLastName(sheet[&quot;LAST NAME&quot;][sheet.currentRow]);
		obj.setAddress1(sheet[&quot;ADDRESS&quot;][sheet.currentRow]);
		obj.setAddress2(sheet[&quot;APT&quot;][sheet.currentRow]);
		obj.setCity(sheet[&quot;CITY&quot;][sheet.currentRow]);
		obj.setstate(sheet[&quot;STATE&quot;][sheet.currentRow]);
		obj.setPostalCode(sheet[&quot;ZIP&quot;][sheet.currentRow]);
		obj.setPhoneNumber(sheet[&quot;PHONE ##&quot;][sheet.currentRow]);
		obj.setEmailAddress(sheet[&quot;EMAIL&quot;][sheet.currentRow]);
		obj.setProfession(sheet[&quot;PROFESSION&quot;][sheet.currentRow]);
		obj.setChapterName(sheet[&quot;CHAPTER&quot;][sheet.currentRow]);
		obj.setInitiationYear(val(sheet[&quot;INITIATION YEAR&quot;][sheet.currentRow]));
		entitySave(obj);
	&lt;/cfscript&gt;
	
&lt;/cfloop&gt;

&lt;cfset ormFlush() /&gt;

&lt;/code&gt;

&lt;p&gt;Those last two lines are the fun part and should be explained. &lt;strong&gt;entitySave&lt;/strong&gt; causes Hibernate to store the object in its own cache for really, really fast retrieval.  To actually get the data written to the database, we call &lt;strong&gt;ormFlush()&lt;/strong&gt;. If the object has been changed, it gets pushed to the database.  In this example, 245 records are created in the cache, then all written out to the database.&lt;/p&gt; 

&lt;p&gt;Our database:&lt;/p&gt;

&lt;img src=&quot;http://www.countermarch.com/blog/images/orm_4.png&quot;&gt;

&lt;p&gt;So now that all of that info is loaded into the database without having written a single line of SQL (c&apos;mon, don&apos;t act like you&apos;re not impressed), let&apos;s slap together a quick browse interface.  Do not use this code as an example of &quot;how to write CF&quot;...it&apos;s a hacktacular approach just to show the basics. Please.&lt;/p&gt;

&lt;code&gt;
&lt;cfparam name=&quot;form.personID&quot; default=&quot;0&quot; /&gt;

&lt;!--- get all the people in the database ---&gt;
&lt;cfset aPeople = EntityLoad(&quot;person&quot;) /&gt;

&lt;!--- set up my postback form, populating the dropdown with people ---&gt;
&lt;form id=&quot;browse&quot; method=&quot;post&quot; action=&quot;&quot;&gt;

	&lt;select id=&quot;personID&quot; name=&quot;personID&quot;&gt;
	&lt;cfloop array=&quot;#aPeople#&quot; index=&quot;person&quot;&gt;
		&lt;cfoutput&gt;
			&lt;option value=&quot;#person.getPersonID()#&quot; &lt;cfif isDefined(&quot;form.personID&quot;) and form.personID is person.getPersonID()&gt;selected&lt;/cfif&gt;&gt;#person.getLastName()#, #person.getFirstName()#&lt;/option&gt;
		&lt;/cfoutput&gt;
	&lt;/cfloop&gt;
	&lt;/select&gt;
	&lt;input type=&quot;submit&quot; value=&quot;Get&quot; /&gt;
&lt;/form&gt;

&lt;!--- if a person was selected, dump out their information ---&gt;
&lt;cfif form.personID is not 0&gt;
        &lt;!--- the second argument is the structure of matching criteria ---&gt;
	&lt;cfset person = entityLoad(&quot;person&quot;, {personID=form.personID}) /&gt;
	
	&lt;cfdump var=&quot;#person#&quot; /&gt;
	
&lt;/cfif&gt;

&lt;/code&gt;

&lt;p&gt;In &quot;old school&quot; code we would have had to write a query to get any of this data out of the db. Instead, we&apos;re asking the ORM engine to do all the heavy lifting. You can see that we&apos;re adding a match between the personID field and the form field of the same name.  You can specify as many matching criteria as you wish, again without writing any &amp;lt;cfif&amp;gt; this or &amp;lt;cfelse&amp;gt; that.&lt;/p&gt;

&lt;p&gt;The result (blurred for privacy reasons):&lt;/p&gt;

&lt;img src=&quot;http://www.countermarch.com/blog/images/orm_5.png&quot;&gt;

&lt;p&gt;In my next post, I&apos;ll create the edit form AND start working on the one-to-many relationship between a person and a &quot;comments&quot; table.  This is where we&apos;ll get the most utility out of ORM, but also where we&apos;ll find the most complexity.&lt;/p&gt;

&lt;p&gt;So far, though, I&apos;m totally impressed.  This really was my first experiment with ColdFusion&apos;s ORM capabilities.  There&apos;s plenty more to learn and I&apos;m sure I&apos;ll refine my technique even more as I dig in to it.&lt;/p&gt; 
				</description>
				
				<category>ColdFusion</category>				
				
				<pubDate>Sun, 02 Aug 2009 00:38:00 -0400</pubDate>
				<guid>http://www.countermarch.com/blog/index.cfm/2009/8/2/ORM_Part_1</guid>
				
			</item>
			
			<item>
				<title>CFSpreadsheet</title>
				<link>http://www.countermarch.com/blog/index.cfm/2009/8/1/CFSpreadsheet</link>
				<description>
				
				&lt;p&gt;It really is this simple in ColdFusion 9:&lt;/p&gt;

&lt;code&gt;
&lt;cfspreadsheet action=&quot;read&quot; src=&quot;master.xls&quot; query=&quot;sheet&quot; headerrow=&quot;1&quot; /&gt;
&lt;/code&gt;

&lt;p&gt;No more cfx_Excel2Query, no more hacks, no more funky parsing...just straight up Excel to a native ColdFusion recordset.&lt;/p&gt;

&lt;p&gt;Up next: creating a simple app using the ColdFusion 9 ORM capability. This is tonight&apos;s programming challenge.&lt;/p&gt; 
				</description>
				
				<category>ColdFusion</category>				
				
				<pubDate>Sat, 01 Aug 2009 22:32:00 -0400</pubDate>
				<guid>http://www.countermarch.com/blog/index.cfm/2009/8/1/CFSpreadsheet</guid>
				
			</item>
			
			<item>
				<title>Adobe Community Expert</title>
				<link>http://www.countermarch.com/blog/index.cfm/2009/2/12/Adobe-Community-Expert</link>
				<description>
				
				&lt;p&gt;&lt;a href=&quot;http://www.adobe.com/communities/experts/&quot;&gt;&lt;img src=&quot;http://www.countermarch.com/blog/images//ace_logo.gif&quot; align=&quot;left&quot; alt=&quot;Adobe Community Expert&quot; border=&quot;0&quot; style=&quot;padding:1em;&quot;/&gt;&lt;/a&gt; I got some great news yesterday from Adobe informing me that I&apos;ve been invited to join the Adobe Community Experts group for 2009!&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;http://www.adobe.com/communities/experts/&quot;&gt;community experts program&lt;/a&gt; (and forgive me if I quote directly from the site here) &quot;is a community based program made up of Adobe customers who share their product expertise with the world-wide Adobe community.&quot;  Kinda like what I used to do with the &lt;a href=&quot;http://www.phillycfug.org&quot;&gt;Philly CFUG&lt;/a&gt;, but on a broader scale.  We&apos;re expected to attend and present at conferences, write frequently (on actual paper and online), and make ourselves available to others in the community who want to learn more.&lt;/p&gt;

&lt;p&gt;I&apos;m happy to be a champion for ColdFusion and Flex (and other Adobe tools) and look forward to making an even more active contribution to the community this year!&lt;/p&gt; 
				</description>
				
				<category>ColdFusion</category>				
				
				<category>shameless self promotion</category>				
				
				<category>Flex</category>				
				
				<pubDate>Thu, 12 Feb 2009 11:31:00 -0400</pubDate>
				<guid>http://www.countermarch.com/blog/index.cfm/2009/2/12/Adobe-Community-Expert</guid>
				
			</item>
			
			<item>
				<title>QueryParam Scanner</title>
				<link>http://www.countermarch.com/blog/index.cfm/2008/7/22/QueryParam-Scanner</link>
				<description>
				
				&lt;p&gt;Time to step back and check your work...&lt;/p&gt;

&lt;p&gt;Every now and then it&apos;s worth taking the time to run a scan tool against your always-growing codebase to make sure you haven&apos;t opened up any avenues for a SQL injection attack.&lt;/p&gt;

&lt;p&gt;You&apos;d think that after so long and so many repeated warnings we&apos;d all be tighter than tight now and that param-ing our queries would be second nature.  This is such an old vulnerability for any webapp and building in fault tolerance from the start should be elementary.  For the most part that&apos;s absolutely the case...but there are always a few queries that manage to get by without wearing proper protection.&lt;/p&gt;

&lt;p&gt;I was a bit surprised at the results after running the &lt;a href=&quot;http://qpscanner.riaforge.org/&quot;&gt;QueryParam Scanner&lt;/a&gt; tool from RIAForge (thank you. &lt;a href=&quot;http://blog.bpsite.net/&quot;&gt;Peter Boughton&lt;/a&gt;!) -- until I realized that the tool isn&apos;t excluding SQL in a query of queries (dbtype=&quot;query&quot;) nor is it omitting any values that are being set from an unadulterated CF function (now() is one example).  Still. though. it did identify a number of queries that needed a little extra attention just to be truly safe from attack. I highly recommend that you &lt;a href=&quot;http://qpscanner.riaforge.org/&quot;&gt;go get it and run it today&lt;/a&gt;.  You can clean up the mess before you leave work today.  This would be an excellent feature to be written as an extension to CFEclipse or (as &lt;a href=&quot;http://www.brooks-bilson.com/blogs/rob/&quot;&gt;Rob Brooks-Bilson&lt;/a&gt; suggested) integrated into standard CF unit testing suites.&lt;/p&gt;

&lt;p&gt;Worth noting is that in many cases (at least for the numeric params) we val the value and set the type on the cfargument tag in all the CFCs all the way down to the DAO level so even without the cfqueryparam tag we&apos;re mostly safe.  It&apos;s those char/varchar fields that require the most attention (complete with trim(). left(). and maxlength checking!) to be considered sufficiently safe.&lt;/p&gt;

&lt;p&gt;All of that aside. cfqueryparam alone is a strong first step to protecting your system from a SQL injection attack.  Using it reduces the likelihood you&apos;ll be wearing egg on your face on Monday morning!&lt;/p&gt; 
				</description>
				
				<category>ColdFusion</category>				
				
				<pubDate>Tue, 22 Jul 2008 17:00:00 -0400</pubDate>
				<guid>http://www.countermarch.com/blog/index.cfm/2008/7/22/QueryParam-Scanner</guid>
				
			</item>
			
			<item>
				<title>Get ready for &quot;boom&quot;</title>
				<link>http://www.countermarch.com/blog/index.cfm/2008/2/1/Get-ready-for-boom</link>
				<description>
				
				&lt;p&gt;The blog has been dark for about a month. but the office has been anything but.&lt;/p&gt;

&lt;p&gt;We&apos;ve been working a lot - way more than we expected - to get our projects done.  We&apos;ve done great at delivery. with upgrades to our faculty evaluation system pushed out the door on time (followed by a trouble-free reporting cycle). a brand-new award nomination system launched last night (basically a build-your-own form generator) and a soon-to-launch software project documentation/lifecycle tracker for one of our favorite clients (you know who you are!).&lt;/p&gt;

&lt;p&gt;We&apos;re now in the final 48 hours of work on a slick Flex-based benchmarking survey suite.  The final 48 hours of a 7 month project that has cost Matt more than enough sleep and both of us a nice slice of youth.  HOWEVER...it&apos;s a beautiful thing and will give our client the ability to support and encourage the growth of their clients in a way that hasn&apos;t been done on this scale before.  I can&apos;t wait to post screenshots and show off what we accomplished.  This application integrates data from two outside databases. compiling and calculating additional data on top of it. and providing a rich reporting UI that includes Excel export and on-screen chart creation.  Flex makes the graphical and user interface elements of the project so much more attractive!  We&apos;re also expecting a heavy load. which we&apos;re feeling more comfortable about supporting through the offloading of a lot of work to the client through the use of Flex and web services.  Can&apos;t wait to get it pushed live!&lt;/p&gt;

&lt;p&gt;Also coming down to the final week is our long-discussed Online Community project.  We&apos;ve been focused on making it a stunning and useful experience and at the same time adapting features to meet last minute shifts in requirements.  This isn&apos;t another Facebook/MySpace/Ning site - this product is for colleges and universities to use. The OC provides a high-content. simple-to-use and CRM-oriented platform for alumni to reconnect with one another and their alma mater.  Lots of time has been spent balancing the integration needs of the institution (always interesting) and ease of use - at this stage I&apos;m convinced that few other online community vendors in this space have considered these issues as thoroughly as we have.&lt;/p&gt;

&lt;p&gt;The OC has been previewed to a few people (and they&apos;ve been impressed). but next Saturday is the &quot;big one&quot; - the feature-complete dog and pony show that will either excite the heck out of them or make us wonder where we went wrong.  Early indications are positive. but we&apos;ve got a ways to go to be ready for it.  I&apos;m going to steal as many ideas from Steve Jobs as I can for the Powerpoint portion of the talk - possibly even the attire!&lt;/p&gt;

&lt;p&gt;So that&apos;s where we&apos;ve been: working on a ton of Flex. kicking out a little bit of inspired ColdFusion and spending lots of time in meetings.  A couple weeks from now we&apos;ll post screenshots (and probably put the community up on Labs for folks to play with).  Our clients are eager to get these projects wrapped up. so back to work I go.  We&apos;re doing great and we&apos;ll be doing even better after go-live!&lt;/p&gt; 
				</description>
				
				<category>ColdFusion</category>				
				
				<category>Flex</category>				
				
				<pubDate>Fri, 01 Feb 2008 18:31:00 -0400</pubDate>
				<guid>http://www.countermarch.com/blog/index.cfm/2008/2/1/Get-ready-for-boom</guid>
				
			</item>
			
			<item>
				<title>Get on the Bus!</title>
				<link>http://www.countermarch.com/blog/index.cfm/2007/12/14/Get-on-the-Bus</link>
				<description>
				
				&lt;p&gt;The Enterprise Service Bus. that is...&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.brooks-bilson.com/blogs/rob/index.cfm/2007/12/14/The-Evolution-of-Integration-Architecture--An-Introduction-to-the-Enterprise-Service-Bus-ESB&quot;&gt;Rob Brooks-Bilson&lt;/a&gt; is doing a mini-series of posts on what an ESB is and how you might work one in to your ColdFusion environment.&lt;/p&gt;

&lt;p&gt;An ESB is a great platform-neutral. SOA-way of integrating disparate systems using common technologies like web services. FTP. email. ftp and more.  Yes. there&apos;s FAR more to it than that...but if I went in to detail. there&apos;d be no reason to &lt;a href=&quot;http://www.brooks-bilson.com/blogs/rob/index.cfm/2007/12/14/The-Evolution-of-Integration-Architecture--An-Introduction-to-the-Enterprise-Service-Bus-ESB&quot;&gt;read Rob&apos;s post&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Can&apos;t wait for the next installment - we&apos;ve got a couple big projects that would benefit greatly by being &quot;on the bus&quot; for data exchange!&lt;/p&gt; 
				</description>
				
				<category>ColdFusion</category>				
				
				<pubDate>Fri, 14 Dec 2007 18:08:00 -0400</pubDate>
				<guid>http://www.countermarch.com/blog/index.cfm/2007/12/14/Get-on-the-Bus</guid>
				
			</item>
			
			<item>
				<title>CFEclipse on Flex Builder 3 Beta 2</title>
				<link>http://www.countermarch.com/blog/index.cfm/2007/10/24/CFEclipse-on-Flex-Builder-3-Beta-2</link>
				<description>
				
				&lt;p&gt;I figured I would try to spend a day with FB3 to see how it&apos;s coming along (so far it seems a little faster).  Of course. we do a lot of ColdFusion development so CFEclipse is pretty much a requirement.&lt;/p&gt;

&lt;p&gt;However. I could not install it due to some missing files in Eclipse.  Thankfully. Joao &lt;a href=&quot;http://www.onflexwithcf.org/index.cfm/2007/10/5/Where-did-the-orgeclipsejdtcore-go-in-Flex-Builder-3-Beta-2-standalone&quot;&gt;posted instructions&lt;/a&gt; on how to correct this and get CFEclipse working on FB3b2.&lt;/p&gt;

&lt;p&gt;Thanks. Joao!&lt;/p&gt; 
				</description>
				
				<category>ColdFusion</category>				
				
				<category>eclipse</category>				
				
				<category>Flex</category>				
				
				<pubDate>Wed, 24 Oct 2007 10:20:00 -0400</pubDate>
				<guid>http://www.countermarch.com/blog/index.cfm/2007/10/24/CFEclipse-on-Flex-Builder-3-Beta-2</guid>
				
			</item>
			</channel></rss>