The Value Objects
Otherwise known as a transfer object is simply a design pattern for exchanging data between disparate systems. I’m working on a application with a Flex UI and a ColdFusion backend, and I initially discovered that if I return a query directly to Flex, it is converted into an ArrayCollection populated with simple Objects.
What I wanted was an array of specifically typed objects that I could cast as value objects in Flex. Here’s a very simplistic example of an Employee value object in Flex. It has two properties:
- Employee ID
- Employee Name
Flex Employee Value Object
package net.fusioncube.transferObjects
{
[RemoteClass(alias="net.fusioncube.model.employee.Employee")]
[Bindable]
public class Employee
{
private var _employeeID:uint;
private var _employeeName:String;
/* constructor */
public function Effort(employee_id:uint = 0,
employee_name:String = "")
{
this._employeeID= employee_id;
this._employeeName= employee_name;
}
public function get employee_id():uint
{
return _employeeID;
}
public function set employee_id(value:uint):void
{
if(value != 0) _employeeID= value;
}
public function get employee_name():String
{
return _employeeName;
}
public function set employee_name(value:String):void
{
if(value != "") _employeeName= value;
}
}
}
You may have noticed the RemoteClass metadata applied to the Actionscript class. What this does is ensure that this Flex class maps directly to a ColdFusion component value object. To make a ColdFusion component value object is simple: you use the <cfproperty> tag for each property and specify each one’s type.
In this example, I’ve also added an init() method, whose use we’ll discover later.
ColdFusion Employee Value Object
<cfcomponent displayname="Employee" output="false">
<cfproperty name="employee_id" type="numeric" default="" />
<cfproperty name="employee_name" type="string" default="" />
<cffunction name="init" access="public" returntype="net.fusioncube.model.employee.Employee" output="false">
<cfargument name="employee_id" type="numeric" required="false" />
<cfargument name="employee_name" type="string" required="false" />
<cfset this['effort_id'] = arguments.effort_id />
<cfset this['employee_name'] = arguments.employee_name />
<cfreturn this />
</cffunction>
</cfcomponent>
Converting a Query to an Employee Array
Again, as a very simple example, let’s say I have an EmployeeService component in my service layer and have a method listEmployees() that simply queries the employees table and returns all rows.
<cffunction name="listEmployees" access="public" output="false" returntype="query">
<cfset var effortQuery = "" />
<cfquery datasource="#variables.config.getSetting("datasource")#" name="employeeQuery">
select e.* from employees e
</cfquery>
<cfreturn effortQuery />
</cffunction>
Since I don’t want to return a query, and I certainly don’t want to have two methods in every single component – one that returns a query and one that returns an array of objects – I use the handy, dandy AOP feature in ColdSpring to apply an advice that does it at runtime.
QueryToVOAdvice Advice
In this advice, I simply loop over the query’s rows and columns to create a simple structure containing the key/value pairs for each row. It then creates a new component for each query row by passing that structure to the init() function – which you saw above – and adds it to an array.
The result is an array of Employee-typed objects.
<cfcomponent displayname="QueryToVOAdvice" extends="coldspring.aop.MethodInterceptor">
<cffunction name="init" returntype="utility.aop.advice.converters.QueryToVOAdvice" access="public" output="false">
<cfreturn this />
</cffunction>
<cffunction name="invokeMethod" access="public" returntype="any">
<cfargument name="methodInvocation" type="coldspring.aop.MethodInvocation" required="false" />
<cfscript>
var local = structNew();
local.queryRow = 1;
// Create an array to hold the value objects
local.valueObjectArray = ArrayNew(1);
// Store the resulting query object from the method execution
local.queryObject = arguments.methodInvocation.proceed();
// Loop over the query rows
for(local.queryRow=1; local.queryRow lte local.queryObject.recordCount; local.queryRow = local.queryRow+1)
{
local.voStruct = structNew();
// Loop over the query columns and create a key/value pair for each value
// in this row of the query
for(local.columnNum=1; local.columnNum lte listLen(local.queryObject.columnList); local.columnNum = local.columnNum+1)
{
local.columnName = listGetAt(local.queryObject.columnList, local.columnNum);
local.voStruct[local.columnName] = local.queryObject[local.columnName][local.queryRow];
}
// Create an instance of the value object (obtained from the getValueObject method)
// initializing it with the structure we created. Add the value object to the array.
arrayAppend(local.valueObjectArray, createObject('component', arguments.methodInvocation.getTarget().getValueObject()).init(argumentCollection=local.voStruct));
}
return local.valueObjectArray;
</cfscript>
</cffunction>
</cfcomponent>
ValueObject Property
For each of my beans, in this case the Employee bean, I can simply apply an advice in the definition. For this to work, I create a valueObject property in each component.
<component name="Employee">
<cffunction name="setValueObject" access="public" output="false" returntype="void">
<cfargument name="valueObject" type="string" required="true" />
<cfset variables.valueObject = arguments.valueObject />
</cffunction>
<cffunction name="getValueObject" access="public" output="false" returntype="string">
<cfreturn variables.valueObject />
</cffunction>
</component>
Employee Bean Definition
Now when I define my Employee bean, I specify the type of the value object (the type that gets returned from the init() function), and then apply the advisor (shown below).
<bean id="Employee" class="coldspring.aop.framework.ProxyFactoryBean">
<property name="target">
<bean class="net.fusioncube.model.employee.EmployeeService">
<property name="valueObject">
<value>net.fusioncube.model.employee.Employee</value>
</property>
</bean>
</property>
<property name="interceptorNames">
<list>
<value>queryToValueObjectAdvisor</value>
</list>
</property>
</bean>
QueryToValueObjectAdvisor Definition
<bean id="queryToValueObjectAdvisor" class="coldspring.aop.support.RegexMethodPointcutAdvisor">
<property name="advice">
<bean class="utility.aop.advice.converters.QueryToVOAdvice"/>
</property>
<property name="pattern">
<value>^list.*$</value>
</property>
</bean>
The Flex Array of Typed Objects
Here’s an image of an example array I get back from ColdFusion in one of my current apps. You can see that each object was automatically converted into a Teammate (equivalent of an Employee) rather than a simple Object.
Caveat: If you’re passing back queries with a thousand or more rows, and are running CFMX 7 or older, then this solution may cause serious performance problems as object creation is notoriously “slow” in those versions of ColdFusion.


