<?xml version="1.0" encoding="utf-8"?>

			<rss version="2.0" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:cc="http://web.resource.org/cc/" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd">

			<channel>
			<title>Brian Kotek: Inversion of Control - ColdFusion</title>
			<link>http://www.briankotek.com/blog/index.cfm</link>
			<description>Brian Kotek on ExtJS, DeftJS, CoffeeScript, Java, Groovy, Grails, Design Patterns, and Object-Oriented Programming</description>
			<language>en-us</language>
			<pubDate>Sun, 19 May 2013 02:14:09 -0700</pubDate>
			<lastBuildDate>Wed, 14 Sep 2011 09:11:00 -0700</lastBuildDate>
			<generator>BlogCFC</generator>
			<docs>http://blogs.law.harvard.edu/tech/rss</docs>
			<managingEditor>brian428@briankotek.com</managingEditor>
			<webMaster>brian428@briankotek.com</webMaster>
			<itunes:subtitle></itunes:subtitle>
			<itunes:summary></itunes:summary>
			<itunes:category text="Technology" />
			<itunes:category text="Technology">
				<itunes:category text="Podcasting" />
			</itunes:category>
			<itunes:category text="Technology">
				<itunes:category text="Tech News" />
			</itunes:category>
			<itunes:keywords></itunes:keywords>
			<itunes:author></itunes:author>
			<itunes:owner>
				<itunes:email>brian428@briankotek.com</itunes:email>
				<itunes:name></itunes:name>
			</itunes:owner>
			
			<itunes:explicit>no</itunes:explicit>
			
			
			
			
			
			<item>
				<title>BlazeDS and LCDS RPC Call Ordering</title>
				<link>http://www.briankotek.com/blog/index.cfm/2011/9/14/BlazeDS-and-LCDS-RPC-Call-Ordering</link>
				<description>
				
				I&apos;m working on a project that is performing &quot;real-time saving&quot; of data in a Flex UI. In other words, if they do something in the UI, that change is saved to the database automatically, rather than waiting until the user presses a save button.

One concern we had was what happens if multiple requests are sent to the server, and for whatever reason some take longer to complete than others? i.e. you send RequestA then RequestB, and RequestA takes 10 seconds but RequestB takes 1 second. Which would mean the database would end up being wrong, with the data from RequestA being the last version saved. How can we make sure that the final state persisted in the database is actually the current state, and not the last request that happened to complete?

A number of options were thrown on the table, including implementing a client and/or server-side queue, or building logic to verify that the current state in the client matches the persisted state. While mulling this over, one of my colleagues noticed an interesting line in the &lt;a href=&quot;http://help.adobe.com/en_US/LiveCycleDataServicesES/3.1/Developing/WSc3ff6d0ea77859461172e0811f00f7045b-7ff8Update.html&quot; target=&quot;_blank&quot;&gt;LCDS documentation&lt;/a&gt;:

&lt;blockquote&gt;Channels also impose an order to the flow of messages sent to the server and the order of corresponding responses. Order is important to ensure that interactions between the client and server occur in a consistent, predictable fashion.&lt;/blockquote&gt;

It&apos;s rather vague, but we read that to say &quot;even though you think your calls to the channel are asynchronous, they actually aren&apos;t.&quot; Which, even though it is not what I thought was going on at all, would mean that the problem I mentioned earlier actually isn&apos;t a problem at all.

Tom Jordahl was kind enough to respond to an email and discuss this. I then ran a number of tests locally to confirm the behavior. It turns out that calls to Messaging Channels are totally asynchronous, &lt;strong&gt;but calls by the same client to the same RPC Channel are synchronous&lt;/strong&gt;. Which means if you send RequestA then RequestB, they will be processed in that order and the results will come back in that order. Regardless of how long either of them take to complete.

You can still run asynchronous RPC calls from the same client, but they would have to call different Channels. So the option is there if you need it.

I wanted to blog this because I&apos;ve been using remoting for a long time and never knew this. In fact, I always assumed the opposite was true. So, this is a big deal for two reasons: if you need to ensure the order of your RPC calls, you can. And conversely, if you think your RPC calls to the same Channel are running asynchronously, they actually are not! And this applies whether you&apos;re using a Java back end with BlazeDS/LCDS, or using ColdFusion with its BlazeDS integration.
				
				</description>
				
				
				<category>ColdFusion</category>
				
				<category>Flex</category>
				
				<pubDate>Wed, 14 Sep 2011 09:11:00 -0700</pubDate>
				<guid>http://www.briankotek.com/blog/index.cfm/2011/9/14/BlazeDS-and-LCDS-RPC-Call-Ordering</guid>
				
				
			</item>
			
		 	
			
			
			<item>
				<title>Using ColdFusion ORM and HQL, Part 5: Optimizing with HQL</title>
				<link>http://www.briankotek.com/blog/index.cfm/2010/9/21/Using-ColdFusion-ORM-and-HQL-Part-5-Optimizing-with-HQL</link>
				<description>
				
				In this entry, I want to take a look at using HQL to reduce unwanted database queries. As with any optimization, the first thing to do is identify the problem. So lets take a look at how Hibernate does things by default.

When you create a relationship between entities, the default fetching behavior for the relationship is called &quot;lazy&quot;. Which means that Hibernate won&apos;t try to load up the associated objects until something actually asks for them. And in some cases, this is perfectly fine. But in other cases, it can cause a lot of overhead.

Consider the relationship between a BlogEntry and a BlogComment. If you recall, this is a bidirectional relationship, where a BlogEntry has many BlogComments, and a BlogComment has one BlogEntry. That means if I load up a BlogComment, by default the associated BlogEntry is not loaded yet. Only when some code tries to access the comment&apos;s BlogEntry does Hibernate actually create that object. And that may be fine if I&apos;m only dealing with one comment.

But consider a situation where I want to show all of the comments that have been posted by a specific user, along with the BlogEntry where the comment was posted. I might have a simple DAO method that looks like:

&lt;code&gt;js|
function commentsByUser( id )
{
	return OrmExecuteQuery( &quot;SELECT c
				 FROM 
				 	BlogComment c
				 WHERE 
				 	c.createdBy.id=:id&quot;,
				 {id=arguments.id} 
				);
}
&lt;/code&gt;

Which will generate SQL like this:

&lt;code&gt;sql|
09/20 22:29:09 [jrpp-1] HIBERNATE DEBUG - 
    select
        blogcommen0_.id as id2_,
        blogcommen0_.content as content2_,
        blogcommen0_.dateCreated as dateCrea3_2_,
        blogcommen0_.entryId as entryId2_,
        blogcommen0_.createdBy as createdBy2_ 
    from
        BlogComment blogcommen0_ 
    where
        blogcommen0_.createdBy=?
&lt;/code&gt;
        
The query gets all of the comments posted by the user. I can loop over them, showing the comment along with the name and date of the blog entry. However, the overhead caused by the lazy loading will increase as the number of comments I&apos;m displaying goes up. For example, if a user has posted three comments, Hibernate will run the following queries when I try to display this information:  

&lt;code&gt;sql|        
09/20 22:29:09 [jrpp-1] HIBERNATE DEBUG - 
    select
        blogentry0_.id as id0_0_,
        blogentry0_.content as content0_0_,
        blogentry0_.dateCreated as dateCrea3_0_0_,
        blogentry0_.title as title0_0_,
        blogentry0_.createdBy as createdBy0_0_ 
    from
        BlogEntry blogentry0_ 
    where
        blogentry0_.id=?

09/20 22:29:09 [jrpp-1] HIBERNATE DEBUG - 
    select
        blogentry0_.id as id0_0_,
        blogentry0_.content as content0_0_,
        blogentry0_.dateCreated as dateCrea3_0_0_,
        blogentry0_.title as title0_0_,
        blogentry0_.createdBy as createdBy0_0_ 
    from
        BlogEntry blogentry0_ 
    where
        blogentry0_.id=?

09/20 22:29:09 [jrpp-1] HIBERNATE DEBUG - 
    select
        blogentry0_.id as id0_0_,
        blogentry0_.content as content0_0_,
        blogentry0_.dateCreated as dateCrea3_0_0_,
        blogentry0_.title as title0_0_,
        blogentry0_.createdBy as createdBy0_0_ 
    from
        BlogEntry blogentry0_ 
    where
        blogentry0_.id=?
&lt;/code&gt;

As I iterate over each comment to show the blog entry information, Hibernate must execute separate queries for each entry. This is how the lazy loading works. The associated objects are built on an as-needed basis.

As you can see, if I were showing 30 comments, that would be one query to get the comments, and then 30 queries to create each related BlogEntry. That&apos;s a lot of separate queries, especially if I know in advance that I will need them all.

One option is to modify the association to specify fetch=&quot;join&quot;, like this:

&lt;code&gt;js|[1]|
property name=&quot;blogEntry&quot; fieldtype=&quot;many-to-one&quot; fetch=&quot;join&quot;
		fkcolumn=&quot;entryId&quot; cfc=&quot;BlogEntry&quot; notnull=&quot;true&quot;;  
&lt;/code&gt;

This tells Hibernate &quot;every time you load a BlogComment, I want you to load the associated BlogEntry at the same time&quot;. This will cause the objects to be loaded in one SQL statement, eliminating the extra queries. Unfortunately, it&apos;s a very brute-force approach. I&apos;d better be &lt;strong&gt;really&lt;/strong&gt; sure that I &lt;strong&gt;always&lt;/strong&gt; want the associated blog entry with every comment. Otherwise, I&apos;m just switching one problem for another: I&apos;ll be loading a bunch of extra data if all I actually want are the comments!

To be honest, I&apos;m not happy with this all or nothing decision. The good news is, I can leave the association lazy by default, but use HQL to perform JOIN fetching for situations where I want to load all of the data at once. The method in my DAO might look like this:

&lt;code&gt;js|[6]|
function commentsByUser( id )
{
	return OrmExecuteQuery( &quot;SELECT c
				 FROM 
				 	BlogComment c 
				 	JOIN FETCH c.blogEntry b
				 	JOIN c.createdBy u
				 WHERE 
				 	u.id=:id&quot;,
				 {id=arguments.id} 
				);
}
&lt;/code&gt;	

As you can see, I&apos;m telling hibernate to fetch the blog entry data along with the comments. The resulting SQL would look like:
		
&lt;code&gt;sql|
09/20 22:30:11 [jrpp-1] HIBERNATE DEBUG - 
    select
        blogcommen0_.id as id2_0_,
        blogentry1_.id as id0_1_,
        blogcommen0_.content as content2_0_,
        blogcommen0_.dateCreated as dateCrea3_2_0_,
        blogcommen0_.entryId as entryId2_0_,
        blogcommen0_.createdBy as createdBy2_0_,
        blogentry1_.content as content0_1_,
        blogentry1_.dateCreated as dateCrea3_0_1_,
        blogentry1_.title as title0_1_,
        blogentry1_.createdBy as createdBy0_1_ 
    from
        BlogComment blogcommen0_ 
    inner join
        BlogEntry blogentry1_ 
            on blogcommen0_.entryId=blogentry1_.id 
    inner join
        `User` user2_ 
            on blogcommen0_.createdBy=user2_.id 
    where
        user2_.id=?
&lt;/code&gt;

Which means the BlogEntry will be loaded up along with the BlogComments, all from a single query. In this context, that&apos;s going to be a great deal more efficient than executing separate queries for every association. I hope you can see that a big advantage of using HQL is the fine-grained control it offers when it comes to loading objects. I should have one or two more looks at some other scenarios where HQL can help you optimize your application, so stay tuned!
				
				</description>
				
				
				<category>ColdFusion</category>
				
				<category>Object-Relational Mapping</category>
				
				<pubDate>Tue, 21 Sep 2010 07:49:00 -0700</pubDate>
				<guid>http://www.briankotek.com/blog/index.cfm/2010/9/21/Using-ColdFusion-ORM-and-HQL-Part-5-Optimizing-with-HQL</guid>
				
				
			</item>
			
		 	
			
			
			<item>
				<title>Using ColdFusion ORM and HQL, Part 4: Basic Filtering and Sorting</title>
				<link>http://www.briankotek.com/blog/index.cfm/2010/9/15/Using-ColdFusion-ORM-and-HQL-Part-4-Basic-Filtering-and-Sorting</link>
				<description>
				
				Now that we&apos;ve got our domain model set up, associations created, and relationships managed, I want to delve into the topic of &lt;a href=&quot;http://docs.jboss.org/hibernate/core/3.3/reference/en/html/queryhql.html&quot; target=&quot;_blank&quot;&gt;HQL&lt;/a&gt;. In case you aren&apos;t aware, HQL is an &quot;object-centric&quot; query syntax that gives you very fine-grained control over what Hibernate is doing when you ask it to retrieve objects from the database.

I&apos;ll say up front that I am a proponent of using &lt;a href=&quot;http://en.wikipedia.org/wiki/Data_access_object&quot; target=&quot;_blank&quot;&gt;data access objects (DAOs)&lt;/a&gt; to encapsulate interaction with the database. In essence, that means the only place that really should know about the database, Hibernate, or HQL is within the DAOs. So the examples I&apos;m going to show are created as methods within a DAO. 

We&apos;ll start with some simple sorting and filtering. This is a common requirement, and HQL makes it very easy to do:

&lt;code&gt;js|	
function allEntries()
{
	return OrmExecuteQuery( &quot;FROM 
					BlogEntry b 
				 ORDER BY 
					b.dateCreated DESC&quot; );
}
&lt;/code&gt;

That simply gets all of the blog entries, sorted by the date they were created.

&lt;code&gt;js|
function mostRecentEntry()
{
	var results = OrmExecuteQuery( &quot;FROM 
						BlogEntry b 
					ORDER BY 
						b.dateCreated DESC&quot;, 
					false, {maxResults=1} );
	return results[1];
}
&lt;/code&gt;

As the name implies, the above HQL would get the most recent blog entry. 

&lt;code&gt;js|
function entriesByUser( id )
{
	return OrmExecuteQuery( &quot;SELECT b 
				FROM 
					BlogEntry b 
					JOIN b.createdBy u
				WHERE 
					u.id=:id&quot;,
				{id=arguments.id} );
}
&lt;/code&gt;

Here, we start leveraging the object relationships. In this case, I&apos;m getting all of the blog entries that were created by the specified user.

&lt;code&gt;js|
function entriesWithCommentsFromUserName( userName )
{
	return OrmExecuteQuery( &quot;SELECT DISTINCT b 
				FROM 
					BlogEntry b 
					JOIN b.comments c 
					JOIN c.createdBy u 
				WHERE 
					u.name LIKE :userName&quot;,
				{userName=&apos;%#arguments.userName#%&apos;} );
}
&lt;/code&gt;

And finally, the above HQL loads all BlogEntries that have a comment which was posted by a user matching a user name search string. This is a fairly contrived example, since I&apos;m not sure a blog application would actually need to do this. But on the ORM mailing list, I&apos;ve seen several people with the need to filter the objects based on a property from a collection of related objects. 

To make it more clear, this is the actual SQL that Hibernate would generate under the hood for this HQL:

&lt;code&gt;sql|
09/15 00:58:17 [jrpp-2] HIBERNATE DEBUG - 
select
        distinct blogentry0_.id as id0_,
                blogentry0_.content as content0_,
                blogentry0_.dateCreated as dateCrea3_0_,
                blogentry0_.title as title0_,
                blogentry0_.createdBy as createdBy0_ 
        from
                BlogEntry blogentry0_
                inner join
                BlogComment comments1_ 
                	on blogentry0_.id=comments1_.entryId 
                inner join
                	`User` user2_
                	on comments1_.createdBy=user2_.id
        where
        		user2_.name like ?
            		
09/15 00:58:17 [jrpp-2] HIBERNATE DEBUG - binding &apos;%Tom%&apos; to parameter: 1
&lt;/code&gt;

The SQL itself may seem obvious to anyone familiar with SQL. But since Hibernate is dealing with objects and properties, it can sometimes take a bit of trial and error to work out how traverse properties that are collections of objects.

I will stop here for today. In the next entry, we&apos;ll focus on using HQL to optimize the loading of larger object graphs.
				
				</description>
				
				
				<category>ColdFusion</category>
				
				<category>Object-Relational Mapping</category>
				
				<pubDate>Wed, 15 Sep 2010 08:52:00 -0700</pubDate>
				<guid>http://www.briankotek.com/blog/index.cfm/2010/9/15/Using-ColdFusion-ORM-and-HQL-Part-4-Basic-Filtering-and-Sorting</guid>
				
				
			</item>
			
		 	
			
			
			<item>
				<title>Using ColdFusion ORM and HQL, Part 3: Bidirectional Relationships</title>
				<link>http://www.briankotek.com/blog/index.cfm/2010/9/14/Using-ColdFusion-ORM-and-HQL-Part-3-Bidirectional-Relationships</link>
				<description>
				
				In this entry I want to take a closer look at the relationship I have set up between BlogEntry and BlogComment. Since I want to be able to ask an entry for its comments, and I also want to be able to ask a comment for its entry, this is a bidirectional relationship. As a result, this takes a bit of additional thought to get working optimally.

Recall that BlogEntry looks like this right now:

&lt;code&gt;js|
component displayname=&quot;BlogEntry&quot; extends=&quot;Entity&quot; output=&quot;false&quot; 
		  persistent=&quot;true&quot; accessors=&quot;true&quot;
{
	property name=&quot;title&quot; type=&quot;string&quot; ormtype=&quot;string&quot;;
	property name=&quot;content&quot; type=&quot;string&quot; ormtype=&quot;text&quot;;
	property name=&quot;categories&quot; singularname=&quot;category&quot; fieldtype=&quot;many-to-many&quot; 
  		     cfc=&quot;BlogCategory&quot; linktable=&quot;entry_category&quot; 
  		     fkcolumn=&quot;entryId&quot; inversejoincolumn=&quot;categoryId&quot;;
	property name=&quot;comments&quot; singularname=&quot;comment&quot; fieldtype=&quot;one-to-many&quot;
  		     cfc=&quot;BlogComment&quot; fkcolumn=&quot;entryId&quot; 
  		     orderby=&quot;dateCreated ASC&quot; inverse=&quot;true&quot;;
	
	BlogEntry function init()
	{
		variables.categories = [];
		variables.comments = [];
		return this;
	}	
}
&lt;/code&gt;

And that BlogComment looks like:

&lt;code&gt;js|
component displayname=&quot;BlogComment&quot; extends=&quot;Entity&quot; output=&quot;false&quot;
		  persistent=&quot;true&quot; accessors=&quot;true&quot;
{
	property name=&quot;content&quot; type=&quot;string&quot; ormtype=&quot;text&quot;;
	property name=&quot;blogEntry&quot; fieldtype=&quot;many-to-one&quot; 
 	  	     fkcolumn=&quot;entryId&quot; cfc=&quot;BlogEntry&quot;;  
}
&lt;/code&gt;

The first thing to make note of is that the comments collection in BlogEntry is marked as inverse. As I (and others) have &lt;a href=&quot;http://www.briankotek.com/blog/index.cfm/2009/12/21/More-on-CF9-ORM-Relationships&quot; target=&quot;_blank&quot;&gt;mentioned&lt;/a&gt; &lt;a href=&quot;http://www.barneyb.com/barneyblog/2010/04/09/dont-forget-inverse-true/&quot; target=&quot;_blank&quot;&gt;previously&lt;/a&gt;, it is important to designate one side of a bidirectional relationship as the owning side. By setting the comments collection as inverse, I am telling Hibernate that &lt;strong&gt;the other side of this relationship is the owning side&lt;/strong&gt;. In other words, the blogEntry property in BlogComment is the owner of this relationship.

This has a very important effect on the relationship: &lt;strong&gt;Hibernate will ignore all persistence operations regarding this relationship on the side that is marked as inverse.&lt;/strong&gt; Which means that in order to get Hibernate to properly save this relationship, I must set the blogEntry property in BlogComment. Put another way, I&apos;m telling Hibernate: &quot;when it comes to his relationship, I want you to use the blogEntry property of BlogComment to dictate what you persist to the database&quot;. 

I need to emphasize one additional point, which is that even though Hibernate only cares about what is set into the blogEntry property when it comes to persisting my data, my domain model most certainly cares about both sides of the relationship. If I set the blogEntry property on one of my BlogComments, then that BlogComment better be present in the comments collection of my BlogEntry.

So it looks like we have two different issues. First, how do I make sure the owning side of the relationship (the blogEntry property) is always set correctly. And second, how do I make sure that the collection of BlogComments in a BlogEntry is also kept up to date?

At first glace, the solution might just be to dictate that anyone who wants to set up this bidirectional relationship needs to know that they should always do both comment.setBlogEntry( blogEntry ) and blogEntry.addComment( comment ). And that will certainly work. But it&apos;s a poor solution, and the reason why is probably obvious: if someone forgets to set up both sides, my domain model spirals into an invalid state.

The good news is that there is a simple best-practice way to enforce this relationship. It is called an association management method. Which just means I should create methods on my BlogEntry and my BlogComment to ensure that both sides are always set together.

I&apos;ll start with the owning side, which in this case is BlogComment.

&lt;code&gt;js|
component displayname=&quot;BlogComment&quot; extends=&quot;Entity&quot; output=&quot;false&quot;
		  persistent=&quot;true&quot; accessors=&quot;true&quot;
{
	property name=&quot;content&quot; type=&quot;string&quot; ormtype=&quot;text&quot;;
	property name=&quot;blogEntry&quot; fieldtype=&quot;many-to-one&quot; 
 	  	     fkcolumn=&quot;entryId&quot; cfc=&quot;BlogEntry&quot; notnull=&quot;true&quot;;  

	function setBlogEntry( blogEntry )
	{
		if( !IsNull( arguments.blogEntry ) )
		{
			variables.blogEntry = arguments.blogEntry;		

			if( !arguments.blogEntry.hasComment( this ) )
			{
				ArrayAppend( arguments.blogEntry.getComments(), this );
			}
		}	
	}
}
&lt;/code&gt;

The code is very straightforward, but just to make sure, I&apos;ll go through it. When a blogEntry is set on a BlogComment, the first thing I do is check to make sure the incoming blogEntry is not null. In my model, I can&apos;t have a comment without an entry. Next, I set the value of blogEntry to the incoming value. And finally, if the incoming blogEntry doesn&apos;t have this comment in its collection of comments, I add it to the comments collection.

Since BlogComment already has all of the logic I need to set up the relationship, all I need to do in BlogEntry is delegate to the setBlogEntry method in BlogComment:

&lt;code&gt;js|
component displayname=&quot;BlogEntry&quot; extends=&quot;Entity&quot; output=&quot;false&quot; 
		  persistent=&quot;true&quot; accessors=&quot;true&quot;
{
	property name=&quot;title&quot; type=&quot;string&quot; ormtype=&quot;string&quot;;
	property name=&quot;content&quot; type=&quot;string&quot; ormtype=&quot;text&quot;;
	property name=&quot;categories&quot; singularname=&quot;category&quot; fieldtype=&quot;many-to-many&quot; 
  		     cfc=&quot;BlogCategory&quot; linktable=&quot;entry_category&quot; 
  		     fkcolumn=&quot;entryId&quot; inversejoincolumn=&quot;categoryId&quot;;
	property name=&quot;comments&quot; singularname=&quot;comment&quot; fieldtype=&quot;one-to-many&quot;
  		     cfc=&quot;BlogComment&quot; fkcolumn=&quot;entryId&quot; 
  		     orderby=&quot;dateCreated ASC&quot; inverse=&quot;true&quot;;
	
	BlogEntry function init()
	{
		variables.categories = [];
		variables.comments = [];
		return this;
	}	

	function addComment( comment )
	{
		comment.setBlogEntry( this );
	}
}
&lt;/code&gt;

With these association management methods set up, I now know that any time someone sets a blogEntry on a comment, or adds a comment to a blogEntry, both sides of the relationship will always be set. I would strongly recommend that you adopt a strategy like this to enforce the rules for your bidirectional relationships.

In the next few entries, I&apos;ll move on to the topic of HQL. I want to show some of the ways you can leverage HQL to optimize the way Hibernate interacts with the database.
				
				</description>
				
				
				<category>ColdFusion</category>
				
				<category>Object-Relational Mapping</category>
				
				<pubDate>Tue, 14 Sep 2010 08:16:00 -0700</pubDate>
				<guid>http://www.briankotek.com/blog/index.cfm/2010/9/14/Using-ColdFusion-ORM-and-HQL-Part-3-Bidirectional-Relationships</guid>
				
				
			</item>
			
		 	
			
			
			<item>
				<title>Using ColdFusion ORM and HQL, Part 2: ORM Event Handler</title>
				<link>http://www.briankotek.com/blog/index.cfm/2010/9/10/Using-ColdFusion-ORM-and-HQL-Part-2-ORM-Event-Handler</link>
				<description>
				
				In the previous entry, I described the basic blog application I want to create. We looked at the model, the relationships needed, and whipped up the CFCs to implement that model.

One of the things I mentioned is that I want each entity to be able to keep track of when it was created and who created it. This could be done manually, but I like to avoid manual whenever I can. The good news is that we can easily do this automatically. 

The solution is to use Hibernate&apos;s event model. In Hibernate terms, the classes that are notified about persistence activities are called interceptors. Happily, the ColdFusion development team have given us access to this capability by letting us specify event handler CFCs in our ORM configuration.

I should note that I am running CF 9.0.1 with the &lt;a href=&quot;http://kb2.adobe.com/cps/862/cpsid_86263.html&quot; target=&quot;_blank&quot;&gt;cumulative hotfix&lt;/a&gt; installed. I&apos;ll set up my Application.cfc like this:

&lt;code&gt;js|
component name=&quot;Application.cfc&quot; output=&quot;false&quot;
{
    this.name = Hash( GetCurrentTemplatePath() );
    
    this.sessionManagement = true;
    this.sessionTimeout = CreateTimeSpan( 0, 0, 0, 10 );
    this.setClientCookies = true;
    this.setDomainCookies = true;
    
    this.appRoot = ExpandPath( &apos;.&apos; );
    this.mappings = {};
    this.mappings[&quot;/ormblog&quot;] = this.appRoot;
    
    this.datasource = &quot;ormblog&quot;;
    this.ormEnabled = true;
    this.ormSettings.dialect = &quot;MySQLwithInnoDB&quot;;
    this.ormSettings.logSQL = true;
    this.ormSettings.saveMapping = false;
    this.ormSettings.eventHandler = &apos;ormblog.model.orminterceptor.AuditInterceptor&apos;;
    this.ormSettings.flushAtRequestEnd = false;
    this.ormSettings.autoManageSession = false;
    this.ormsettings.dbcreate = &quot;dropcreate&quot;;
} 
&lt;/code&gt;

You can see that I&apos;m specifying an AuditInterceptor CFC as an &lt;a href=&quot;http://help.adobe.com/en_US/ColdFusion/9.0/Developing/WSDD377092-70D9-4b11-A19C-505F59EE31D1.html&quot; target=&quot;_blank&quot;&gt;ORM event handler&lt;/a&gt;. Any event handler CFC we define must implement the CFIDE.ORM.IEventHandler interface, so my AuditInterceptor looks like this:

&lt;code&gt;js|
import ormblog.model.domain.*;

component output=&quot;false&quot; implements=&quot;CFIDE.ORM.IEventHandler&quot;
{
    public void function preInsert( any entity )
    {
   	 entity.setDateCreated( Now() );
   	 if( IsNull( entity.getCreatedBy() ) 
             &amp;&amp; StructKeyExists( session, &apos;currentUser&apos; ) )
   	 {
   		 entity.setCreatedBy( EntityLoadByPK( &apos;User&apos;, session.currentUser ) );
   	 }
    }
    
    public void function preLoad( any entity )
    {
    }
    
    public void function postLoad( any entity )
    {
    }
    
    public void function postInsert( any entity )
    {
    }
    
    public void function preUpdate( any entity, Struct oldData )
    {
    }
    
    public void function postUpdate( any entity )
    {
    }
    
    public void function preDelete( any entity )
    {
    }
    
    public void function postDelete( any entity )
    {
    }

}
&lt;/code&gt;

In my preInsert() method, I&apos;m setting the dateCreated, and setting the createdBy to the currently logged in User. In a real application, I would probably avoid having my interceptor reach into the session scope by using ColdSpring to inject a Session Proxy object that encapsulates interaction with the session scope. But in the interest of keeping this example simple and focused, we&apos;ll just grab the current user&apos;s ID from the session scope.

The end result of this is that any time I persist a new entity, the dateCreated and createdBy properties will be set automatically. And this could easily be expanded, for example if I ever want to track dateUpdated or updatedBy, etc. 

If I only wanted to perform this audit tracking on certain CFCs, rather than all subclasses of my Entity class, I could create another subclass of Entity called AuditableEntity and have my CFCs extend that, or I could create an Auditable interface and have my CFCs implement that interface. The AuditInterceptor could then be changed to only set the audit properties if the CFC being saved is of type AuditableEntity/Auditable. But I digress. ;-)

We&apos;ve now completed the automatic population of dateCreated and updatedBy. In the next entry I&apos;ll dig deeper into the bi-directional relationship between BlogEntry and BlogComment.
				
				</description>
				
				
				<category>ColdFusion</category>
				
				<category>Object-Relational Mapping</category>
				
				<pubDate>Fri, 10 Sep 2010 08:35:00 -0700</pubDate>
				<guid>http://www.briankotek.com/blog/index.cfm/2010/9/10/Using-ColdFusion-ORM-and-HQL-Part-2-ORM-Event-Handler</guid>
				
				
			</item>
			
		 	
			
			
			<item>
				<title>Using ColdFusion ORM and HQL, Part 1</title>
				<link>http://www.briankotek.com/blog/index.cfm/2010/9/9/Using-ColdFusion-ORM-and-HQL-Part-1</link>
				<description>
				
				Now that the Hibernate integration in ColdFusion 9 has been in use for a while, we&apos;re seeing an increasing number of questions on the &lt;a href=&quot;http://groups.google.com/group/cf-orm-dev&quot; target=&quot;_blank&quot;&gt;CF-ORM mailing list&lt;/a&gt;. This isn&apos;t surprising, Hibernate is a vast topic in and of itself, and the CF documentation can really only scratch the surface. There are entire books just dedicated to using Hibernate (my personal favorite being &lt;a href=&quot;http://www.amazon.com/Java-Persistence-Hibernate-Christian-Bauer/dp/1932394885&quot; target=&quot;_blank&quot;&gt;Java Persistence with Hibernate&lt;/a&gt;). 

It&apos;s one thing to look at the documentation and understand the simple use cases, but quite another to actually get into real world application development with Hibernate. With this in mind, I&apos;m going to be posting a few blog entries that explore using CF and Hibernate in some more complex scenarios.

The end result will be a rudimentary blog application, and I&apos;ll post that code in the last blog entry on this topic. But before we get to that, I want to back up and look at how one might approach the design of this application.

Here is a simple UML diagram of the domain model I want to create:

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

Contrary to good OO design, I&apos;m not focusing on the behavior of these objects at all due to the fact that this is specifically an ORM example. I am also making the following assumptions, which affected the way the associations were defined, and will drive some later decisions when it comes to loading the objects:

&lt;ul&gt;
&lt;li&gt;A BlogEntry will typically be associated with a few BlogCategories (between one and four, but maybe a few more)&lt;/li&gt;
&lt;li&gt;A large number of BlogEntries (hundreds or thousands) can be associated with a BlogCategory&lt;/li&gt;
&lt;li&gt;A low to moderate number of BlogComments can be associated with a BlogEntry (probably up to a few dozen unless the entry triggers an unusual number of comments)&lt;/li&gt;
&lt;li&gt;Each entity should keep track of when it was created and who created it&lt;/li&gt;
&lt;/ul&gt;

With this in mind, the relationships are defined as follows:

&lt;ul&gt;
&lt;li&gt;One User can be associated with many Entities via the createdBy property&lt;/li&gt;
&lt;li&gt;One BlogCategory can be associated with many BlogEntries&lt;/li&gt;
&lt;li&gt;Many BlogComments can be associated with a BlogEntry&lt;/li&gt;
&lt;li&gt;One BlogEntry can be associated with a BlogComment&lt;/li&gt;
&lt;/ul&gt;

Translated into code, the entities look like this:

&lt;code&gt;js|
component displayname=&quot;Entity&quot; output=&quot;false&quot; mappedsuperclass=&quot;true&quot; accessors=&quot;true&quot;
{
	property name=&quot;id&quot; fieldtype=&quot;id&quot; type=&quot;numeric&quot; ormtype=&quot;int&quot; generator=&quot;native&quot;;
	property name=&quot;dateCreated&quot; type=&quot;date&quot; ormtype=&quot;timestamp&quot;;
	property name=&quot;createdBy&quot; fieldtype=&quot;many-to-one&quot; cfc=&quot;User&quot; fkcolumn=&quot;createdBy&quot;;
}
&lt;/code&gt;

&lt;code&gt;js|
component displayname=&quot;User&quot; extends=&quot;Entity&quot; persistent=&quot;true&quot;
		  output=&quot;false&quot; accessors=&quot;true&quot;
{
	property name=&quot;name&quot; type=&quot;string&quot; ormtype=&quot;string&quot;;
}
&lt;/code&gt;

&lt;code&gt;js|
component displayname=&quot;BlogEntry&quot; extends=&quot;Entity&quot; output=&quot;false&quot; 
		  persistent=&quot;true&quot; accessors=&quot;true&quot;
{
	property name=&quot;title&quot; type=&quot;string&quot; ormtype=&quot;string&quot;;
	property name=&quot;content&quot; type=&quot;string&quot; ormtype=&quot;text&quot;;
	property name=&quot;categories&quot; singularname=&quot;category&quot; fieldtype=&quot;many-to-many&quot; 
  		     cfc=&quot;BlogCategory&quot; linktable=&quot;entry_category&quot; 
  		     fkcolumn=&quot;entryId&quot; inversejoincolumn=&quot;categoryId&quot;;
	property name=&quot;comments&quot; singularname=&quot;comment&quot; fieldtype=&quot;one-to-many&quot;
  		     cfc=&quot;BlogComment&quot; fkcolumn=&quot;entryId&quot; 
  		     orderby=&quot;dateCreated ASC&quot; inverse=&quot;true&quot;;
	
	BlogEntry function init()
	{
		variables.categories = [];
		variables.comments = [];
		return this;
	}	
}
&lt;/code&gt;

&lt;code&gt;js|
component displayname=&quot;BlogCategory&quot; extends=&quot;Entity&quot; output=&quot;false&quot;
		  persistent=&quot;true&quot; accessors=&quot;true&quot;
{
	property name=&quot;name&quot; type=&quot;string&quot; ormtype=&quot;string&quot;;
}
&lt;/code&gt;

&lt;code&gt;js|
component displayname=&quot;BlogComment&quot; extends=&quot;Entity&quot; output=&quot;false&quot;
		  persistent=&quot;true&quot; accessors=&quot;true&quot;
{
	property name=&quot;content&quot; type=&quot;string&quot; ormtype=&quot;text&quot;;
	property name=&quot;blogEntry&quot; fieldtype=&quot;many-to-one&quot; 
 	  	     fkcolumn=&quot;entryId&quot; cfc=&quot;BlogEntry&quot;;  
}
&lt;/code&gt;

As you can see, this is really a tiny amount of code when you consider everything that is going on under the hood. This gives me a solid basis for the application. I can create these objects, set properties and associations, and persist them to the database. But that&apos;s the easy part. I want to go further than the simple use cases.

In the upcoming entries, I&apos;ll look at how to best handle the bi-directional association between BlogEntry and BlogComment, as well as how to automatically set the createdBy and dateUpdated properties in Entity. I&apos;ll also be taking an in-depth look at using HQL for filtering, sorting, and optimizing the way the objects are created to eliminate unnecessary database queries.
				
				</description>
				
				
				<category>ColdFusion</category>
				
				<category>Object-Relational Mapping</category>
				
				<pubDate>Thu, 09 Sep 2010 08:48:00 -0700</pubDate>
				<guid>http://www.briankotek.com/blog/index.cfm/2010/9/9/Using-ColdFusion-ORM-and-HQL-Part-1</guid>
				
				
			</item>
			
		 	
			
			
			<item>
				<title>ColdFusion 9 Article at Techrepublic.com</title>
				<link>http://www.briankotek.com/blog/index.cfm/2010/3/1/ColdFusion-9-Article-at-Techrepubliccom</link>
				<description>
				
				Just a quick note that I&apos;ve had an &lt;a href=&quot;http://blogs.techrepublic.com.com/programming-and-development/?p=2291&quot; target=&quot;_blank&quot;&gt;article on ColdFusion 9&lt;/a&gt; published over at CNET TechRepublic.com. It probably won&apos;t tell anyone who reads my blog much that they don&apos;t already know, but I hope that it attracts the attention of those outside of the core CF community!
				
				</description>
				
				
				<category>ColdFusion</category>
				
				<pubDate>Mon, 01 Mar 2010 11:25:00 -0700</pubDate>
				<guid>http://www.briankotek.com/blog/index.cfm/2010/3/1/ColdFusion-9-Article-at-Techrepubliccom</guid>
				
				
			</item>
			
		 	
			
			
			<item>
				<title>More on CF9 ORM Relationships</title>
				<link>http://www.briankotek.com/blog/index.cfm/2009/12/21/More-on-CF9-ORM-Relationships</link>
				<description>
				
				My entry late last week on &lt;a href=&quot;http://www.briankotek.com/blog/index.cfm/2009/12/16/Bidirectional-Association-Management-in-ColdFusion-9-ORM&quot; target=&quot;_blank&quot;&gt;association management methods&lt;/a&gt; prompted a number of comments. I was going to add another comment but this became quite long so instead I&apos;m adding another blog entry.

The point of my last post was to talk about bidirectional relationships, particularly a one-to-many/many-to-one between two entities. Hibernate (and, thus, the CF9 ORM) has the ability to specify an &quot;inverse&quot; attribute on your relationship. To better show why you usually want to do this, let&apos;s look at an example.
				 [More]
				</description>
				
				
				<category>ColdFusion</category>
				
				<category>OOP CF</category>
				
				<category>Object-Relational Mapping</category>
				
				<pubDate>Mon, 21 Dec 2009 13:07:00 -0700</pubDate>
				<guid>http://www.briankotek.com/blog/index.cfm/2009/12/21/More-on-CF9-ORM-Relationships</guid>
				
				
			</item>
			
		 	
			
			
			<item>
				<title>Bidirectional Association Management in ColdFusion 9 ORM</title>
				<link>http://www.briankotek.com/blog/index.cfm/2009/12/16/Bidirectional-Association-Management-in-ColdFusion-9-ORM</link>
				<description>
				
				And to follow up on my recent pledge to start blogging further about ORM, lets jump right into a recent topic. A thread on the CF-ORM mailing list brought up the topic of &lt;a href=&quot;http://groups.google.com/group/cf-orm-dev/browse_thread/thread/4320cc207bc8df53?hl=en&quot; target=&quot;_blank&quot;&gt;dealing with a bidirectional relationship&lt;/a&gt;.
				 [More]
				</description>
				
				
				<category>ColdFusion</category>
				
				<category>OOP CF</category>
				
				<category>Object-Relational Mapping</category>
				
				<pubDate>Wed, 16 Dec 2009 10:36:00 -0700</pubDate>
				<guid>http://www.briankotek.com/blog/index.cfm/2009/12/16/Bidirectional-Association-Management-in-ColdFusion-9-ORM</guid>
				
				
			</item>
			
		 	
			
			
			<item>
				<title>Iterator on RIAForge, and Updates to FormUtils and ColdSpring Utils</title>
				<link>http://www.briankotek.com/blog/index.cfm/2009/12/16/Iterator-on-RIAForge-and-Updates-to-FormUtils-and-ColdSpring-Uti</link>
				<description>
				
				The blog has been quiet lately, but that should be changing now that I&apos;m finally doing some real work with ColdFusion 9! In the meantime, I&apos;ve committed a few minor updates to some RIAForge projects, and added a new one.

The new project is &lt;a href=&quot;http://collectioniterator.riaforge.org/&quot; target=&quot;_blank&quot;&gt;Collection Iterator&lt;/a&gt;. This is simply a CFC that allows you to iterate the same way over queries, lists, structures, or arrays. The syntax is simple:

&lt;code&gt;
var array = [&apos;foo&apos;, &apos;boo&apos;, &apos;zoo&apos;];
var iterator = new Iterator( array );
var counter = 0;

while( iterator.hasNext() )
{
    counter++;
    var thisRow = iterator.next();
    assertTrue( array[counter] == thisRow, &quot;Array element not found.&quot; );    
}

assertTrue( counter == 3, &quot;Iterator did not loop the correct number of times.&quot; );    
&lt;/code&gt;

The obvious benefit is that it lets you handle all four collection types in a standard way. This is a CF9-only component, as it is written using the new script-only CFC syntax (which I LOVE, but will be talking about further in future entries).

As for updates, I fixed a bug in the DynamicXMLBeanFactory, which is part of the &lt;a href=&quot;http://coldspringutils.riaforge.org/&quot; target=&quot;_blank&quot;&gt;ColdSpring Bean Utilities library&lt;/a&gt;. There was an issue when using ColdSpring configuration files that imported multiple other config files. The CFC was also modified to only attempt to do an ExpandPath() on the configuration file location if a file doesn&apos;t exist using the value supplied by the developer. I also updated the &lt;a href=&quot;http://formutils.riaforge.org/&quot; target=&quot;_blank&quot;&gt;FormUtils CFC&lt;/a&gt; to make the constructor arguments optional, to make it easier to configure and use.

So, that&apos;s all for now, but look for some entries on CF9 ORM tips and techniques, as well as a full reboot of my earlier series on the Swiz framework for Flex. &lt;a href=&quot;http://swizframework.org/2009/12/swiz-1-0-0-alpha-released/&quot; target=&quot;_blank&quot;&gt;Swiz 1.0 alpha was just released&lt;/a&gt;, and as the finishing touches are added I plan to be blogging about all the excellent new capabilities that have been added by the Swiz team!
				
				</description>
				
				
				<category>ColdFusion</category>
				
				<category>ColdSpring</category>
				
				<category>FormUtilities CFC</category>
				
				<pubDate>Wed, 16 Dec 2009 09:49:00 -0700</pubDate>
				<guid>http://www.briankotek.com/blog/index.cfm/2009/12/16/Iterator-on-RIAForge-and-Updates-to-FormUtils-and-ColdSpring-Uti</guid>
				
				
			</item>
			
		 	
			
			
			<item>
				<title>My CFinNC Presentations at SlideSix</title>
				<link>http://www.briankotek.com/blog/index.cfm/2009/10/22/My-CFinNC-Presentations-at-SlideSix</link>
				<description>
				
				I&apos;ve uploaded my &lt;a href=&quot;http://www.cfinnc.com&quot; target=&quot;_blank&quot;&gt;CFinNC&lt;/a&gt; presentations to SlideSix for anyone who&apos;s interested:

&lt;a href=&quot;http://slidesix.com/view/Brian-Kotek--CFinNC--OO-Design-Principles-Final&quot; target=&quot;_blank&quot;&gt;Object-Oriented Design Principles&lt;/a&gt;

&lt;a href=&quot;http://slidesix.com/view/Swiz--Brian-Kotek--CFinNC&quot; target=&quot;_blank&quot;&gt;Introduction to Swiz&lt;/a&gt;

Overall, CFinNC was great. I actually had to work for a large chunk of the weekend so aside from presenting and mingling with folks later in the evening, I didn&apos;t get to attend many other sessions. That said, everything looked top-notch while I was there. The conference unfolded very smoothly and all of the attendees seemed very engaged. Hats off to Dan Wilson and the entire volunteer team for pulling this off! This conference definitely held its own against the other CF conferences I&apos;ve attended. It was very difficult to tell that it was completely free. Hopefully we can do it again next year!
				
				</description>
				
				
				<category>Development</category>
				
				<category>ColdFusion</category>
				
				<category>OOP CF</category>
				
				<category>Flex</category>
				
				<category>Conferences</category>
				
				<category>Presentations</category>
				
				<category>Swiz</category>
				
				<pubDate>Thu, 22 Oct 2009 12:02:00 -0700</pubDate>
				<guid>http://www.briankotek.com/blog/index.cfm/2009/10/22/My-CFinNC-Presentations-at-SlideSix</guid>
				
				
			</item>
			
		 	
			
			
			<item>
				<title>On the CFPanel Podcast with Mark Mandel and Barney Boisvert</title>
				<link>http://www.briankotek.com/blog/index.cfm/2009/9/4/On-the-CFPanel-Podcast-with-Mark-Mandel-and-Barney-Boisvert</link>
				<description>
				
				I&apos;m happy to say I&apos;ll be participating in the &lt;a href=&quot;http://cfpanel.com/index.cfm/2009/9/3/Episode-5--ColdFusion-and-Java-Integration&quot; target=&quot;_blank&quot;&gt;CFPanel Podcast&lt;/a&gt; on September 8 at 8 PM EST. We&apos;ll be discussing ColdFusion and Java integration. I hope to add some helpful substance to the conversation, but I&apos;m really looking forward to hearing what Mark (who created JavaLoader) and Barney (who created CFGroovy) have to say.

Listen in if you can, or check out the Connect recording afterwards. Thanks!
				
				</description>
				
				
				<category>Development</category>
				
				<category>ColdFusion</category>
				
				<category>Java</category>
				
				<category>Groovy</category>
				
				<category>Presentations</category>
				
				<pubDate>Fri, 04 Sep 2009 12:11:00 -0700</pubDate>
				<guid>http://www.briankotek.com/blog/index.cfm/2009/9/4/On-the-CFPanel-Podcast-with-Mark-Mandel-and-Barney-Boisvert</guid>
				
				
			</item>
			
		 	
			
			
			<item>
				<title>I&apos;m Speaking at the CFinNC Conference...See You There?</title>
				<link>http://www.briankotek.com/blog/index.cfm/2009/9/4/Im-Speaking-at-the-CFinNC-ConferenceSee-You-There</link>
				<description>
				
				Just a quick note that I&apos;ll be speaking at the &lt;a href=&quot;http://www.cfinnc.com/&quot; target=&quot;_blank&quot;&gt;CFinNC&lt;/a&gt; conference on October 17-18th here in Raleigh, NC. My topics are Object-oriented Design Principles and The Swiz Framework for Flex. 

The conference is FREE and the lineup is very impressive, so if you can attend, please register! And if you register, please actually show up! The danger with a free conference is that it&apos;s easy for folks to back out at the last minute, since they lose nothing. But for the organizers, it makes estimating actual attendance difficult. So if you sign up, please do your best to make it. :-)

I&apos;m looking forward to seeing some folks that I normally have to wait until MAX or next year&apos;s CFObjective or CFUnited conferences to see. And I hope to meet a lot of new people as well. See you in Raleigh!
				
				</description>
				
				
				<category>ColdFusion</category>
				
				<category>OOP CF</category>
				
				<category>Flex</category>
				
				<category>Conferences</category>
				
				<category>Swiz</category>
				
				<pubDate>Fri, 04 Sep 2009 12:00:00 -0700</pubDate>
				<guid>http://www.briankotek.com/blog/index.cfm/2009/9/4/Im-Speaking-at-the-CFinNC-ConferenceSee-You-There</guid>
				
				
			</item>
			
		 	
			
			
			<item>
				<title>Final Prep for CFUnited!</title>
				<link>http://www.briankotek.com/blog/index.cfm/2009/8/10/Final-Prep-for-CFUnited</link>
				<description>
				
				It&apos;s been a while since I&apos;ve blogged, as you might guess I&apos;ve been really busy. I do plan to dive back into blogging again after the conference, both here and at the &lt;a href=&quot;http://www.alagad.com/go/blog&quot; target=&quot;_blank&quot;&gt;Alagad blog&lt;/a&gt;. But right now my focus is on wrapping up some tasks so that my time at &lt;a href=&quot;http://cfunited.com/2009/&quot; target=&quot;_blank&quot;&gt;CFUnited&lt;/a&gt; is used to it&apos;s full potential!

I&apos;m presenting on Friday on Introduction to Object-Oriented Modeling and Design. I&apos;ve tweaked the presentation a bit since I gave it last, based partly on the &lt;a href=&quot;http://www.briankotek.com/blog/index.cfm/2009/7/14/ColdFusion-and-OOP--Match-Made-in-Heaven-or-Long-Road-to-Hell&quot;&gt;podcast&lt;/a&gt; that Hal, Ben Nadel and I did a few weeks ago. If you&apos;re interested in what helps make &quot;good&quot; OO design, I hope the presentation will be helpful. Again, let me point out that the presentation isn&apos;t an introduction to OO, I&apos;m assuming attendees already understand what a class is, what an object is, etc. This presentation is talking about OO at a more general level, in terms of how sets of objects actually work together.

My tentative schedule for the conference is attached to this entry, so if you&apos;d like to chat about OO, CF, Flex, Groovy, or just about anything else, feel free to catch up with me. I&apos;ll also most likely be a regular at any evening gatherings at the hotel bar. ;-)

Anyway, I hope to see you this week in DC! Until then!
				
				</description>
				
				
				<category>ColdFusion</category>
				
				<category>OOP CF</category>
				
				<category>Conferences</category>
				
				<category>Presentations</category>
				
				<category>Personal</category>
				
				<pubDate>Mon, 10 Aug 2009 13:07:00 -0700</pubDate>
				<guid>http://www.briankotek.com/blog/index.cfm/2009/8/10/Final-Prep-for-CFUnited</guid>
				
				
			</item>
			
		 	
			
			
			<item>
				<title>ColdFusion and OOP - Match Made in Heaven, or Long Road to Hell?</title>
				<link>http://www.briankotek.com/blog/index.cfm/2009/7/14/ColdFusion-and-OOP--Match-Made-in-Heaven-or-Long-Road-to-Hell</link>
				<description>
				
				Hal Helms, Ben Nadel and I recorded a conversation over the weekend on the subject of OO in CF. I&apos;m supporting the position that OO is still a good thing in CF, Hal disagrees, and Ben is undecided. As you might expect, Hal is left a trembling husk as the weight of my arguments unmercifully crushes him. You know those scenes in superhero movies where someone gets punched so hard they end up in a crater in the ground? It&apos;s like that. Only worse.

In all seriousness though, it was a very fun talk and I think there are some solid points made from all involved, but I&apos;ll let you, gentle reader, be the judge. &lt;a href=&quot;http://epicenter-public.s3.amazonaws.com/ColdFusion-and-OOP--Match-Made-in-Heaven-or-Long-Road-to-Hell.mp3&quot; target=&quot;_blank&quot;&gt;You can download the recording here&lt;/a&gt;.

In the interest of keeping any discussion on this topic from fragmenting, we&apos;ve decided to disable comments on our respective blog entries and instead created a &lt;a href=&quot;http://groups.google.com/group/coldfusionoo&quot; target=&quot;_blank&quot;&gt;Google Group&lt;/a&gt; to act as a central sounding board. Hopefully this isn&apos;t too inconvenient, I realize it&apos;s something of a departure from the norm, but let&apos;s see how that works.

I&apos;m not sure yet whether this will turn into any kind of regular discussion, but I suppose it could. We&apos;ll just have to see what folks think! Thanks.
				
				</description>
				
				
				<category>Development</category>
				
				<category>ColdFusion</category>
				
				<category>OOP CF</category>
				
				<pubDate>Tue, 14 Jul 2009 06:29:00 -0700</pubDate>
				<guid>http://www.briankotek.com/blog/index.cfm/2009/7/14/ColdFusion-and-OOP--Match-Made-in-Heaven-or-Long-Road-to-Hell</guid>
				
				
			</item>
			
		 	
			</channel></rss>