<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>epiphantastic &#187; ColdFusion</title>
	<atom:link href="http://www.epiphantastic.com/category/coldfusion/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.epiphantastic.com</link>
	<description>Just another WordPress weblog</description>
	<lastBuildDate>Wed, 13 Apr 2011 19:20:37 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.1</generator>
		<item>
		<title>Problem Installing ColdFusion 8 on Snow Leopard</title>
		<link>http://www.epiphantastic.com/2011/04/13/problem-installing-coldfusion-8-on-snow-leopard/</link>
		<comments>http://www.epiphantastic.com/2011/04/13/problem-installing-coldfusion-8-on-snow-leopard/#comments</comments>
		<pubDate>Wed, 13 Apr 2011 19:20:37 +0000</pubDate>
		<dc:creator>Thomas</dc:creator>
				<category><![CDATA[ColdFusion]]></category>

		<guid isPermaLink="false">http://www.epiphantastic.com/?p=96</guid>
		<description><![CDATA[I ran into a problem trying to install ColdFusion 8 on my MacBook Pro running Snow Leopard. I honestly don&#8217;t know the what the exact problem is, but from what I can gather, it has to do with Java and the crappy InstallAnywhere installer used for CF 8. To give credit where credit is due, [...]]]></description>
			<content:encoded><![CDATA[<p>I ran into a problem trying to install ColdFusion 8 on my MacBook Pro running Snow Leopard. I honestly don&#8217;t know the what the exact problem is, but from what I can gather, it has to do with Java and the crappy InstallAnywhere installer used for CF 8. To give credit where credit is due, the solution is taken from this site: <a href="http://www.doyourself.org/windows-2/786-install-coldfusion-8-on-snow-leopard/" target="_blank">http://www.doyourself.org/windows-2/786-install-coldfusion-8-on-snow-leopard/</a></p>
<p>The steps are simple:</p>
<ol>
<li>Open a Terminal</li>
<li>cd &#8220;Downloads/ColdFusion Installer 8.app/Contents/Resources/Java&#8221;  (modify to fit the name/path of your installer file)</li>
<li>java -cp ./IAClasses.zip:Execute.zip:installscript.zip:. com.zerog.ia.installer.Main</li>
<li>Installer should launch, just install normally</li>
</ol>
<p>Doing this allowed me to get through the install. I did it with CF 8 64 bit, but I checked an the 32 bit installer wouldn&#8217;t run for me either, so maybe this would work in that case too.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.epiphantastic.com/2011/04/13/problem-installing-coldfusion-8-on-snow-leopard/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Lightwire Tutorial 2: AOP</title>
		<link>http://www.epiphantastic.com/2010/03/15/lightwire-tutorial-2-aop/</link>
		<comments>http://www.epiphantastic.com/2010/03/15/lightwire-tutorial-2-aop/#comments</comments>
		<pubDate>Mon, 15 Mar 2010 14:03:08 +0000</pubDate>
		<dc:creator>Thomas</dc:creator>
				<category><![CDATA[ColdFusion]]></category>

		<guid isPermaLink="false">http://www.epiphantastic.com/?p=82</guid>
		<description><![CDATA[Now that I&#8217;ve gone over the basics of Lightwire as far as creating bean and injecting dependencies go, let&#8217;s get into some Aspect Oriented Programming (AOP). AOP is about addressing the separation of cross-cutting concerns from the main application functionality. Yeah, I know, the first time I read this, it came through as &#8220;blah blah [...]]]></description>
			<content:encoded><![CDATA[<p>Now that I&#8217;ve <a href="http://www.epiphantastic.com/?p=65">gone over the basics of Lightwire as far as creating bean and injecting dependencies</a> go, let&#8217;s get into some <a href="http://en.wikipedia.org/wiki/Aspect-oriented_programming">Aspect Oriented Programming</a> (AOP). AOP is about addressing the separation of cross-cutting concerns from the main application functionality. Yeah, I know, the first time I read this, it came through as &#8220;blah blah blah [jargon here] blah blah blah.&#8221; So to simplify, cross-cutting concern just means some functionality that can apply to many parts of an application. The examples you&#8217;ll likely see over and over for this (and rightly so) are logging and security. Suppose you have a bunch of components/beans and you want to log method calls for several/all the methods in those beans. You could do something like this in a method:</p>
<pre>&lt;!--- Logger.cfc ---&gt;
&lt;cfcomponent&gt;
	&lt;cffunction name="init"&gt;
		&lt;cfreturn this /&gt;
	&lt;/cffunction&gt;

	&lt;cffunction name="log"&gt;
		&lt;cfargument name="txt" type="string"&gt;

		&lt;!--- Some code to write the log text to a file ---&gt;
		.....
	&lt;/cffunction&gt;
&lt;/cfcomponent&gt;

&lt;!--- Controller.cfc ---&gt;
&lt;cfcomponent&gt;
	&lt;cffunction name="init"&gt;
		&lt;cfset variables.Logger = createObject("component", "Logger") /&gt;

		&lt;cfreturn this /&gt;
	&lt;/cffunction&gt;

	&lt;cffunction name="doSomething"&gt;
		&lt;cfset variables.Logger.log("Function doSomething() ran.") /&gt;

		&lt;!--- A bunch of code here doing amazing things! ---&gt;
		.....
	&lt;/cffunction&gt;
&lt;/cfcomponent&gt;
</pre>
<p>Now think of having to do it for 75 beans with an average of 7 methods in each. Are you feeling the pain? Or what if you suddenly needed to apply security to certain parts of a site running on an MVC framework. Imagine your controller:</p>
<pre>&lt;!--- Security.cfc ---&gt;
&lt;cfcomponent&gt;
	&lt;cffunction name="init"&gt;
		&lt;cfset variables.Security = createObject("component", "Security") /&gt;

		&lt;cfreturn this /&gt;
	&lt;/cffunction&gt;

	&lt;cffunction name="hasSuperExtraMegaSecretClearance"&gt;
		&lt;!--- Some code to test if the user is the director of the CIA ---&gt;
		.....
	&lt;/cffunction&gt;
&lt;/cfcomponent&gt;

&lt;!--- Controller.cfc ---&gt;
&lt;cfcomponent&gt;
	&lt;cffunction name="init"&gt;
		&lt;cfreturn this /&gt;
	&lt;/cffunction&gt;

	&lt;cffunction name="uncoverKennedyAssassinationPlot"&gt;
		&lt;cfif variables.Security.hasSuperExtraMegaSecretClearance()&gt;
			&lt;!--- Some code to load all that stuff from the databases at Langley ---&gt;
			.....
		&lt;/cfif&gt;
	&lt;/cffunction&gt;
&lt;/cfcomponent&gt;
</pre>
<p>Now think about adding that cfif for all the methods that pertain to Area 51. Sounds like a great way to lose your sanity. Enter AOP! AOP will allow you to do all these things and avoid that stream of curses that would undoubtedly result from your boss telling you &#8220;Listen Bob, I have this project I need you to work on&#8230;&#8221; For instance, let&#8217;s take a look at the first scenario using Lightwire and AOP. In the code below, assume that the Logger.cfc file is exactly the same as the one above.</p>
<pre>&lt;!--- Controller.cfc ---&gt;
&lt;cfcomponent&gt;
	&lt;cffunction name="init"&gt;
		&lt;cfreturn this /&gt;
	&lt;/cffunction&gt;

	&lt;cffunction name="doSomething"&gt;
		&lt;!--- A bunch of code here doing amazing things! ---&gt;
		.....
	&lt;/cffunction&gt;
&lt;/cfcomponent&gt;

&lt;!--- LogAdvice.cfc ---&gt;
&lt;cfcomponent&gt;
	&lt;cffunction name="init"&gt;
		&lt;cfargument name="Logger" type="any"&gt;

		&lt;cfset variables.Logger = arguments.Logger /&gt;

		&lt;cfreturn this /&gt;
	&lt;/cffunction&gt;

	&lt;cffunction name="before" returntype="string"&gt;
		&lt;cfargument name="method" type="string"&gt;
		&lt;cfargument name="args" type="struct"&gt;
		&lt;cfargument name="target" type="any"&gt;

		&lt;cfset variables.Logger.log("Function #arguments.method#() ran.") /&gt;
	&lt;/cffunction&gt;
&lt;/cfcomponent&gt;

&lt;!--- BeanConfig.cfc ---&gt;
&lt;cfcomponent extends="lightwire.BaseConfigObject" hint="A LightWire configuration bean."&gt;
	&lt;cffunction name="init" output="false" returntype="any" hint="I initialize the config bean."&gt;
		&lt;cfscript&gt;
		// Call the base init() method to set sensible defaults. Do NOT remove this.
		Super.init();

		// OPTIONAL: Set lazy loading: true or false. If true, Singletons will only be created when requested. If false, they will all be created when
		//LightWire is first initialized. Default if you don't set: LazyLoad = true.
		setLazyLoad("false");

		// BEAN DEFINITIONS (see top of bean for instructions)
		addSingleton("cfcPath.Controller");
		addSingleton("cfcPath.Logger");
		addSingleton("cfcPath.LogAdvice");

		// Depency Injection
		addConstructorDependency("LogAdvice", "Logger");

		// AOP Advice
		addBeforeAdvice("Controller", "Logger", "doSomething");
		&lt;/cfscript&gt;

		&lt;cfreturn this /&gt;
	&lt;/cffunction&gt;
&lt;/cfcomponent&gt;
</pre>
<p>As you can see, the logging code has been completely removed from the original Controller.cfc file. The Lightwire config file is fairly straightforward. The Controller bean, Logger bean, and a new LoggerAdvice bean get defined with addSingleton() calls. Once defined, a Before advice is used to tell Lightwire that you want method &#8220;before&#8221; (it&#8217;s the default method for Before advice) from bean &#8220;Logger&#8221; to run before the method &#8220;doSomething&#8221; in bean &#8220;Controller&#8221; when it is called. Simple, right? For this one case, it can seem like overkill, but if you have a lot of logging to do, it&#8217;ll save you a lot of time. Note that if you wanted to log every function call in the Controller bean, you could just put &#8220;*&#8221; as the third argument instead of &#8220;doSomething&#8221;, and you can also ue a comma-delimited list of functions. If there were more beans you needed to do logging for, you would just need to add an addBeforeAdvice() call for that other bean. This may seem like a problem if you have a lot of beans, but thanks to the programmatic nature of the Lightwire configuration, it&#8217;s usually easy to loop through all the CFCs in a directory, add a singleton for each, and add the advice for each. Also, while I think the LoggerAdvice bean is recommended in this case to keep the generic Logger functionality (you may be using it for other things than logging method calls), you could technically only have a Logger bean and define a before() method in it, eliminating the need for the LoggerAdvice.</p>
<p>Now, let&#8217;s move on to the second example. Here&#8217;s how you could implement the security using AOP and an Around advice:</p>
<pre>&lt;!--- Controller.cfc ---&gt;
&lt;cfcomponent&gt;
	&lt;cffunction name="init"&gt;
		&lt;cfreturn this /&gt;
	&lt;/cffunction&gt;

	&lt;cffunction name="uncoverKennedyAssassinationPlot"&gt;
		&lt;!--- Some code to load all that stuff from the databases at Langley ---&gt;
		.....
	&lt;/cffunction&gt;
&lt;/cfcomponent&gt;

&lt;!--- SecurityAdvice.cfc ---&gt;
&lt;cfcomponent&gt;
	&lt;cffunction name="init"&gt;
		&lt;cfargument name="Security" type="any"&gt;

		&lt;cfset variables.Security = arguments.Security /&gt;

		&lt;cfreturn this /&gt;
	&lt;/cffunction&gt;

	&lt;cffunction name="around" returntype="string"&gt;
		&lt;cfargument name="AdviceDispatcher" type="any"&gt;

		&lt;cfif variables.Security.hasSuperExtraMegaSecretClearance()&gt;
			&lt;cfset arguments.AdviceDispatcher.run()&gt;
		&lt;/cfif&gt;
	&lt;/cffunction&gt;
&lt;/cfcomponent&gt;

&lt;!--- BeanConfig.cfc ---&gt;
&lt;cfcomponent extends="lightwire.BaseConfigObject" hint="A LightWire configuration bean."&gt;
	&lt;cffunction name="init" output="false" returntype="any" hint="I initialize the config bean."&gt;
		&lt;cfscript&gt;
		// Call the base init() method to set sensible defaults. Do NOT remove this.
		Super.init();

		// OPTIONAL: Set lazy loading: true or false. If true, Singletons will only be created when requested. If false, they will all be created when
		//LightWire is first initialized. Default if you don't set: LazyLoad = true.
		setLazyLoad("false");

		// BEAN DEFINITIONS (see top of bean for instructions)
		addSingleton("cfcPath.Controller");
		addSingleton("cfcPath.Security");
		addSingleton("cfcPath.SecurityAdvice");

		// Depency Injection
		addConstructorDependency("SecurityAdvice", "Security");

		// AOP Advice
		addAroundAdvice("Controller", "Security", "uncoverKennedyAssassinationPlot");
		&lt;/cfscript&gt;

		&lt;cfreturn this /&gt;
	&lt;/cffunction&gt;
&lt;/cfcomponent&gt;
</pre>
<p>This case is similar to the first, except this time we&#8217;re using an Around advice. Around advice gives you more complete control over method execution, it&#8217;s kind of a Before and After advice rolled into one. The AdviceDispatcher argument it receives allows you to retrieve info about the method and bean that is being advised, as well as control the timing of the execution of the original method. You could even decide, depending on logic, that you don&#8217;t want to execute that method at all. And again, if you need to apply security to many different parts of your app, it&#8217;s easy to use this and apply it to multiple beans/method in a generic way.</p>
<p>As a side note, it&#8217;s worth mentioning that while I use Lightwire because  it&#8217;s the project I&#8217;m contributing to, all this is applicable to  ColdSpring, which offers the same types of advice. The difference is  that you&#8217;d have to define your beans, dependencies, and advices in XML  and if I remember correctly your beans have to extend certain  components. But it&#8217;ll get the same job done. Also, it&#8217;s worth noting that AOP is not yet in the main distribution of Lightwire (<a href="http://www.epiphantastic.com/?p=38">see my previous post on AOP in Lightwire</a>), it&#8217;s only available here until it&#8217;s further vetted. Feel free to <a href="http://www.epiphantastic.com/?page_id=4">download it from the Download section</a> and give it a try. Any feedback is very appreciated.</p>
<p>I hope that from these examples you&#8217;re able to see both the power and convenience that AOP can provide you with, and how to use Lightwire to achieve those results.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.epiphantastic.com/2010/03/15/lightwire-tutorial-2-aop/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Lightwire Tutorial 1: The Basics</title>
		<link>http://www.epiphantastic.com/2010/03/12/lightwire-tutorial-1-the-basics/</link>
		<comments>http://www.epiphantastic.com/2010/03/12/lightwire-tutorial-1-the-basics/#comments</comments>
		<pubDate>Fri, 12 Mar 2010 17:38:09 +0000</pubDate>
		<dc:creator>Thomas</dc:creator>
				<category><![CDATA[ColdFusion]]></category>
		<category><![CDATA[Lightwire]]></category>
		<category><![CDATA[ColdFusion Lightwire]]></category>

		<guid isPermaLink="false">http://www.epiphantastic.com/?p=65</guid>
		<description><![CDATA[Following up on my last post regarding Lightwire Aspect Oriented Programming (AOP), I thought I&#8217;d write up some tutorials to help people get familiaried with Lightwire itself, since I didn&#8217;t see a ton of info around. The harder part is actually getting comfortable with the concepts of dependency injection and AOP. Once you got those [...]]]></description>
			<content:encoded><![CDATA[<p>Following up on my last post regarding Lightwire Aspect Oriented Programming (AOP), I thought I&#8217;d write up some tutorials to help people get familiaried with Lightwire itself, since I didn&#8217;t see a ton of info around. The harder part is actually getting comfortable with the concepts of dependency injection and AOP. Once you got those figured out, Lightwire is stupidly easy to use.</p>
<p>In this post, I&#8217;ll cover the concept of dependency injection and leave AOP for another post. Dependency injection is basically a way to ensure that your code is more loosely coupled. As it turns out, it can also make it a heck of a lot easier to use your objects. As an example, I&#8217;ll use something simple that will hopefully demonstrate the concept well. I&#8217;m going to take a simple service bean (a bean is just a CFC) and a logger bean and show different ways to make them work together. The service bean could do anything, its functionality is irrelevant to this example.</p>
<pre>&lt;!--- Logger.cfc ---&gt;
&lt;cfcomponent&gt;
	&lt;cffunction name="init" returntype="Logger"&gt;
		&lt;cfreturn this /&gt;
	&lt;/cffunction&gt;

	&lt;cffunction name="log" returntype="void"&gt;
		&lt;cfargument name="text" type="string" /&gt;

		&lt;!--- Here there would be some code to log things somewhere (a file, DB, etc.) ---&gt;
		&lt;/cffunction&gt;
	&lt;/cfcomponent&gt;
</pre>
<p>The above illustrates highly coupled components. What&#8217;s wrong with it? Technically speaking, nothing. It won&#8217;t throw errors or anything (unless I screwed up something!) But the two components are tightly coupled. Imagine if you want to change the class you use for logging? In this simple scenario, it&#8217;s pretty simple, all you need to do is change that one call, but what if you have 100 service beans and all of them use the Logger bean? It becomes a bit more painful, right? OK, OK, you could do a Find/Replace in your IDE, but you catch my drift. The other problem is that you will need to manually instantiate the logger bean in every component, which is tedious and violates the DRY principle. Finally, you sometimes want a bean to be a singleton, meaning there&#8217;s only one instance of it for the entire application. You need something to manage that.</p>
<p>Here&#8217;s another way to go about it (the logger component stays the same so I won&#8217;t repeat it here, assume it&#8217;s the same as the one above):</p>
<pre>&lt;!--- Service.cfc ---&gt;
&lt;cfcomponent&gt;
	&lt;cffunction name="init" returntype="Engine"&gt;
		&lt;cfargument name="logger" type="Logger" required="yes" /&gt;

		&lt;cfset variables.logger = arguments.logger /&gt;

		&lt;cfreturn this /&gt;
	&lt;/cffunction&gt;

	&lt;cffunction name="doSomething" returntype="void"&gt;
		&lt;cfset variables.logger.log("Hello world!") /&gt;

		&lt;!--- Perform more actions here, anything ---&gt;
	&lt;/cffunction&gt;
&lt;/cfcomponent&gt;

&lt;!--- ServiceFactory.cfm ---&gt;
&lt;cfcomponent&gt;
	&lt;cffunction name="init" returntype="ServiceFactory"&gt;
		&lt;cfreturn this /&gt;
	&lt;/cffunction&gt;

	&lt;cffunction name="getService" returntype="Service"&gt;
		&lt;cfif NOT structKeyExists(variables, "service")&gt;
			&lt;cfset variables.service = createObject("component", "Service").init( createObject("component", "Logger").init() ) /&gt;
		&lt;/cfif&gt;

		&lt;cfreturn variables.service /&gt;
	&lt;/cffunction&gt;
&lt;/cfcomponent&gt;
</pre>
<p>Using the above, things are a little better. The Service bean receives the Logger bean when created and doesn&#8217;t have to worry about how it gets instantiated. However, you&#8217;re still left with the tedious task of creating the factory, instantiating the Logger manually, etc. Imagine if you wanted the logger to behave similarly. You&#8217;d have to create a factory for it to. And imagine if the logger object had dependencies of its own. You can see how this can get really ugly. That&#8217;s when a dependency framework comes to the rescue. Here&#8217;s how you would do things with lightwire:</p>
<pre>&lt;!--- BeanConfig ---&gt;
&lt;cfcomponent extends="lightwire.BaseConfigObject" hint="A LightWire configuration bean."&gt;

	&lt;cffunction name="init" output="false" returntype="any" hint="I initialize the config bean."&gt;
		&lt;cfset addSingleton("cfcPath.Service", "Service") /&gt;
		&lt;cfset addSingleton("cfcPath.Logger") /&gt;
		&lt;cfset addConstructorDependency("Service", "Logger") /&gt;

		&lt;cfreturn this /&gt;
	&lt;/cffunction&gt;

&lt;/cfcomponent&gt;

&lt;!--- index.cfm ---&gt;
&lt;cfset config = createObject("component","cfcPath.BeanConfig").init() /&gt;
&lt;cfset lightwire = createObject("component","lightwire.LightWire").init(config) /&gt;

&lt;cfset service = lightwire.getBean("Service") /&gt;
</pre>
<p>In the example above, assume that Logger.cfc is the same as the first example and Service.cfc is the same as the second example. With that out of the way, here&#8217;s what&#8217;s happening in the above. In the configuration bean, you&#8217;re giving Lightwire the definition for your beans. The addSingleton() function is used to define a singleton bean, and you could use addTransient() in the same way to define a transient bean. Within that function call, you specify the path of the component in the first argument and the name of the bean as the second. If the name of the bean is the same as the last part of the path, you don&#8217;t need to specify it. You then use the addConstructorDependency() to wire the beans together. The first argument is the bean you want to inject something into, the second is the bean to inject. Then the index.cfm file shows how to start Lightwire and get a bean from it. So the getBean() call basically retrieves a bean based on the configuration above. So behind the scene, something is happening to do createObject(&#8220;component&#8221;, &#8220;cfcPath.Service&#8221;).init(createObject(&#8220;component&#8221;, &#8220;cfcPath.Logger&#8221;).init()); without you having to type all that. Imagine how useful that is when you have tons of beans with lots of dependencies, that are reused in many other beans. Priceless. Note that since we defined the beans as singletons Lightwire will only instantiate them once in its lifetime. So if you store Lightwire in a persistent scope, like the application scope, your beans will only get created once, saving you the overhead of creating them over and over.</p>
<p>There are 3 ways to inject beans in Lightwire. The first is the one described above, using a constructor dependency. In that case, you add an argument to your bean&#8217;s init() function matching the name of the bean to be injected (or you can specify a different name as the third argument of the addConstructorDependency() function). A second way is a setter injection. For a setter injection, you would use addSetterDependency() function. The arguments are the same as for the constructor function, but to get the bean injected you need to define a method in the receiving bean named &#8220;set[BeanName]&#8220;. Finally, there&#8217;s mixin injection. You can add a mixin dependency by using the addMixinDependency() function, which works exactly like the other two, the difference is you don&#8217;t need to do anything in the receiving bean. The injection will be done behind the scenes and you don&#8217;t have to worry about a thing.</p>
<p>How do you know which injection type to use? It really depends. If you have two beans that both depend on each other, you can&#8217;t use constructor dependency, otherwise you&#8217;ll run into a circular reference problem. So you can use setter or mixin dependencies in those cases. If you need to use the injected bean in the init() method of the receiving bean, you&#8217;ll probably want to use constructor injection. Then it&#8217;s down to preference. Some people don&#8217;t like mixin injection because they feel it hides part of the implementation and can be confusing to an outsider looking at your application. But I find it invaluable, saves me from adding all those constructor arguments or setter methods. When I have a bean I want to inject pretty much everywhere (like a Utility bean, for example), I usually use mixin injection.</p>
<p>You can also inject regular properties using addConstructorProperty(), addSetterProperty(), and addMixinProperty(). All those take 3 arguments, the name of the bean, the name of the property, and the value of the property.</p>
<p>So this ought to cover the basics of DI and how to use Lightwire for that purpose. Stay tuned for a post on Lightwire and AOP (I&#8217;ve already done one, but I&#8217;m gonna try to make one that&#8217;s actually clear!)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.epiphantastic.com/2010/03/12/lightwire-tutorial-1-the-basics/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Aspect Oriented Programming (AOP) with Lightwire</title>
		<link>http://www.epiphantastic.com/2010/03/12/aspect-oriented-programming-aop-with-lightwire/</link>
		<comments>http://www.epiphantastic.com/2010/03/12/aspect-oriented-programming-aop-with-lightwire/#comments</comments>
		<pubDate>Fri, 12 Mar 2010 06:02:29 +0000</pubDate>
		<dc:creator>Thomas</dc:creator>
				<category><![CDATA[ColdFusion]]></category>
		<category><![CDATA[Lightwire]]></category>
		<category><![CDATA[AOP]]></category>

		<guid isPermaLink="false">http://www.epiphantastic.com/?p=38</guid>
		<description><![CDATA[I&#8217;m a big fan of Peter Bell&#8217;s Lightwire framework. I&#8217;ve been using it for quite a while for dependency injection and I love it. However, it&#8217;s been lacking a key feature that ColdSpring has: Aspect Oriented Programming (AOP). No more. I&#8217;ve taken some time to add some AOP magic to Lightwire and although I haven&#8217;t [...]]]></description>
			<content:encoded><![CDATA[<p>
I&#8217;m a big fan of <a href="http://appgen.pbell.com/">Peter Bell&#8217;s</a> <a href="http://lightwire.riaforge.org/">Lightwire</a> framework. I&#8217;ve been using it for quite a while for dependency injection and I love it. However, it&#8217;s been lacking a key feature that <a href="http://www.coldspringframework.org/">ColdSpring</a> has: Aspect Oriented Programming (AOP). No more. I&#8217;ve taken some time to add some AOP magic to Lightwire and although I haven&#8217;t been able to test much yet, it&#8217;s looking pretty good so far.
</p>
<p>
First things first, I gotta give much credit to the developers of ColdSpring. My implementation was very much inspired by their work and made it that much easier to get things done. For users of ColdSpring, things will look rather familiar, I&#8217;ve implemented Before, After, Around, and Exception advices in Lightwire, all of which are supported by ColdSprings, albeit some with slightly different names.
</p>
<p>
For users of Lightwire, AOP is implemented with the same simplicity as the rest of the framework and is a breeze to use. Advices are defined in the configuration bean in a similar way as beans. There is a method for each type of advice: addBeforeAdvice(), addAfterAdvice(), addAroundAdvice(), and addExceptionAdvice(). The arguments for these four methods are the same, so I&#8217;m just going to show addBeforeAdvice():
</p>
<pre>
addBeforeAdvice(
	beanName,	// The name of a Lightwire bean that you want to give advice to
	adviceBeanName,	// The name of a Lightwire bean that provides advice
	[methods],	// Optional, methods that the advice applies to; defaults to *, which means all, can be a comma delimited list of method names
	[adviceMethod]	// Optional, name of the advice method, which defaults to the advice type (before, after, around, or exception) if not specified
);
</pre>
<p>
Note that neither of the beans specified above need to extend anything. They can be any bean, any class, extending anything else you want. Now, let&#8217;s take a look at what parameters the advice bean methods should receive. Note that I&#8217;m going to use the default method names, but you can set the advice method to whatever you want using the optional adviceMethod argument.
</p>
<pre>
before(
	method,	// The method that triggered the advice
	args,	// The arguments passed into the method (struct)
	target	// The bean that contains the method that triggered the advice
);

after(
	method,		// The method that triggered the advice
	args,		// The arguments passed into the method (struct)
	target,		// The bean that contains the method that triggered the advice
	[returnVal]	// Will return a value if the triggering function returned something
);

around(
	AdviceDispatcher // An AdviceDispatcher object, which will be further discussed below
);

exception(
	method,	// The method that triggered the advice
	args,	// The arguments passed into the method (struct)
	target,	// The bean that contains the method that triggered the advice
	error	// The cfcatch struct for the error
);
</pre>
<p>
While you are not required to define the arguments (you might not need one or more), if you do define them be sure to spell them right because they are passed as named arguments, not numbered.
</p>
<p>
Now, the around() method is special because it receives a single object, AdviceDispatcher, which is essentially the same as the MethodInvocation object in ColdSpring. This object gives you full control over what will happen with your method call. Within your around device, you can trigger the target method execution by calling the run() method of the AdviceDispatcher object. Beyond that, you can put any code you want around it, to define code to run before and after. Your code can also make it so the method will not run in certain situations, all you have to do is create a situation where the AdviceDispatcher.run() method does not run. Here is the definition of the AdviceDispatcher object:
</p>
<pre>
lighwire.aop.AdviceDispatcher
METHOD		RETURN TYPE	DESCRIPTION
run()		void		Executes the target method
getTarget()	object		Returns the target bean object
getMethod()	string		The name of the target method
getArguments()	struct		The arguments passed to the target method
</pre>
<p>
That&#8217;s it! This is pretty much all you need to know to do AOP with Lightwire. Now I do realize that this article assumes prior knowledge of Lightwire and AOP, so I&#8217;m hoping to blog some tutorials on both of those topics to make things clearer for those just getting started with those.
</p>
<p>
I&#8217;ve been talking with Peter Bell and if my changes prove to be any good, which I hope they will, they could eventually make it into the core product on riaforge. For now, you can download my modified Lightwire by clicking the link at the bottom. I&#8217;ve included an aopSample folder where you can see some tests. They&#8217;re not the best and just output text, but it&#8217;s better than nothing for now. You can unzip the folder in your webroot, or you can unzip it anywhere on your web server and modify the component paths in the aopSample/index.cfm file. I&#8217;ve been testing this on CF 8, IIS, so if you run into problems and are running on a different platform let me know so I can get them sorted out.
</p>
<p>
<a href="http://www.epiphantastic.com/projects/lightwireAOP.zip">DOWNLOAD LIGHTWIRE WITH AOP<a/></p>
]]></content:encoded>
			<wfw:commentRss>http://www.epiphantastic.com/2010/03/12/aspect-oriented-programming-aop-with-lightwire/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Arbitrary runtime constructor dependencies in Lightwire</title>
		<link>http://www.epiphantastic.com/2010/03/06/arbitrary-runtime-constructor-dependencies-in-lightwire/</link>
		<comments>http://www.epiphantastic.com/2010/03/06/arbitrary-runtime-constructor-dependencies-in-lightwire/#comments</comments>
		<pubDate>Sat, 06 Mar 2010 14:47:28 +0000</pubDate>
		<dc:creator>Thomas</dc:creator>
				<category><![CDATA[ColdFusion]]></category>
		<category><![CDATA[Lightwire]]></category>
		<category><![CDATA[ColdFusion Lightwire]]></category>

		<guid isPermaLink="false">http://www.epiphantastic.com/?p=27</guid>
		<description><![CDATA[I love Lightwire for dependency injection, it&#8217;s lightweight, it&#8217;s not XML based, and allows for mixins which saves me from having to constantly add constructor properties or setters. However, I was recently confronted with a problem. When using Lightwire for transient beans, I often found myself wanting to inject dependencies, but also pass in some [...]]]></description>
			<content:encoded><![CDATA[<p>
I love <a href="http://lightwire.riaforge.org/">Lightwire</a> for dependency injection, it&#8217;s lightweight, it&#8217;s not XML based, and allows for mixins which saves me from having to constantly add constructor properties or setters. However, I was recently confronted with a problem. When using Lightwire for transient beans, I often found myself wanting to inject dependencies, but also pass in some properties/dependencies at runtime (for example, some data somebody entered in a form). Now, an obvious way to do this would be to define the bean without that dependency, create a setter for it, and then add whatever you need to the bean using that. Somehow, it felt like kind of a roundabout way of doing it, so I figured I&#8217;d look for a way to be able to do it at the time of bean invocation. In terms of code, here&#8217;s what I was looking for:</p>
<pre>
myBean = application.lightwire.getBean("myBean", form.runTimeData, form.moreData);
</pre>
<p>INSTEAD OF</p>
<pre>
myBean = application.lightwire.getBean("myBean");
myBean.setRuntimeData(form.runTimeData);
myBean.setMoreData(form.moreData);
</pre>
</p>
<p>
Note that you could also do the above with one setter that would set all the runtime data you want at once. Still, it&#8217;s an extra call, and that just bothers me to no end! So after some modifications to the Lightwire code I was almost able to do what I wanted, with a small caveat. I wasn&#8217;t able to use numbered arguments, had to settle for named arguments for now (though I&#8217;m still working on it). So right now I&#8217;m able to do this:</p>
<pre>
myBean = application.lightwire.getBean(
	objectName="myBean",
	runTimeData=form.runTimeData,
	moreData=form.moreData
);
</pre>
</p>
<p>
I&#8217;m not 100% happy with it because I&#8217;d like to get it working with numbered argument and avoid all that typing, but the arguments/argumentCollection object is a weird one and I haven&#8217;t been able to swing that yet. Hoping I&#8217;ll come up with some sort of solution eventually (if anybody has some insights in the Java internals of argumentCollection and how to manipulate that, I&#8217;m all ears). But for now this works for me.
</p>
<p>
I&#8217;m interested in knowing if anybody else would find this feature useful, or if for any reason this would be bad practice and maybe I&#8217;m going about things all wrong. Again, I know it&#8217;s kind of a small nitpicky thing, but when you&#8217;re coding all day, small details make a big difference!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.epiphantastic.com/2010/03/06/arbitrary-runtime-constructor-dependencies-in-lightwire/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Making ColdFusion report fields stretch without messing everything up</title>
		<link>http://www.epiphantastic.com/2007/04/24/making-coldfusion-report-fields-stretch-without-messing-everything-up/</link>
		<comments>http://www.epiphantastic.com/2007/04/24/making-coldfusion-report-fields-stretch-without-messing-everything-up/#comments</comments>
		<pubDate>Tue, 24 Apr 2007 18:08:21 +0000</pubDate>
		<dc:creator>Thomas</dc:creator>
				<category><![CDATA[ColdFusion]]></category>

		<guid isPermaLink="false">http://www.epiphantastic.com/?p=24</guid>
		<description><![CDATA[The ColdFusion Report Builder was a welcome addition to CF, allowing for report generation without using third-party software like Crystal Reports. The problem with it is that documentation and examples are sparse. And the CFREPORT site doesn&#8217;t seem to have a lot of activity lately (in all fairness, I did not contact the site owner, [...]]]></description>
			<content:encoded><![CDATA[<p>
The ColdFusion Report Builder was a welcome addition to CF, allowing for report generation without using third-party software like Crystal Reports. The problem with it is that documentation and examples are sparse. And the <a href="http://www.cfreport.org">CFREPORT site</a> doesn&#8217;t seem to have a lot of activity lately (in all fairness, I did not contact the site owner, maybe he&#8217;d have a solution for me). Granted, it&#8217;s not really that complicated to pick up, but there are some cases that leave you scratching your head. I recently ran into one such case.
</p>
<p>
Basically, the report builder allows you to put some fields on your report and you can make them a certain size. But what if you have text of variable size and you&#8217;re not sure how long it&#8217;ll be? No problem, you can just set it to whatever width you want and then set the &#8220;Stretch With Overflow&#8221; field to true. That way when the text is too long to fit within the pre-defined width it&#8217;ll wrap to the next line. That&#8217;ll solve all your problems, right? Nope&#8230;
</p>
<p>
This solution will work if your report is a simple table, with a single row of fields put one next to the other. If you have a field that requires more space, the text will wrap and push down thenext record. But what if you have something like the following?
</p>
<p>
<a href="images/report1.jpg" target="_blank"><img src="images/report1.jpg" width="450" height="193" /></a>
</p>
<p>
Suppose the Office field got long and you set its &#8220;Stretch With Overflow&#8221; property to true, guess what would happen? Yeah, the text would wrap alright, but it wouldn&#8217;t push the stuff below it down, instead it would overlap it, and that&#8217;s obviously not good. I searched around and didn&#8217;t really find an answer to my problem. So either I didn&#8217;t search enough and wasted my time with a hack when there&#8217;s a built-in solution, or else I&#8217;m very clever and came up with a brilliant hack. I hope the latter is true!
</p>
<p>
I figured the way to make things stretch properly would be to put things in different bands. But you can&#8217;t randomly insert bands. So to get an extra band, we need a hack. I did it using groups. Basically, whenever you add a group you get a new band for that group. So my idea was to add groups on a field that is unique. That way you get extra bands but they actually aren&#8217;t grouping anything. I just used the primary key of my records as the group by field. And to be able to get more bands, I modified my query and to something like this:</p>
<pre>
SELECT
	JournalID,
	JournalID AS StretchHack1,
	JournalID AS StretchHack2,
	...
FROM Journals
</pre>
</p>
<p>
Then you go under &#8220;Report > Group Management&#8221; and use those fields for Groups. You can put in as many groups as you need bands and then break down your fields/labels into the different bands. Here&#8217;s the result for my example:
</p>
<p>
<a href="images/report2.jpg" target="_blank"><img src="images/report2.jpg" width="450" height="203" /></a>
</p>
<p>
I set the &#8220;Stretch With Overflow&#8221; property to true for Office, Contacts, Categories, and text. Because they are all in separate bands, if their content is too long to fit on one line it&#8217;ll wrap to the next line and push down the content below. Neat huh?
</p>
<p>
I&#8217;m sure this is not a bulletproof solution and there are certain types of layouts where this might either not work or be a real pain in the ass to use. But I think it should come in handy in cases resembling the one I illustrated above.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.epiphantastic.com/2007/04/24/making-coldfusion-report-fields-stretch-without-messing-everything-up/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>JSON schemas/validation with CFJSON</title>
		<link>http://www.epiphantastic.com/2007/03/25/json-schemas-and-validation-with-cfjson/</link>
		<comments>http://www.epiphantastic.com/2007/03/25/json-schemas-and-validation-with-cfjson/#comments</comments>
		<pubDate>Sun, 25 Mar 2007 22:12:00 +0000</pubDate>
		<dc:creator>Thomas</dc:creator>
				<category><![CDATA[CFJSON]]></category>
		<category><![CDATA[ColdFusion]]></category>

		<guid isPermaLink="false">http://www.epiphantastic.com/?p=22</guid>
		<description><![CDATA[I&#8217;ve made it no secret that I&#8217;m not a fan of XML. However, one of the advantages of XML that is constantly brought up is the ability to validate XML documentes using an XML Schema or DTD. I haven&#8217;t had much use for them myself, but seeing as many people consider this important, I figured [...]]]></description>
			<content:encoded><![CDATA[<p>
I&#8217;ve made it no secret that I&#8217;m not a fan of XML. However, one of the advantages of XML that is constantly brought up is the ability to validate XML documentes using an XML Schema or DTD. I haven&#8217;t had much use for them myself, but seeing as many people consider this important, I figured there was no reason the same couldn&#8217;t be done in JSON. So I came up with a format for a JSON schema file (written in JSON, of course) and added a function to the <a href="cfjson/">CFJSON library</a> to validate a JSON document based on a schema.
</p>
<p>
While I don&#8217;t have docs written for this, it&#8217;s pretty self-explanatory. Here&#8217;s an example of a schema that shows pretty much all the features I&#8217;ve put in it so far:</p>
<pre>
{
   type: "struct",
   keys: ["title","body","categories","start_date","active"],
   items: {
      title: {
         type: "string", maxlength: 20, minlength: 8
      },
      body: {
         type: "string", minlength: 1
      },
      categories: {
         type: "array",
         minlength: 1,
         maxlength: 4,
         items: {
            type: "struct",
            items: {
               id: {
                  type: "number", min:6, max:10
               },
               name: {
                  type: "string"
               }
            }
         }
      },
      start_date: {
         type: "date", mask: "mm-dd-yyyy"
      },
      active: {
         type: "boolean"
      }
   }
}
</pre>
</p>
<p>
In a nutshell, your schema is always an object/struct and it must always have a &#8220;type&#8221; key set. Then you go on nesting more definitions under the &#8220;items&#8221; key if you have more complex data types like structs or arrays. The valid types right now are &#8220;struct&#8221;, &#8220;array&#8221;, &#8220;date&#8221;, &#8220;number&#8221;, &#8220;boolean&#8221;, and &#8220;string&#8221;. Each of these data types have some additional options, which are explained below.
</p>
<p>
<strong>struct</strong><br />
For a type &#8220;struct, you have two additional keys you can add. The first is &#8220;keys&#8221;, in which you can provide an array of the keys that this structure MUST have. The second is &#8220;items&#8221;, which is a structure with keys for each structure key you want to add validation rules for. The &#8220;keys&#8221; and &#8220;items&#8221; values are both optional. You can specify an array of keys without providing &#8220;items&#8221; and vice-versa.
</p>
<p>
<strong>array</strong><br />
An &#8220;array&#8221; type can take 3 additional parameters, &#8220;minlength&#8221;, &#8220;maxlength&#8221;, and &#8220;items&#8221;. The first two are pretty self-explanatory, they check for a certain array length. The last is similar to the &#8220;struct&#8221; type&#8217;s &#8220;items&#8221; key, except inside that structure you do not list validation individually for keys since arrays are just numeric. So you simply put in the structure you want for all the items in the array.
</p>
<p>
<strong>date</strong><br />
The only option for the &#8220;date&#8221; struck type is &#8220;mask&#8221;. In it you can specify a date mask that you want the date to conform to. The possible masks are the same as the ones used by ColdFusion&#8217;s DateFormat function, although this could change because JSON is a universal format not restricted to CF.
</p>
<p>
<strong>number</strong><br />
A &#8220;number&#8221; type provides additional options of &#8220;min&#8221; and &#8220;max&#8221;, which allows you to specify minimum and maximum values for a number. Note that right now the &#8220;number&#8221; type allows for floats too, this will eventually be updated to allow for validating for integers, floats, unsigned numbers, etc.
</p>
<p>
<strong>boolean</strong><br />
The boolean type has no additonal options, although eventually it&#8217;ll probably allow for choosing what can be considered a valid boolean.
</p>
<p>
<strong>string</strong><br />
The &#8220;string&#8221; type can specify a &#8220;maxlength&#8221; and &#8220;minlength&#8221; option that will make sure the string is not longer or shorter than the values specified. Note that the &#8220;string&#8221; type will actually accept booleans and numbers. Right now I&#8217;m not seeing a way around it given the way I implemented things, and I&#8217;m not sure it&#8217;s really a big deal.
</p>
<p>
After defining the JSON schema standard I added a validate() function to CFJSON that validates a JSON document based on a schema conforming to the format described above. I also made a small example, creating a JSON document that conforms to the schema above and running the validate function against it. There&#8217;s a link to download the example below, all you have to do is change some values in the document or in the schema to see the validation working. There are a few more options that are probably easy to figure out looking at the code, such as the &#8220;errorVar&#8221; and &#8220;stopOnError&#8221; arguments. If anybody has any feedback on this I&#8217;d love to hear it.
</p>
<p>
<a href="cfjson/downloads/schema_example.zip">DOWNLOAD CFJSON DOCUMENT VALIDATION EXAMPLE (includes the latest CFJSON)</a><br />
<a href="cfjson/">FIND OUT MORE ABOUT CFJSON</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.epiphantastic.com/2007/03/25/json-schemas-and-validation-with-cfjson/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Suppressing whitespace in ColdFusion</title>
		<link>http://www.epiphantastic.com/2007/03/16/suppressing-whitespace-in-coldfusion/</link>
		<comments>http://www.epiphantastic.com/2007/03/16/suppressing-whitespace-in-coldfusion/#comments</comments>
		<pubDate>Sat, 17 Mar 2007 01:10:01 +0000</pubDate>
		<dc:creator>Thomas</dc:creator>
				<category><![CDATA[ColdFusion]]></category>

		<guid isPermaLink="false">http://www.epiphantastic.com/?p=20</guid>
		<description><![CDATA[One of the things about ColdFusion that I don&#8217;t like so much is its inability to conveniently suppress whitespace. It&#8217;s ridiculous, there are like 3 million tags/attributes/options that are related to whitespace, I seem to discover a new one all the time and it invariably fails to do what I want. First, there&#8217;s &#60;cfsilent&#62;. The [...]]]></description>
			<content:encoded><![CDATA[<p>
One of the things about ColdFusion that I don&#8217;t like so much is its inability to conveniently suppress whitespace. It&#8217;s ridiculous, there are like 3 million tags/attributes/options that are related to whitespace, I seem to discover a new one all the time and it invariably fails to do what I want. First, there&#8217;s &lt;cfsilent&gt;. The result is pretty straightforward, it kills all output found in between it. Then there&#8217;s &lt;cfsetting enablecfoutputonly=&#8221;Yes&#8221;&gt;. That supposedly suppresses things that aren&#8217;t inside of &lt;cfoutput&gt; tags, but my experience has shown that it doesn&#8217;t pick up everything. Then there&#8217;s &lt;cfprocessingdirective suppresswhitespace=&#8221;Yes&#8221;&gt;, which I never use, but I tried it recently for something and it was useless. Plus from what I read it&#8217;s the worse performance-wise.
</p>
<p>
Besides the tags, you can set output=&#8221;no&#8221; on both your &lt;cfcomponent&gt; and &lt;cffunction&gt; tags, and it&#8217;s often necessary to do so. Finally, there&#8217;s an option in the Settings section of the CF Administrator that you can use to let CF manage whitespace suppression.
</p>
<p>
So I had a whitespace problem the other day and I was trying to get rid of it by all means necessary. I have all these options right? Something&#8217;s gonna work, right? Wrong! None of these things did it for me. I had a function in a component that you pass some arguments to and it outputs a &lt;select&gt; field populated with &lt;option&gt; tags. So I was calling the function something like this</p>
<pre>
&lt;cfsetting enablecfoutputonly="yes" /&gt;

&lt;cfoutput&gt;Label: #selectBox(options)#&lt;/cfoutput&gt;

&lt;cfsetting enablecfoutputonly="no" /&gt;
</pre>
<p>This was part of a larger framework, but everything was wrapped in a &lt;cfsetting enablecfoutputonly=&#8221;Yes&#8221;&gt; and all components and functions had output=&#8221;no&#8221; where possible. I was really starting to get pissed when I had one of my Einstein moments. I took the code out of the &lt;cfoutput&gt; and changed it to the following and all was well:</p>
<pre>
&lt;cfsetting enablecfoutputonly="yes" /&gt;

&lt;cfoutput&gt;Label: &lt;/cfoutput&gt;&lt;cfset selectBox(options) /&gt;

&lt;cfsetting enablecfoutputonly="no" /&gt;
</pre>
<p>Presto! Like magic it worked. I&#8217;m glad I found a workaround, but I still think it&#8217;s pathetic that CF can&#8217;t handle this for me.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.epiphantastic.com/2007/03/16/suppressing-whitespace-in-coldfusion/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>CFJSON version 1.7</title>
		<link>http://www.epiphantastic.com/2007/03/02/cfjson-version-17/</link>
		<comments>http://www.epiphantastic.com/2007/03/02/cfjson-version-17/#comments</comments>
		<pubDate>Sat, 03 Mar 2007 00:50:59 +0000</pubDate>
		<dc:creator>Thomas</dc:creator>
				<category><![CDATA[CFJSON]]></category>
		<category><![CDATA[ColdFusion]]></category>

		<guid isPermaLink="false">http://www.epiphantastic.com/?p=19</guid>
		<description><![CDATA[Today I had some free time and decided to implement some bug fixes for CFJSON. Many thanks to Larry Reinhard who not only provided many fixes but actually built a unit test for them. Wow! That makes my work that much easier! Steve Nelson also contributed and I thank him for that. After implementing Larry&#8217;s [...]]]></description>
			<content:encoded><![CDATA[<p>
Today I had some free time and decided to implement some bug fixes for CFJSON. Many thanks to Larry Reinhard who not only provided many fixes but actually built a unit test for them. Wow! That makes my work that much easier! Steve Nelson also contributed and I thank him for that.
</p>
<p>
After implementing Larry&#8217;s changes I so happened to read a post on <a href="http://www.bennadel.com">Ben Nadel&#8217;s blog</a> about a problem with a JSON string that had a carriage return. This incited me to go and check if special characters were properly handled, and I discovered that while they were as far as encoding, the decoding was not correct. In the process of fixing this I discovered a serious bug that caused errors when there was one double-quote in a string within a complex data type. I tracked it down to an inexplicable problem with a loop, whereby I incremented the loop&#8217;s index value to essentially skip an iteration, but for whatever reason on the next iteration the value of the index was reset to the original value it would have had if I hadn&#8217;t incremented it. Mystery&#8230; I just changed the loop to a conditional loop where I incremented values myself and that solved my problem.
</p>
<p>
So given the bugs mentioned above, this version of CFJSON is a must download. Hopefully there won&#8217;t be too many serious problems from now on, the transition from one owner to the next and implementation of accumulated code/bug fixes/features made it so some unpleasant stuff crept in, but it&#8217;s looking under control now. Thanks again to all the contributors!
</p>
<p>
<a href="http://www.epiphantastic.com/cfjson/downloads/cfjson-1.7.zip">DOWNLOAD CFJSON v1.7</a><br />
<a href="http://www.epiphantastic.com/cfjson/">GO TO THE CFJSON SITE</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.epiphantastic.com/2007/03/02/cfjson-version-17/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Getting familiar with ColdFusion frameworks</title>
		<link>http://www.epiphantastic.com/2007/03/01/getting-familiar-with-coldfusion-frameworks/</link>
		<comments>http://www.epiphantastic.com/2007/03/01/getting-familiar-with-coldfusion-frameworks/#comments</comments>
		<pubDate>Thu, 01 Mar 2007 13:22:46 +0000</pubDate>
		<dc:creator>Thomas</dc:creator>
				<category><![CDATA[ColdFusion]]></category>

		<guid isPermaLink="false">http://www.epiphantastic.com/?p=18</guid>
		<description><![CDATA[I recently had a look at two of the most popular ColdFusion frameworks, Mach-II and Model-Glue. And since I got the latest Model-Glue, the Unity release (still in beta), I was also exposed to ColdSpring and Reactor. It was long-overdue on my part to have a look at those. I can&#8217;t say I&#8217;ve gone in-depth [...]]]></description>
			<content:encoded><![CDATA[<p>
I recently had a look at two of the most popular ColdFusion frameworks, Mach-II and Model-Glue. And since I got the latest Model-Glue, the Unity release (still in beta), I was also exposed to ColdSpring and Reactor. It was long-overdue on my part to have a look at those. I can&#8217;t say I&#8217;ve gone in-depth into each one of them, but I understand the basic principles and could write a simple app/site using those frameworks. The question is, would I want to? I&#8217;m actually a big fan of frameworks/APIs/Libraries because they allow you to concentrate on your specific problem while providing you with a context in which to solve it, along with an intelligent way of organizing your code. That&#8217;s wonderful. But it&#8217;s becoming clear to me that there&#8217;s no right way of doing this and what works for/appeals to somebody doesn&#8217;t necessarily work for somebody else.
</p>
<p>
Both Mach-II and Model-Glue don&#8217;t really turn me on, at least not at first glance. Maybe I have to let them grow on me. Right from the beginning, at the very core of them, there&#8217;s XML. I can&#8217;t stand XML, I just can&#8217;t help it. In both Mach-II and Model-Glue, there&#8217;s a considerable amount of stuff that gets set up in XML files, they&#8217;re a fundamental part of the frameworks, unfortunately for me. Essentially, you define events that broadcast messages heard by listeners that provoke some action to be taken, and possibly generating output to the screen. In essence, I like the principle, I guess I may just not like the implemementation.
</p>
<p>
So that I don&#8217;t come accross as a total framework hater, I have to say that I&#8217;m quite a fan of Ruby on Rails. I think the way they go about it is more intuitive to me, I think their approach of using a lot of naming conventions helps minimize the amount of configuration needed. Just follow the conventions and things get magically connected and meshed in the background. I like that. On the ColdFusion end of things, from my (very) limited experience with it, I&#8217;d say that I also like Reactor as a framework, although we&#8217;re talking about totally different kind of framework here.
</p>
<p>
Bottomline, I think I may have to come up with a real project to get a better feel for the existing ColdFusion frameworks. In my case I&#8217;d go with Model-Glue:Unity, with Reactor plugged in. That way I get the benefit of testing 3 frameworks at once. And I could also take the opportunity to throw YUI and YUI-Ext into the mix to get my javascript groove on. I don&#8217;t know where I&#8217;ll find the time, but hopefully I can sneak in a few minutes here and there for the sake of knowledge.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.epiphantastic.com/2007/03/01/getting-familiar-with-coldfusion-frameworks/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

