I posted about this on the ColdSpring list but I thought I'd add a blog entry on it to see if it draws any further comments or ideas from the community. Basically I am playing with a modification to ColdSpring that will let me inject extra metadata about my components that ColdSpring can use when generating remote proxies or executing AOP advices. In summary, what it would allow you to do is:

  1. Alter the API of methods generated by ColdSpring in a remote proxy. This will allow your remote proxy to have different arguments and return types than the underlying component being proxied.
  2. Allow you to inject custom metadata into AOP Advices to give them extra information to act on (such as what data to log in a Logging Advice).

First, a little background. I was playing with the new AJAX features in CF8. In particular, I was messing with the AJAX grid. I created a simple service component that returns a query, and wanted to use ColdSpring to generate a remote proxy bean that the grid can call. So far so good.

The first issue I ran into was that the AJAX grid requires a query to be reformatted using QueryConvertForGrid(). So I created a simple AOP advice that runs the target method and then returns the result wrapped with QueryConvertForGrid(). It also handles resorting the query if they click on a column, and sorting in ascending or descending order. I could also imagine doing something like this to format data for use in the AJAX tree component.

Anyway, when I bound my grid to the CFC method, ColdFusion complained loudly. I seems any method used to update a grid requires several arguments, such as cfgridpage, cfgridsize, cfgridpagesortcolumn, and cfgridpagesortdirection. So I specified these arguments in my CFC call from the grid. CF still complained. It seems that the AJAX to CFC binding uses CFC metadata and REQUIRES that cfargument tags exist in the target CFC that match these arguments.

Now you can probably see the problem. My base service component has no such arguments. It has no idea I'm eventually using the data it returns in an AJAX grid. And since ColdSpring uses the base CFC metadata when generating the remote proxy bean, it won't generate any arguments at all for that remote method. So it looked like I was out of luck on using ColdSpring for this sort of thing. Which would suck for an app that sent a lot of data to AJAX grids...I'd have to manually create remote facades for every method.

Unless....

The wheels began turning...

What if I could somehow inject artificial metadata into the system, so that even though my base service component didn't have these grid-specific cfargument tags, the generated remote proxy would? Then ColdFusion's AJAX to CFC binding would be happy, and the AOP advice would have these arguments available for use in the QueryConvertForGrid() function call that it does.

Well, I did it. The result is that a bean definition like this will have extra metadata defined, that will be used by the RemoteFactoryBean to generate the remote proxy bean.

To put this in context, say I have an AccountingService that has a lot of data getting methods, and I want to use it to populate various AJAX grids. Maybe we're talking about 50 methods. Instead of having to manually write the proxy methods (and losing the AOP Advice to handle Grid reformatting across lots of methods), wouldn't it be great to do:

<bean id="AccountingServiceAJAX" class="coldspring.aop.framework.RemoteFactoryBean" lazy-init="false">
	<property name="target">
		<ref bean="AccountingService" />
	</property>
	<property name="serviceName">
		<value>AccountingServiceAJAX</value>
	</property>
	<property name="relativePath">
		<value>/common/components/</value>
	</property>
	<property name="remoteMethodNames">
		<value>get*</value>
	</property>
	<property name="beanFactoryName">
  			<value>BeanFactory</value>
	</property>
	<property name="interceptorNames">
		<list>
			<value>AJAXGridAdvisor</value>
		</list>
	</property>
	metadata>
		<methods>
			<method name="get*">
				<parameter name="cfgridpage" />
				<parameter name="cfgridpageSize" />
				<parameter name="cfgridpagesortcolumn" />
				<parameter name="cfgridpagesortdirection" />
			</method>	
		</methods>
	</metadata>
</bean>
		

Now the generated remote proxy CFC that ColdSpring creates will have methods that look like:

<cffunction name="getSalesData" access="remote" returntype="any" output="false" > 
	<cfargument name="cfgridpage" /> 
	<cfargument name="cfgridpageSize" /> 
	<cfargument name="cfgridpagesortcolumn" /> 
	<cfargument name="cfgridpagesortdirection" /> 
	<cfset var rtn = callMethod('getSalesData', arguments) />
	<cfif isDefined('rtn')><cfreturn rtn /></cfif>
</cffunction>
		

And now I'm able to use all 50 methods from my AJAX grids, without having to change anything in my model or write any other CFCs. I think that's pretty cool.

I can imagine other uses for this as well. How about with a web service. Maybe you want to use an advice to wrap incoming web service calls, and you want to force them to pass an authentication token each time that your advice will check (for security), log, or whatever. But your actual Service CFC doesn't know or care about web service authentication tokens. You could use this approach to generate remote proxies with WSDL that requires the token, and your advice could use it, but your base service component never knows anything about it.

Here's another possibility. Chris Scott blogged about adding extra attributes to your CFC to help tell a ColdSpring LoggingAdvisor what variables to log. It would be possible to modify what I'm trying out to handle this Logging situation as well, from within the ColdSpring XML instead of adding extra attributes to your actual Service CFC methods. In other words, you could define extra metadata for the method in the XML (such as what variables to log) that would be available to the Advice. This would completely separate what ColdSpring needs to know from your real CFC, which seems like it might be pretty handy.

Anyway, this is really just me messing around, trying things out, and looking at an idea that I hadn't seen discussed before. There may well be a better approach that I'm missing, or a better way to integrate what I'm trying to do. I'm open to ideas or discussion so please post away here or on the ColdSpring list!

Comments Comments (1) | del.ico.us del.icio.us | Digg It! Digg It! | Linking Blogs Linking Blogs | 3174 Views

Comments

  • # Posted By bethb | 7/12/07 3:09 PM

    I have a vision of you pouring the bubbling green contents of a test tube into your keyboard. Madness aside -- great post