Building ColdFusion services with ColdSpring and Reactor, part 2

Submitted by Falken on
At the top of our tiers of ColdFusion objects, we have the Service.
Services deal with making sure the underlying Managers who perform the work are abstracted from the way the Service is called. Typically this means a service will enforce authentication requirements, though authorisation may be dealt with here too rather than with in a manager particularly if it is a simple 'is user in role' task. If you do this though you must be careful to make the same checks when the Manager is invoked in other ways - like from another Manager.

Services accept transfer objects and simple types as arguments and ensure only those are return by marshalling the results of Managers.
It may be advantageous to have a consistent interface across all your services such as a success/failure flag plus data structure.
Unlike the mostly internal interfaces in a Manager, Service method arguments should be typed and have the required flag set, as this will help with consuming them.

A typical service method would be createUser, and would expect to be passed a User transfer object. A service will normally only call one Manager, apart from those involved with security. You will probably want to catch any non-security errors and report them back.

What might such a Service CFC look like ? Maybe something like this:

<cfcomponent extends="serviceBase">
<cffunction name="getAllUsers" access="remote" output="false">
<cfset super.init()>
<cfreturn queryToArrayOfVO(
application.beanFactory.getBean('userManager').getDepartmentList(),'data.UserVO')
> >
</cffunction>

<cffunction name="createUser" access="remote" output="false">
<cfargument name="userVO" type="data.userVO" required="true"/>
<cfset var ret=structNew()>
<cfset ret.ok=false>
<cfset super.init()>
<cftry>
<cfset application.beanFactory.getBean('userManager').create(arguments.userVO) />
<cfset ret.ok=true>
<cfcatch type="any">
<cfset application.beanFactory.getBean('logger').logError("#cfcatch.message# #cfcatch.detail#");
</cfcatch>
</cftry>
<cfreturn ret
</cffunction>
</cfcomponent>


Services obviously need to locate Managers, and this is where ColdSpring (or some other dependancy injection framework such as LightWire) is used to abstract the details of creating a userManager (and all the things it needs) out of the Service. As a double benefit, Managers can be decoupled from each other using ColdSpring.

The ColdSpring configuration file might include snippits such as:

<bean id="logger" class="com.Logger">
<property name="level">
<value>Information</value>
</property>
</bean>
<bean id="userManager" class="com.userManagerImpl">
<property name="reactor">
<ref bean="reactor"/>
</property>
<property name="logger">
<ref bean="logger"/>
</property>
</bean>

The base class referenced in the above ColdFusion component has an init() method which takes care of placing a Factory for Managers into the application scope - the rest of the code need not worry about this, it can just ask application.beanFactory for a userManager, or a logger and be sure the detail of creating one (the userManager probably wants a logger too !) is kept well out the way. Note theService does not even know anything about ColdSpring directly - all it cares about is a getBean() method on some object or other.

The base class also has a set of utility methods such as queryToArrayOfVO() which can loop over native ColdFusion object such as a query, and convert it into an (array of) value objects ready to be consumed by the invoker of the service.

It is the Managers that Services invoke that we will explore in the next article.

Previous part | Next part

Sections