The amazing adventures of Doug Hughes

I am a big fan of ColdSpring. I have been for quite a while. I am also aware of the fact that I typically use only a small portion of what ColdSpring offers us. I use it mostly for bean definitions and managing dependencies. I always wanted to play around with the AOP (aspect oriented programming) pieces of ColdSpring, but I never had a real need to do so…or so I thought.

On a recent project, we had the need to have our model return data in a slightly different format when being called from a remoting proxy (also created by ColdSpring). In this case we needed to return data for use in a . Initially, we simple added a method that was solely used for AJAX calls. This can cause issues as now we had very similar code, doing a very similar process in more than once place. This can lead to issues if there were changes made to one method and not the other. The solution we came up with was to use method interception in ColdSpring.Basically, method interception, is a way that we can use ColdSpring to process method calls differently by ‘intercepting’ them.

It may seem difficult to comprehend where this would be needed, but I think the above example is a great one. Lets say you have a service object named WidgetService and inside that object is a method named getWidgets(). In our original code, we might also have a method named getWidgetsFromAJAX() that would format the data for use in the . Both of these methods would need to accept the same arguments, query the database the same way and return data. The only difference is that in the second method, we would need to call QueryConvertForGrid() before returning the results. This just feels dirty to me.

Using method interception, we can tell ColdSpring that if the method call comes from a certain file (like our remoting proxy), to handle it differently, and in this case, format the data to be used with . Lets start by going over the ColdSpring configuration.

The following is our intercept definition. The interceptor names are other beans, and in this case the bean name is the bean that will be used during our intercept. This bean is also used as our ‘target’ for the remoting proxy. This is how we limit the intercept to only calls made through the remoting proxy.

The following will create our remoting proxy. This definition tells ColdSpring to create a file named ‘RemoteWidgetService.cfc’ that is based off of the ‘ajaxWidgetService’ bean and will include the method named ‘getWidgets’ in the remoting proxy.

This code is what actually gets run during the intercept. What we do here is use to make the method call and pass along any arguments using . Then, as long as the result of that method call is a ColdFusion query object, we call the queryConvertForGrid() method and return that value. In our project, we had a lot more code as we needed to massage some of the values returned before shipping it off to .

This example uses a bit of ColdSpring’s functionality, so lets break it down one more time.

First, we have a simple service, named ‘widgetService’ that has a method named ‘getWidgets’. This method returns a ColdFusion query object containing the id and name of the widget.

Next we have a bean named ‘ajaxWidgetService’ that defines our intercept and tells ColdSpring to use the ‘ajaxMethodInterceptorAdvice’ bean as an interceptor.

Then we create our remoting proxy by telling ColdSpring what bean to base the proxy on.

Lastly, we have the bean that will be used for our intercept.

Now lets follow the path of execution. We make a remote call to the ‘getWidgets’ method on the ‘remoteWidgetService’. This in turn calls the ‘getWidgets’ method on the widgetService, however, ColdSpring intercepts this method call, and instead, calls the ‘invokeMethod’ method on our interceptor. This method then makes the call to the ‘target’, which in this case is the ‘widgetService’. If the result of this method call is a ColdFusion query, we run call the queryConvertForGrid() method and finally return that result.

Maybe I’m missing something here… I certainly could be… this just seems amazingly complex to me, and at least at first glance I’m not really seeing the benefit. I’m just thinking about the original problem of converting data for use by cfgrid in a web service and how I would likely approach that problem…

In my case I’m likely to be using the onTap framework (due to my obvious bias) and so I’ll have a webservice CFC in my app that has whatever arguments it needs to call to the widgetService.getWidgets() method.

So rather than having some XML config and a new extra CFC to create, all the logic for converting the data for the ajax call would be built into that web service where the ajax call is being made. Am I missing something?

I will say that it’s been a long while since I’ve used a cfgrid for anything and I’ve never used the ajax integration with it, so it’s not like I’m an expert on this or anything.

@Ike – Then how would you suggest handling the case where you need to get all the widgets, but it is not from a remote AJAX call? That would take either a seperate method, or passing in an argument that tells the method whether or not we want the query returned for the grid or for just all the widgets. Neither of these really feels like the best solution.

As I mentioned, in our case, we also needed to do other processing on some of the data before it was sent off to be used in the .

At most it seems like you’d end up with a couple of duplicated cfargument tags. That’s why I’m still confused as to what the advantage of the proxy is. It seems like a lot more work to me than maintaining a handful of duplicated cfargument tags. Also seems like there would be more dependencies and it would execute slower.

I’m not just trying to be difficult, it’s just not something I’ve worked with. I could be totally off-base, that’s why I’m asking.

Thanks Scott, I do appreciate your taking the time to both write the blog and put up with my questions. 🙂

i understand the use of AOP for security, logging, etc. across a whole application and i’m looking into it now, but i have to agree with ike, this seems pretty overkill for a simple QueryConvertForGrid(). especially if a function with one line will do the same.

@Scott – I’ve been traditionally dealing with this type of issue with a similar solution to Ike. What is the difference between the two solutions? Is there some type of concern, theory or design pattern issue that makes the ColdSpring intercept more “correct” or advantageous?