Building ColdFusion services with ColdSpring and Reactor, part 6

Submitted by Falken on

In the previous part, we saw how you can easily get up and running with the AOP features of ColdSpring in a ColdFusion project. But what practical use can this be put too ?
In this part I will show a simple piece of AroundAdvice that helps with reporting exceptions to clients of services. The next part will present a more complicated example - using BeforeAdvice to enforce security constraints and time-limited tokens.

What's wrong with the way remote exceptions normally work with a ColdFusion CFC endpoint (from Flex or any other client) though - why would we want to do anything other than just have exceptions be raised and fired back ?
There are a number of issues.
We might want to include a common version number in all responses (though this example doesn't do this). We might want our client (esp. a Cairngorm Command) to use it's fault handler for actual network and connectivity problems, and handle remote errors in a (common, or automatic) result handler. And that means we'll need some standard way of indicating if the remote call was successful or not - and if not, at least a hint of the error. Sending the whole exception to (say) a Flex client is pointless because it's trivial to have this stack trace be so long, that if you try and put it in an Alert, it's taller than the screen.

So, what to do ?
We want to run the actual Manager method inside a CFTRY block, and if there was an error, return the first part of the error. We'll probably also want to move that result or error string into a 'data' key in a structure along with a boolean to indicate if the 'data' key is an error or not.
Our client can then leave it's fault handler to worry about network issues, which makes it much clearer, and concentrate our client-side effort into the more common result handlers.

Now, on to the code - RemoteExceptionAroundAdvice.
What does this do then ?
It starts by creating a 'record' struct which we return at the end of code. We'll be using the 'result' key to hold a 'has data' or 'has error' boolean, so we set that to false to start with - after all, we've not run anything yet.
Next, we enter a CFTRY block, where we make use of the AOP framework's magic to go off and run the underlying CFC method the Advice is advising - arguments.mi.proceed().
We save the result of what ever else has to be done to get a result from the 'target' bean into the 'data' property of our result structure, then set the 'result' field to true to indicate all went well.
In the CFTRY we CFCATCH all errors, and construct a simple error message, using information we can extract from the arguments to the Advice to locate the target bean and method name. We then set the result field to false to indicate something went wrong server-side.

You'd then configure a new bean in ColdSpring using the RemoteExceptionAroundAdvice class, and use that bean as an item in the interceptorNames list in a RemoteFactoryBean, and it'll Just Work.
You can use this same interceptorName bean in all your RemoteFactoryBean's.

<bean id="remoteExceptionAdvice" class="com.falkensweb.aop.RemoteExceptionAroundAdvice"/>

<bean id="remoteFooService" class="coldspring.aop.framework.RemoteFactoryBean">
<property name="target">
<ref bean="fooManager"/>
</property>
<property name="serviceName">
<value>FooService</value>
</property>
<property name="relativePath">
<value>/com/falkensweb/bar/service/</value>
</property>
<property name="remoteMethodNames">
<value>lbaz,boo</value>
</property>
<property name="interceptorNames">
<list>
<value>remoteExceptionAdvice</value>
</list>
</property>
</bean>

What I really like is that the code to do this really handy, yet massive to the client, change is so small, and so easy to do.

Lastly, if anyone would like to write a handy CommandUtil ActionScript class, with a single static method getResult(event, errorText, errorTitle):* that can parse this standard result and return the 'data' element, automatically showing an Alert if there's an error, with default title and body text that can be overridden- you'll get a big fat credit for saving me the trouble :-)

Come back next time for something even more useful.

Previous Part | Next Part

Sections