The Grade Schooler's Guide To ColdSpring - Part 2 Flex To ColdSpring Connection
Introduction:
One of the web applications I'm developing for the Kansas City Adobe User Group uses a Flex front end. The backend CFCs are managed by ColdSpring (see part 1 Naked ColdSpring). Since ColdSpring is managing the CFCs and their dependencies, I cannot just call my UserService CFC from Flex. My Flex application needs to connect to the UserService object being managed by ColdSpring, which has all of its dependencies resolved.
ColdSpring provides a means to create a version of my UserService CFC that Flex can connect to. References 1 and 2 provide some advanced explanations of how to get ColdSpring to create a remote version of a CFC. This blog entry will provide the grade school version.
Setup The Example Code:
Make sure you've gotten the example code provided for part 1 Naked ColdSpring working correctly. The example code for this blog entry requires the same database and datasource. You should unzip this example code to the coldspring/examples folder (NOTE: this action will overwrite files of the same name. So if you made changes to any of those files backup the JustColdSpring folder and its contents before unzipping this code download). Just as in part 1, if you did not use the same datasource name I did (justCSdbMySQL) then you'll need to change the line in services.xml to specify the datasource name you used (see part 1's instructions).
Review The Example Code:
Look over the example code. You should have a folder named JustColdSpring, which is under the ColdSpring/Examples folder (which should be under your web root). In the JustColdSpring folder will be a new flex folder that contains a basic Flex application to test connecting Flex to the UserService CFC that is being managed by ColdSpring.
In the model folder you should see a new CFC named UserServiceRemote. This CFC is actually written by ColdSpring for us and later on I'll explain how that happens. The UserServiceRemote CFC is the CFC that our Flex application will communicate with to get data about a user.
Those are the only new files. I did add some code to the services.xml and application.cfm files. I'll cover those changes below.
services.xml
<bean id="userServiceRemote" class="coldspring.aop.framework.RemoteFactoryBean">
<property name="target">
<ref bean="userService" />
</property>
<property name="serviceName">
<value>userServiceRemote</value>
</property>
<property name="beanFactoryName">
<value>beanFactory</value>
</property>
<property name="relativePath">
<value>/coldspring/examples/justcoldspring/model/</value>
</property>
<property name="remoteMethodNames">
<value>getUserByID</value>
</property>
</bean>
At the end of the services.xml file I added a new bean definition. This bean definition provides ColdSpring the information it needs to create a remote version of the UserService CFC. Note the class attribute for this bean is given the value of a ColdSpring CFC (RemoteFactoryBean) that does this work. This CFC is part of the ColdSpring code download.
The various property tags are used for the following purposes:
- target - the name of the CFC that we want ColdSpring to create a remote version of. In this example the value is userService since that CFC has the functions we want to call from the Flex application.
- serviceName - the name we want ColdSpring to give to the remote CFC. In this example the value is userServiceRemote and that will be the value we use for the source attribute of the mx:RemoteObject component in the Flex application.
- beanFactoryName - the name of the bean factory that is in application scope. We setup this bean factory name in our application.cfm file. In this example the bean factory is named beanFactory, so we need to tell ColdSpring that name since its possible for you to give the bean factory a different name.
- relativePath - this is the relative path from the web root where ColdSpring will write the remote version of the CFC. In this example, I want ColdSpring to write the remote CFC in the model folder that is under ColdSpring/Examples/JustColdSpring (remember ColdSpring is under my web root).
- remoteMethodNames - the names of the those methods in the original CFC (UserService) that we want to have written into the remote version (UserServiceRemote). In this example we want a remote version of the getUserByID function. Note that you can use an * to specify all methods that start with a certain word. For example, you could use get* as the value and ColdSpring would create a remote version of every method that starts with the word get.
application.cfm
<!---create the userServiceRemote object that can be used by a Flex
application. See services.xml file bean definition for userServiceRemote--->
<cfset application.beanFactory.getBean("userServiceRemote") />
I added the above line to the inner if statement ( cfif not structKeyExists(application,"beanFactory") or structKeyExists(url,"reloadApp") ) in my application.cfm. So if the beanFactory has not yet been created and placed in the application scope (or if reloadApp is specified in the URL), ColdSpring will create the beanFactory and will also create the userServiceRemote CFC object. So now we have a userServiceRemote object that our Flex application can connect to.
The Flex Example Application
In the flex folder you'll find a Flex project named JustCSFlex. This is just a basic test of connecting a Flex application to the backend ColdFusion userServiceRemote CFC that ColdSpring created for us. If you run this Flex application and click on the button you should see an alert box with userFirstName = "Bruce" and userLastName = "Phillips" if everything is working correctly.
The source value of the mx:RemoteObject tag is "coldspring.examples.JustColdSpring.model.userServiceRemote". This value points to the CFC that ColdSpring created for us.
Notes:
Prior to running the Flex application, you must have loaded index.cfm (which will cause application.cfm to run) in the web browser. You only need to do this once unless you make a change to your CFCs or services.xml. If you do make a change, just reload index.cfm with the reloadApp URL variable (for example: http://localhost:8500/coldspring/examples/JustColdSpring/index.cfm?reloadApp=1 ).
The first time you run index.cfm (or run it again with reloadApp URL variable) ColdSpring will create the UserServiceRemote CFC (or over write the CFC if it exists).
Summary
It was relatively easy to have ColdSpring create a remote version of the CFC that we could use in our Flex application. Thank you to Brian Rinaldi (see reference 1) for providing a good example of how to use ColdSpring to do this. Read his blog entry and the ColdSpring documentation for a more advanced explanation of what is happening when you use this technique.
ColdSpring enables us to easily extend the functionality of our service CFCs so that they can be used with Flex and within a standard ColdFusion application. I did not need to modify the UserService CFC at all, so the developers working on the application can continue to use that CFC and not worry about what I'm doing with the Flex part of the web application.
References:
- Remote Synthesis Blog, Objects and Composition - Connecting To Flex
- Developing With ColdSpring, ColdSpring and Remoting
- Code Example For This Blog Entry, Just ColdSpring With Flex
The Remote Proxy Bean generated by ColdSpring can also be used as the destination for web service or AJAX calls. So it isn't specific to Flex, though that is a common use of this functionality.
The Remote Proxy Bean can also have AOP interceptors attached to it, if you need to perform additional processing before or after the method call. This can be very useful for converting queries to arrays of CF Value Objects that Flex will translate into ActionScript Value Objects, for example.
With the most recent version of ColdSpring, you can specify "constructNonLazyBeans=true" in the init() method of the Bean Factory. This means that you don't have to manually do a getBean() request for the Remote Proxy. You still need to make at least one request to the application so that ColdSpring will be properly instantiated, but at that time it will automatically generate the Remote Proxy Beans (as long as they aren't explicitly specified to use lazy-init).
I do have one piece of advice I'd like to offer. You had mentioned, "Prior to running the Flex application, you must have loaded index.cfm (which will cause application.cfm to run) in the web browser."
This actually isn't necessary if you're using Application.cfc instead of Application.cfm. If you call a CFC with RemoteObject in Flex, Application.cfc is automatically called. You could then create your beanFactory in the onApplicationStart() method as opposed to doing it in a <cfif> block in Application.cfm.
I'm actaully using onError() in Application.cfc with a Flex app with great success. Just thought I'd mention this.
Thanks,
Dutch Rapley