Notes: What’s New in ColdFusion 9

These are notes from Adobe MAX 2009. The talk was given by Adam Lehman.

First, ColdFusion 9 also introduces the new ColdFusion Builder product, an Eclipse-based IDE “to rule them all”. Because it is based on Eclipse, you can also combine other products, like Flash Builder, so that one IDE gets the job done for everything, whether it is HTML, CFML, JS, Flex, ActionScript, CSS, etc.

ColdFusion Builder also supports some interesting server integration features. You can access ColdFusion Administrator and other functionality right from ColdFusion Builder; you can see and browse all of the databases that ColdFusion has datasources for. With such functionality, you can do cool stuff like auto-generate ORM-based CFCs by pointing it to an existing database table! Now, it doesn’t generate just the bean CFC. It generates the entire service layer: DAO and Gateway beans as well!! Now, this obviously is just a starter step. It’s expected that you’d tweak it from that point. With the Flash Builder integration, you can take this to the next step by also generating ActionScript objects to help with Flex integration as well.

CFML Enhancements

Well, in CF7, they introduced Application.cfc that supported hooks for application events. But now in CF9, there is a Server.cfc with an onServerStart() method for handling that event.

Various other holes have been filled. You can now have nested CFTRANSACTION tags. Error catching now supports “finally”. And looping now supports CFCONTINUE.

Variable level enhancements: You can now pass implicit structures/arrays to tags and functions. Before you had to assign it to a var and then pass it. There is assignment chaining (a=b=c). Direct access to elements of returned arrays (i.e. myFunction()[x] couldn’t be done previously). And, finally, ternary operators! For instance, you can do something like: a = (b<c)?b:c

CFSCRIPT enhancements. Starting in CF9, you can now write 100% script-based code, including classes/components.

CFC enhancements. There is now an explicit LOCAL scope. Instead of doing var myvar=1, you can do LOCAL.myvar=1. What’s more, you can declare a variable with var anywhere in the code, not just at the top. CFCs also support implicit getters/setters by using the CFPROPERTY tag. These are worth using if there is no special handling going on, because they’re 7x faster than your own getters/setters.

Here’s an awesome feature. You no longer have to use CreateObject() to create a CFC. You can use the IMPORT keyword to point to a directory of CFCs and have them be first-class citizens in your code. And you can use the NEW keyword to create CFCs, like user = new User(). Looking more Java-like all the time.

How to convince your boss to upgrade

First, with CFIMAP, you can now access email with IMAP support, such as GMail.

There are many PDF support enhancements. Create PDF packages, add/remove headers and footers, optimize PDFs (down-sample images, for instance), extract text/images, high-quality thumbnails, convert Word documents to PDF.

There are presentation options. The CFPRESENTATION tag will generate PPT files from CFML/HTML content. And you can go the other way: Convert PPT to HTML or Flash. Supports Microsoft PowerPoint ’97 to ’08 and Open Office Presentations.

Spreadsheet support. The CFSPREADSHEET helps you create, read, and merge native Excel spreadsheets. This isn’t just a CSV file. This is a real Excel spreadsheet with formulas and formatting support.

SharePoint integration. Native access to SharePoint data and services (Sites, templates, sub-sites, web parts, and workspaces). You can get lists including data, views, and alerts and querying against lists. Users, permissions, site groups, cross-site groups, security groups, and distribution groups. Build web parts with CFML. Integrate with SharePoint Single sign-on. You may wonder, “Why is this necessary since SharePoint has web services and exposes information as XML?” Because it’s painful. ColdFusion makes it significantly easier and faster.

ColdFusion Server Manager. A Flex-based AIR application that helps you manage multiple ColdFusion servers. And it receives system notifications and alerts. Helps apply settings for multiple servers.

The next generation of applications

Coldfusion 9 ORM functionality. Powered by the Java Hibernate framework, so it is industry standard. Various ormXXX() and entityXXX() functions provide this functionality for you. With this feature, no more SQL is necessary, so apps can be developed faster (and potentially with fewer errors). CFCs will just be automagically saved. But it’s not just a matter of saving time on development; it also makes it so that your app is no longer database-dependent. It can point to any database server and it should just work.

Enhanced caching. ColdFusion is already pretty optimized for speed (esp. between CF7 to CF8). So to get more speed, developers need to use these new caching features. Using cacheGet(), cachePut(), and cacheGetMetaData(), you can save/retrieve objects from a built-in cache. Page fragment caching allows you to have a combination of static and dynamic content on a page. This provides a HUGE performance boost, depending on what you’re doing. For instance, you only want to generate a menu dynamically the first time, but then another area of the page is dynamic every time.

Performance gains. Okay, Adam lied. ColdFusion 9 is actually 40% faster than ColdFusion 8, with no changes to code, just upgrading ColdFusion. CFC creation is 8x faster, method invocation is 3x faster. And UUID creation is 100x faster. These are some huge bottlenecks that have been blown away. There is a performance brief that Adobe will be releasing on ColdFusion 9 in the near future.

Search engine. ColdFusion 9 now includes Apache Solr. Verity is still included, but so is Solr, which is actually even faster than Verity. So you may choose to upgrade to Solr! They even provide a Verity-to-Solr migration utility.

ColdFusion Server API. You can have direct access to ColdFusion services for CFCHART, CFDOCUMENT, CFPDF, CFIMAGE, and more. This makes it even easier to access ColdFusion mail/pdf/images services directly within Flex without having to custom code some ColdFusion code.

What’s more, Flash Remoting is 9x faster. It may arguably be the fastest flash remoting server-side technology around.

There are various JavaScript/Ajax tags, like CFMAP for Google Maps, CFMESSAGEBOX, CFSLIDER, and more. Ajax functionality in CF is powered by ExtJS 3.0 (which is nice, because ExtJS isn’t free anymore, so getting CF9 gets you a copy of ExtJS basically), and JQuery is also supported.

This presentation was very rapid fire, which is testimony to how feature-rich of an upgrade ColdFusion 9 is.

Importance of Understanding Factories, Part 2: Transient Factories

In my last post, I discussed some of the mistakes that can be made when using ColdSpring as our factory. It became evident that using ColdSpring to inject transient objects—that is, objects that have a state for a momentary use and then are discarded—into our service objects or other related singletons is problematic. This is largely due to the concurrency issue with reusing that injected bean in the service object's methods, and mistakes that can be made if we forget about objects being passed by reference. Ray Camden also discussed this recently in ColdFusion and Pass by Reference versus Value.

The answer is to build a transient factory for those beans. We can do it without losing the benefits of ColdSpring's dependency and configuration management. And it doesn't take much to make a factory. Take a look at this sample that works with my previous post's code.

CFM:
  1. <cfcomponent>
  2.  
  3.   <!----------------- Constructor ---------------------->   
  4.   <cffunction name="init" returntype="BeanFactory">
  5.     <cfset variables.config=StructNew() />
  6.     <cfreturn this />
  7.   </cffunction>
  8.    
  9.   <!------------------ Config -------------------------->   
  10.   <cffunction name="setConfig" returntype="void">
  11.     <cfargument name="Settings" type="struct" />
  12.     <cfset variables.config=arguments.settings />
  13.   </cffunction>
  14.   <cffunction name="getConfig" returntype="struct">
  15.     <cfreturn variables.config />
  16.   </cffunction>
  17.    
  18.   <!--------------- Create Methods --------------------->
  19.   <cffunction name="createBean" returntype="any">
  20.     <cfset var com=CreateObject("component","Bean") />
  21.     <cfset com.setConfig(getConfig()) />
  22.     <cfreturn com.init(argumentCollection=arguments) />
  23.   </cffunction>
  24.  
  25. </cfcomponent>

The factory has a setConfig() method, just like the Bean does, and can be used to conveniently inject all configuration information with ColdSpring. Now, let's look at the createBean() method where the action is. It performs 3 key actions: (a) Create a fresh object. (b) Pass in configuration. (c) Call the init() method and return the object.

Our ColdSpring file can now be rewritten like this:

XML:
  1. <bean id="BeanService" class="com.BeanService">
  2.   <constructor-arg name="BeanFactory">
  3.     <ref bean="BeanFactory" />
  4.   </constructor-arg>
  5. </bean>
  6. <bean id="BeanFactory" class="com.BeanFactory">
  7.   <property name="Config">
  8.     <map>
  9.       <entry key="dsn"><value>MyDSN</value></entry>
  10.     </map>
  11.   </property>
  12. </bean>

See, we use the same XML for injecting configuration, it's just injected it into BeanFactory. We then inject BeanFactory into BeanService, instead of the Bean itself. It can use the factory to get a fresh bean whenever it needs one—properly instantiated and configured.

An example of BeanService tweaked to accept and use the factory:

CFM:
  1. <cfcomponent hint="Handles beans." output="false">
  2.   <cffunction name="init">
  3.     <cfargument name="BeanFactory" type="BeanFactory" />
  4.     <cfset variables.BeanFactory=Arguments.BeanFactory />
  5.     <cfreturn this />
  6.   </cffunction>
  7.   <cffunction name="workWithBean">
  8.     <cfscript>
  9.       var myBean=variables.BeanFactory.createBean();
  10.       myBean.setX("I changed X on the bean!");
  11.       myBean.setY("I changed Y on the bean!");
  12.       return myBean;
  13.     </cfscript>
  14.   </cffunction>
  15. </cfcomponent>

Let's make the factory better. First, your app probably has more than one type of transient object. You don't need a separate transient factory for each type of object. Just have a different createBeanName() method for each object type, with creation code specific for each object. And if your objects are all essentially created with the same conventions, you can handle create methods for all of them with a single onMissingMethod handler. Something like this:

CFM:
  1. <!--- Create Methods --->
  2. <cffunction name="onMissingMethod" returntype="any">
  3.   <cfargument name="MissingMethodName" />
  4.   <cfargument name="MissingMethodArguments" />
  5.   <cfscript>
  6.     var method=Arguments.MissingMethodName ;
  7.     var args=Arguments.MissingMethodArguments ;
  8.     var classList="MyBean,DiffBean,AnotherBean";
  9.     var className=RemoveChars(method,1,6);
  10.     var com="";
  11.     if( Left(method,6)=="create" &&
  12.         ListFindNoCase(classList,className) )
  13.     {
  14.       com=CreateObject("component",className);
  15.       com.setConfig(getConfig());
  16.       if(StructKeyExists(com,"setFactory"))
  17.         com.setFactory(this);
  18.       return com.init(argumentCollection=args);
  19.     }
  20.   </cfscript>
  21. </cffunction>

See how the first if statement checks to make sure the method is a valid method name: One that starts with "create" and ends with an acceptable class name as we define in our classList variable. So this onMissingMethod handler will work with createMyBean(), createDiffBean(), and createAnotherBean(). Note how it also checks for the existence of a setFactory() method in the object it creates. If it is there, it will use the method to inject itself into the new object! This is a simple example of how autowiring is accomplished.

Take it even further! Head over to Paul Marcotte's blog post, A Coldfusion Transient Factory Example, which shows how to make a very generic transient factory that receives configuration on which classes it should create through ColdSpring. Very cool stuff.

Review. Transient factories don't require a lot of code, and are a vital step to simplifying and centralizing our instantiation and configuration of transient objects, or objects that have a state. Doing so doesn't negate the need for ColdSpring, in fact it complements it as it was intended, since ColdSpring works well with instantiation of singletons, and transient factories as described here are used as singletons. By utilizing ColdSpring and a transient factory, we can be well on our way to cleaner and more organized development.

Get the files. Download sample code to play with: ColdSpring Bean Test. It walks us through the issues discussed in the previous post as well as using transient factories like we just discussed.

This post has gotten pretty long, so I'll save the race condition demonstration for "Part 3". :-)

Importance of Understanding Factories, Part 1: ColdSpring Misunderstandings

As ColdFusion developers progress in the use of object oriented programming concepts with CFCs, our applications become more flexible and able to support additional interfaces such as Ajax or Flex through web services. We also potentially benefit just from overall code maintainability, extensibility, and reusability by using best practices and design patterns common in OOP.

The benefits are many, but there are certainly pitfalls along the way. Perhaps we're ready to begin using service objects. And we'd like to create and pass in our transient objects with ColdSpring as a factory for all objects.

Let's cover the groundwork of our example, and then consider a pitfall. Here's our transient object:

Bean.cfc

CFM:
  1. <cfcomponent hint="Represents a bean." output="false">
  2.  
  3.   <cffunction name="init" access="public"
  4.               returntype="Bean" output="false">
  5.     <cfargument name="x" type="any" required="true" />
  6.     <cfargument name="y" type="any" required="true" />
  7.     <cfargument name="z" type="any" required="true" />
  8.     <cfset setX(arguments.x) />
  9.     <cfset setY(arguments.y) />
  10.     <cfset setZ(arguments.z) />
  11.     <cfreturn this />
  12.   </cffunction>
  13.  
  14.   <!------------------- Config -------------------------> 
  15.   <cffunction name="setConfig" access="public"
  16.               output="false" returntype="void"
  17.               hint="Method to pass in configs.">
  18.     <cfargument name="Settings" type="struct" />
  19.     <cfset variables.instance.config=arguments.settings/>
  20.   </cffunction>
  21.  
  22.   <!------------------ Setters ----------------------->
  23.   <cffunction name="setX">
  24.     <cfargument name="newval" />
  25.     <cfset variables.instance.data.x=arguments.newval />
  26.   </cffunction>
  27.   <cffunction name="setY">
  28.     <cfargument name="newval" />
  29.     <cfset variables.instance.data.y=arguments.newval />
  30.   </cffunction>
  31.   <cffunction name="setZ">
  32.     <cfargument name="newval" />
  33.     <cfset variables.instance.data.z=arguments.newval />
  34.   </cffunction>
  35.  
  36.   <!------------------ Getters ----------------------->
  37.   <cffunction name="getMemento" access="public"
  38.               returntype="struct" output="false">
  39.     <cfreturn variables.instance />
  40.   </cffunction>
  41.  
  42. </cfcomponent>

This is an overly-simplified example of a bean. It just has 3 properties (X, Y, Z) and corresponding setter methods. It also has a typical init() method, a setConfig() method to pass in configuration, and a getter method so we can quickly dump the state of the object. It'll be enough for our samples.

Perhaps we might write a ColdSpring configuration like this:

XML:
  1. <bean id="BeanService" class="com.BeanService">
  2.   <constructor-arg name="Bean">
  3.     <ref bean="Bean" />
  4.   </constructor-arg>
  5. </bean>
  6. <bean id="Bean" class="com.Bean" singleton="false">
  7.   <property name="Config">
  8.     <map>
  9.       <entry key="dsn"><value>MyDSN</value></entry>
  10.     </map>
  11.   </property>
  12.   <constructor-arg name="x">
  13.     <value>One</value>
  14.   </constructor-arg>
  15.   <constructor-arg name="y">
  16.     <value>Two</value>
  17.   </constructor-arg>
  18.   <constructor-arg name="z">
  19.     <value>Three</value>
  20.   </constructor-arg>
  21. </bean>

This seems like it should work, eh? We're instantiating a service object, instantiating and configuring a bean, and passing the bean into the service object. Here's a really simple example of the bean service object:

BeanService.cfc

CFM:
  1. <cfcomponent hint="Handles beans." output="false">
  2.   <cffunction name="init">
  3.     <cfargument name="Bean" />
  4.     <cfset variables.Bean=Arguments.Bean />
  5.     <cfreturn this />
  6.   </cffunction>
  7.   <cffunction name="getBean">
  8.     <cfreturn variables.Bean />
  9.   </cffunction>
  10.   <cffunction name="workWithBean">
  11.     <cfscript>
  12.       var myBean=variables.Bean;
  13.       myBean.setX("I changed X on the bean!");
  14.       myBean.setY("I changed Y on the bean!");
  15.       return myBean;
  16.     </cfscript>
  17.   </cffunction>
  18. </cfcomponent>

This BeanService object has a constructor that receives the bean and stores it in its variables scope. It then has a the getBean() method so we can see the bean, and a workWithBean() method that simulates doing some work with the bean.

And now, the pitfall: ColdSpring singletons and objects passed by reference.

This code technically runs, and appears fine: The Bean instance that we pass into the service is not a singleton, so each BeanService we instantiate (if we were to instantiate multiple) would have a separate Bean instance. And workWithBean() appears to use a local var copy of Bean.

Wrong.

First, the Singleton vs. Transient Objects With ColdSpring page explains that ColdSpring isn't ideal for generating transient components. Its overhead is more appropriate for less frequent creation of components that typically go in a shared scope, such as in the Application scope. Performance aside, though, the approach of injecting a transient bean into a singleton like BeanService does technically work.

So now the second point, how BeanService is working with Bean in our example workWithBean() method. The key misunderstanding is that CFCs like the Bean object are passed by reference when being assigned to variables. So when we do var myBean=variables.Bean, the local myBean variable is pointing to the same copy of Bean that variables.Bean points to. When it executes methods that change the bean's state, the one copy of Bean is being altered. Whoah, that wasn't an intended behavior. This could have very negative consequences, with Bean not being in the state you might expect it to be in.

So, how to fix it? Hmm. I don't want to use CreateObject() because that would become a dependency we'd have to manage, and we'd have to handle properly configuring the bean. This was the whole point of injecting the bean with ColdSpring in the first place.

Well, a quick solution could be to just use Duplicate() to make a copy of the injected bean before working on it! So, we could replace our workWithBean() method with this:

CFM:
  1. <cffunction name="workWithBean">
  2.   <cfscript>
  3.     var myBean=Duplicate(variables.Bean);
  4.     myBean.setX("I changed X on the bean!");
  5.     myBean.setY("I changed Y on the bean!");
  6.     return myBean;
  7.   </cfscript>
  8. </cffunction>

Now, variables.Bean will always be the pristine, original bean injected by ColdSpring, and the local myBean variable will perform its work with a duplicate of that bean. Our code will now be working the way we intended; disaster has been averted.

Well, this does work. But it is neither graceful nor efficient, and it is not recommended. Consider Sean Corfield's blog post, Duplicate() is Bad For Your (Object's) Health. In an informal test, he clocked Duplicate() as being drastically slower—we're talking 50 to 1—than using CreateObject().

Ugh. If we're back to using CreateObject(), what good is using ColdSpring for managing these component relationships, and what about dealing with configuration? Enter the world of factories. Yes, ColdSpring itself is a factory, but it is a factory oriented around creating and configuring our singletons, which can include other factories whose purpose is to properly create transient objects like Bean.

So instead of having ColdSpring inject Bean into BeanService, we can make a BeanFactory and inject that into BeanService, giving BeanService the ability to create Beans to work with any time it needs to. This may seem like a lot of effort, but we'll come to see that creating transient factories is easy and will clean up the mess of an architecture in this sample to something graceful and maintainable.

In this post, I described a few of the mistakes that can be made as we start to utilize ColdSpring. Hopefully these mistakes point to the importance of factories—not just ColdSpring, but our own transient factories as well. In the next blog post, we'll rework the sample to use a factory and review the benefits the factory provides and how it doesn't duplicate the purpose of ColdSpring. We'll review one more scenario that underscores the importance of factories: the dreaded race condition. And I'll provide source code that has executable demonstrations of these undesirable mistakes in action. :-)

Get a Struct or Array in That Simple Value Field

In some environments and scenarios, I used to use initialization (*.ini) files for storing simple configuration settings. Now I typically store this kind of information in a ColdSpring configuration file, or at least in an XML file of some sort. But at times I have to live (and work) with the apps I wrote that use *.ini configuration files.

The nice thing about *.ini files. Not that they're all bad. It's ridiculously easy to extract settings from these files with ColdFusion. For instance:

TEXT:
  1. [Settings]
  2. mysetting=Hello
  3. anothersetting=Goodbye

To retrieve the mysetting configuration setting, I just make one call:

CFM:
  1. x=GetProfileString(pathToFile,"Settings","mysetting");

It can't get much easier than that to retrieve a value from a configuration file!

The bad thing about *.ini files. The only problem is that these files are restricted to name=value pairs of simple values. You may go into a project with no need for configuration settings that are any more complicated than simple numbers or strings, but what about 3 years from now when the business logic now could use some structs or arrays in the configuration?

Of course, you could change your whole configuration methodology when--and if--that time comes, but ugh. Using XML (especially in conjunction with IoC such as ColdSpring) is so much more scalable. The future you will thank you.

But it's too late. You and I already have complex app XYZ that is using *.ini config files, and you need to add feature X without rebuilding the configuration logic of the app. What to do?

Embed a string representation of your struct or array in the config file! After all, ColdFusion 8 allows implicit struct and array creation, right? Well, half-right. Doing something like x=Evaluate(myStructString) just isn't allowed by ColdFusion.

However, we can effectively do the same thing with JSON representations of structs and arrays. So, try this:

TEXT:
  1. [Settings]
  2. mysetting={"one":"Hello","two":"Goodbye"}
  3. anothersetting=Yomomma

Now, retrieving mysetting with GetProfileString() will still get you a string, but using JSON functions built into ColdFusion 8 will get you a struct:

CFM:
  1. x=GetProfileString(pathToFile,"Settings","mysetting");
  2. myStruct=DeserializeJSON(x);

Your myStruct variable will be a struct with two keys ("one" and "two") just as you would expect from the JSON.

You could achieve similar results using XmlParse(), but in a case like this, the less verbose, the better. And JSON is less verbose than XML.

  Theme Brought to you by Directory Journal and Elegant Directory.