I hear ya Chris, and yes, I definitely don't want it to turn into another
programming language or some abstract way to generate CFCs. I saw it as a
way to kick the possibilities of AOP up a notch, since now your generated
remote proxies can handle different/extra arguments than the CFC being
proxied.

For example, lets expand the example. 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 (or even write a generator that then has to be kept up to date)
having to write the proxy methods (and losing the AOP Advice to handle it
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>/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>

And now be able to use all 50 methods from my AJAX grids, without having to
change anything in my model or write any other CFCs?

I could also imagine a similar situation, say with a web service. Maybe you
want to use an advice to wrap web service calls, and you want to force them
to pass an authentication token each time that your advice will check, 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.

I know it's pretty crazy and I really just did it for the challenge of it,
and because I'd never seen anything like it considered before.

Thanks for entertaining my crazy ideas!

Brian

On 7/11/07, Chris Scott <[EMAIL PROTECTED]> wrote:

Hmm, I like the idea, but am not 100% sure this is a good thing to add to
the RemoteFactoryBean. It is a big departure from what Spring offers on one
hand, but more importantly, the code example looks to me like fully
metaprogramming your cfcs in xml. All you are missing is your actual method
call. Being able to fully transform one method into basically a
totally different one is really not what AOP is about, it is about
introducing a little code seamlessly across your application
logic, maximizing code reuse, while simplifying your core business logic.
This seems too much of major magical code transformation to me
C

Chris Scott
[EMAIL PROTECTED]
http://cdscott.blogspot.com/
http://www.coldspringframework.org/








On Jul 11, 2007, at 8:32 PM, Brian Kotek wrote:

I wanted to get some input about a hack that I just created in ColdSpring.
First, some 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(). I could also imagine doing 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 the the RemoteFactoryBean to
generate the remote proxy bean:

    <!-- Generate remote facade for Product Service -->
    <bean id="artServiceAJAX" class="
coldspring.aop.framework.RemoteFactoryBean" lazy-init="false">
        <property name="target">
            <ref bean="artService" />
        </property>
        <property name="serviceName">
            <value>ArtServiceAJAX</value>
        </property>
        <property name="relativePath">
            <value>/artstore/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="getArtists" returnType="query">
                    <parameter name="cfgridpage" required="yes"
type="numeric" />
                    <parameter name="cfgridpageSize" required="yes"
type="numeric" />
                    <parameter name="cfgridpagesortcolumn" required="no"
type="string" default="" />
                    <parameter name="cfgridpagesortdirection"
required="no" type="string" default="" />
                </method>
            </methods>
        </metadata>
    </bean>

And the resulting ArtServiceAJAX.cfc has this method defined:


    <cffunction name="getArtists" access="remote" returntype="any"
output="false" >
        <cfargument name="cfgridpage" type="numeric" required="yes" />
        <cfargument name="cfgridpageSize" type="numeric" required="yes" />

        <cfargument name="cfgridpagesortcolumn" type="string"
required="no" default="" />
        <cfargument name="cfgridpagesortdirection" type="string"
required="no" default="" />
        <cfset var rtn = callMethod('getArtists', arguments) />
        <cfif isDefined('rtn')><cfreturn rtn /></cfif>
    </cffunction>

It seems to me this could be very useful in any remote proxy bean that
also uses AOP to do something beyond what the base component it is proxying
does. In theory it would work for web service calls too, which are also
obviously highly dependent on the metadata of the proxy to generate WSDL,
etc. Flex apps might benefit less since I don't believe they depend on the
actual metadata/arguments/types of the methods being called, but someone who
knows more might correct me. This proof of concept requires you to spell out
the full method names, but I could easily see changing it to support
wildcards like get*.

I set it up so that you can alter the return type of the method itself,
alter the type, required, and default attributes of existing arguments, and
add completely artificial arguments as well.

I'm interested to hear what people think. One downside is that it seems to
definitely alter the ColdSpring XML DTD to differ from the Java Spring DTD,
though I know there is already at least one other difference between the two
(in the constructor arg I think).

Is this madness?

Thanks,

Brian



<<inline: TeamFusionD.gif>>

Reply via email to