I know (or want to believe) that this is actually quite easy... it must be. Here's the deal: I want to access an existing ColdFusions component (CFC) from inside a Flex2 app. I'm experienced with Flash Remoting and can call my CFCs just fine from Flash.
Now I'd like to port things to Flex2 but I am having trouble understanding some concepts. I went ahead and installed Flex2, Flex Data Services (FDS) and ColdFusion 7.0.2 on my laptop. First problem: I didn't understand if Flex Data Services was needed or not... I thought ColdFusion 7.0.2 provided some sort of Remoting gateway for flex2 yet this part of the Flex2 docs seems to suggest that RemoteObject can only be used with FDS - I know now that this does not seem to be the case as I managed to call a CFC on my local CF server using RemoteObject without FDS running. So what am I missing? Is the RemoteObject class different from the MXML tag that I am using? And if it isn't then why do the docs suggest 'FDS only'?
Here's the MXML snippet that works fine for me locally using Flex2 and CF 7.0.2 (no FDS running):
I gather that the destination 'ColdFusion' is somehow configured in Flex's services-config.xml - how and why I haven't yet grasped. The 'names' in my RemoteObject tag is the CFC on my local machine and the getname is hte method in the CFc that I call. This works fine, no problem. But I don't understand how I would access a remote CFC using this code... Do I have to edit XML files and create a destination for every site that uses Remoting? That sounds a bit crazy and the XML config scared me a bit...
But all I got in Flex was this error:
I didn't quite understand this error as the method should return a string - but it was clear that it was throwing an error.
Try this link to see the CFC working in a browser (it should return the string stoem).
Please somebody, anybody, help! What I want to do is access a remote CFC with minimum fuss from Flex, ideally just using a RemoteObject MXML tag. Is that possible and if so, how? I'm trying hard to find the R in RAD here. I think the whole Flex Remoting/FDS/CF thing is really tough to grasp, even for someone who's familiar with Remoting.
Now I'd like to port things to Flex2 but I am having trouble understanding some concepts. I went ahead and installed Flex2, Flex Data Services (FDS) and ColdFusion 7.0.2 on my laptop. First problem: I didn't understand if Flex Data Services was needed or not... I thought ColdFusion 7.0.2 provided some sort of Remoting gateway for flex2 yet this part of the Flex2 docs seems to suggest that RemoteObject can only be used with FDS - I know now that this does not seem to be the case as I managed to call a CFC on my local CF server using RemoteObject without FDS running. So what am I missing? Is the RemoteObject class different from the MXML tag that I am using? And if it isn't then why do the docs suggest 'FDS only'?
Here's the MXML snippet that works fine for me locally using Flex2 and CF 7.0.2 (no FDS running):
<mx:RemoteObject id="RO" destination="ColdFusion"
fault="Alert.show(event.fault.message), 'Error'"
result="Alert.show(String(event.result)), 'Result'"
source="names">
<mx:method name="getname">
</mx:method>
</mx:RemoteObject>
fault="Alert.show(event.fault.message), 'Error'"
result="Alert.show(String(event.result)), 'Result'"
source="names">
<mx:method name="getname">
</mx:method>
</mx:RemoteObject>
I gather that the destination 'ColdFusion' is somehow configured in Flex's services-config.xml - how and why I haven't yet grasped. The 'names' in my RemoteObject tag is the CFC on my local machine and the getname is hte method in the CFc that I call. This works fine, no problem. But I don't understand how I would access a remote CFC using this code... Do I have to edit XML files and create a destination for every site that uses Remoting? That sounds a bit crazy and the XML config scared me a bit...
So what I tried (to access the same CFC but this time on a remote CF box running CF 7.0.2) was to set an endpoint in my RemoteObject tag, pointing to my FlashRemoting gateway. Is that one way of achieving what I want or am I barking up the wrong tree?
Here's what I tried:
<mx:RemoteObject id="RO"
endpoint="http://web.okaygo.co.uk/flashservices/gateway"
fault="Alert.show(event.fault.message), 'Error'"
result="Alert.show(String(event.result)), 'Result'"
source="cfc.flex" >
<mx:method name="getname">
</mx:method>
</mx:RemoteObject>
endpoint="http://web.okaygo.co.uk/flashservices/gateway"
fault="Alert.show(event.fault.message), 'Error'"
result="Alert.show(String(event.result)), 'Result'"
source="cfc.flex" >
<mx:method name="getname">
</mx:method>
</mx:RemoteObject>
But all I got in Flex was this error:
TypeError: Error #1034: Type Coercion failed: cannot convert Object@9373841 to mx.messaging.messages.ErrorMessage.
I didn't quite understand this error as the method should return a string - but it was clear that it was throwing an error.
Try this link to see the CFC working in a browser (it should return the string stoem).
Please somebody, anybody, help! What I want to do is access a remote CFC with minimum fuss from Flex, ideally just using a RemoteObject MXML tag. Is that possible and if so, how? I'm trying hard to find the R in RAD here. I think the whole Flex Remoting/FDS/CF thing is really tough to grasp, even for someone who's familiar with Remoting.


http://mydomain/cfc/flex.cfc
Then this RemoteObject Tag should work.
<mx:RemoteObject
id="RO"
destination="ColdFusion"
source="cfc.flex"
fault="Alert.show( event.fault.message ), 'Error'"
result="Alert.show( String( event.result ) ), 'Result'"
>
<mx:method name="getname"/>
</mx:RemoteObject>
Stefan, Before you pull your hair out send me an email at tpatrick@adobe.com. Glad to see you Flexing! Keep going, it takes time.
Cheers,
Ted :)
But how and where do I tell Flex that I want to use the REMOTE CFC at http://web.okaygo.co.uk/cfc/flex.cfc ?
Do I need to modify the xml config file for that? It just isn't clear to me.
To recap: I want to run my Flex app on my local machien and access a remote CFC (and its methods) at http://web.okaygo.co.uk/cfc/flex.cfc
Ted, your example looks like it will work but only if I upload my compiled swf to mydomain.com. Otherwise how would the app know which URL's remoting gateway I want to use? I know all about CFC paths, I use remoting in Flash all day long. But in Flash I connect to the gateway and then call methods on my CFCs - in Flex I don't see (using your example) any mention of mydomain.com so how would Flex know which gateway to use? It looks like a relative path to me and I don't want that, I want to explicitly use a remoting gateway at web.okaygo.co.uk (the Flash Remoting gateway is web.okaygo.co.uk/flashservices/gateway).
I guess I don't even understand yet if Flex and Flash share the same remoting implementation.
thanks for any pointers
Stefan
The 'ColdFusion' destination as specified in Ted's example would be originating from the services-config.xml file with destination id="ColdFusion" which in turn refers to a channel my-cfamf which in turn specifies an endpoint that ends with /flex2gateway
This seems to be the gateway/URL that is used in mu local example. But I have to understand how I can specify another gateway, in particular the one at my remote site which is http://web.okaygo.co.uk/flex2gateway
Is the Flash Remoting gateway at web.okaygo.co.uk/flashservices/gateway useless in Flex?
Do I really need to mess with these scary looking XML files when I want to use Remoting on a remote server (which is what I need to do all the time)? Is this XML file being compiled into my Flex application? Is there another way to configure this? What would the XML look like in order to set up another Remoting location at web.okaygo.co.uk/flex2gateway ?
thx
i don't recall doing anything beyond setting the mapped dir option on (we have a lot of mapped cfc dirs). it just worked.
I didn't have to configure anything either to get remoting working via my LOCAL CF install - but how do I use a REMOTE remoting gateway? The server I use is web.okaygo.co.uk and it runs CF 7.0.2. How do I tell Flex that that's the gateway I want to use as that's where my CFCs live - they do not live locally.
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
creationComplete="ro.getData()"
layout="absolute">
<mx:RemoteObject
id="ro"
destination="ColdFusion"
source="api.search"
endpoint="http://www.flex.org/flex2gateway/">
<mx:method name="getData"/>
</mx:RemoteObject>
<mx:DataGrid dataProvider="{ro.getData.lastResult}" left="0" top="0" bottom="0" right="0"/>
</mx:Application>
There are several keys:
1. You need a crossdomain.xml file located here:
http://www.flex.org/crossdomain.xml configured to allow connection from the other domain or in this case "*" (All)
2. You need to add the 'endpoint' property to the RemoteObject to denote the gateway implicitly with an HTTP URL.
This was a pain! I will make sure to blog this one.
Ted :)
What I still do not understand is why I need to specify a desination AND and endpoint:
<mx:RemoteObject
id="ro"
destination="ColdFusion"
source="api.search" endpoint="http://www.flex.org/flex2gateway/">
<mx:method name="getData"/>
</mx:RemoteObject>
The docs state: "This property allows the developer to quickly specify an endpoint for a RemoteObject destination without referring to a services configuration file at compile time or programmatically creating a ChannelSet. It also overrides an existing ChannelSet if one has been set for the RemoteObject service."
But if I also need a destination then I am again referring back to the XML config file - which defeats the objective of being able to do everything in MXML.
I see the benefit of having the XML files but I want to understand how I can work without them. It seems strange to me that I would have to configure XML files on a local CF server in order to get flex to work with a remoting gateway on a REMOTE CF server...
I had some success myself. I created a simple XML config file and changed the endpoint ion XML to <endpoint uri="http://web.okaygo.co.uk/flex2gateway/" class="flex.messaging.endpoints.AMFEndpoint"/>
I then included this XML file (which is inside my Flex project directory) via the comoiler command line. That worked fine with this code then:
<mx:Script>
<![CDATA[
import flash.events.*;
import mx.controls.Alert;
private function init ():void
{
RO.getmyname();
}
]]>
</mx:Script>
<mx:RemoteObject
id="RO"
source="cfc.flex"
destination="ColdFusion"
fault="Alert.show( event.fault.message ), 'Error'"
result="Alert.show( String( event.result ) ), 'Result'"
/>
It still means I must use a destination. Trying to rename the destination name in XML as well as MXML also broke my app.
Ted's Flex remoting gateway seems to accept both syntaxes http://www.flex.org/flex2gateway/ and http://www.flex.org/flex2gateway and both work fine. I wonder why on my server it seems to require a trailing slash.
http://web.okaygo.co.uk/flex2gateway throws an error, http://web.okaygo.co.uk/flex2gateway/ works fine.
I am using IIS and not CF's built in webserver - could that have anything to do with it?
In any case, I modified my example and removed all compiler commandline options, meaning no XML files are being compiled into the Flex app anymore.
If I then run this code
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" applicationComplete="init()">
<mx:Script>
<![CDATA[
import flash.events.*;
import mx.controls.Alert;
private function init ():void
{
RO.getname();
}
]]>
</mx:Script>
<mx:RemoteObject
id="RO"
destination="ColdFusion"
endpoint="http://web.okaygo.co.uk/flex2gateway/"
source="cfc.flex"
fault="Alert.show( event.fault.message ), 'Error'"
result="Alert.show( String( event.result ) ), 'Result'"
/>
</mx:Application>
the app still works! I think this is what I wanted. But it seems to conflict with the docs on destination:
"The destination of the service. This value should match a destination entry in the services-config.xml file."
Well in my case it doesn't do that, I actually renamed my services-config file just to make sure that flex isn't somehow grabbing it anyway. My Remoting call still works now with no external configuration - great.
I hope we can continue to dig at this as there's still some loose ends that I don't quite understand.
That's cheating though :-) Please reconsider - Remoting in Flex DOES work and is more efficient than SOAP.
While I can get Remoting to work ok now both locally and remotely I still haven't grasped the whole setup and concepts yet.
I'll try Aactionscript based Remoting next in a pure AS3 class and see how that fits in... Oh joy.
Spare a moment for myself too... I'm just messing with an AS3 class in Flex2 and I get a NetConnection.Call.BadVersion Error when trying to call a CFC method... I tried both AMF0 and AMF3 and both returned the same error. I start to get the idea as to why you gave up man...!
The 'destination' is the name used within the remoting calls to locate resources. Basically there are 2 parts to a remoting address:
1. Endpoint - Denotes the URL of the gateway. The default is /flex2gateway/ on the server the SWF is running on. If you want to point to a remote server running remoting, you change this to a HTTP or HTTPS url.
2. Destination - When the gateway receives a call it needs to be routed to the right resources. This destination is denoted on the target server you are calling. In the CF case, it is configured within the CF server. With FDS, it is configured within the FDS server config xml files (hence the docs). When using Coldfusion, the default to use is: 'ColdFusion'
I think that should get you square. Sorry about the trouble on this.
Have faith Flex gets easier once you get the hang of it. You are going well!
Cheers,
Ted :)
One other question, I was going to install the ColdFusion Extensions for Flex (BuilderColdFusion_Flexbuilder_Feature.zip) but I can't seem to find it on my CF install on OS X. Know where this zip file is under OS X install?
@Mike: I think you should try and use a normal Flex project (not Remoting) and then simply use a similar approach to me where you tell the RO directly where your endpoint is. Also set the destination to ColdFusion and you should be ok.
Sorry no idea on the Extensions...
var ro:RemoteObject = new RemoteObject();
ro.destination = "ColdFusion";
ro.source = "getCCService";
ro.getCCInfo.addEventListener("result",getTest_result);
ro.getCCInfo.addEventListener("fault",somethingWentWrong);
ro.getCCInfo();
folde.subfolder.mycfc
Maybe give that a shot.
Sorry, maybe I am not understanding your exact setup and it may be easier to test this under 'normal' circumstances, without the additional complexity of this particular config.
Coldfusion is installed on the C:\CFusionMX7\ drive.
The web content is installed on the E:\inetpub\wwwroot\ drive.
the CFC component getCCService is right now located in C:\CFusionMX7\wwwroot\ and it is working.
looking at my xmldata from cfc arriving the alertbox was just heaven
lots of <3 ;-)
<mx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.rpc.remoting.RemoteObject;
import mx.rpc.events.ResultEvent;
import mx.rpc.events.FaultEvent;
private var profServicesRO:RemoteObject = new RemoteObject();
public function onInit():void
{
profServicesRO.source = "profservices.components.statistics";
profServicesRO.destination = "ColdFusion";
populateGraph1();
}
public function populateGraph1():void
{
profServicesRO.sayHello.addEventListener("result", populateGraph1Handler);
profServicesRO.addEventListener("fault", faultHandler);
profServicesRO.sayHello();
}
public function populateGraph1Handler(event:ResultEvent):void {
// Do something
Alert.show("THE SERVICE RETURNED BACK SUCCESSFULLY!","Returned");
}
public function faultHandler (event:FaultEvent):void {
// Deal with event.faultstring, etc.
Alert.show(event.fault.faultString, 'Error');
}
]]>
</mx:Script>
<?xml version="1.0" encoding="UTF-8"?>
<services-config>
<services>
<service id="coldfusion-flashremoting-service"
class="flex.messaging.services.RemotingService"
messageTypes="flex.messaging.messages.RemotingMessage">
<adapters>
<adapter-definition id="cf-object" class="coldfusion.flash.messaging.ColdFusionAdapter" default="true"/>
</adapters>
<destination id="ColdFusion">
<channels>
<channel ref="my-cfamf"/>
</channels>
<properties>
<source>*</source>
<!-- define the resolution rules and access level of the cfc being invoked -->
<access>
<!-- Use the ColdFusion mappings to find CFCs, by default only CFC files under your webroot can be found. -->
<use-mappings>false</use-mappings>
<!-- allow "public and remote" or just "remote" methods to be invoked -->
<method-access-level>remote</method-access-level>
</access>
<property-case>
<!-- cfc property names -->
<force-cfc-lowercase>false</force-cfc-lowercase>
<!-- Query column names -->
<force-query-lowercase>false</force-query-lowercase>
<!-- struct keys -->
<force-struct-lowercase>false</force-struct-lowercase>
</property-case>
</properties>
</destination>
</service>
</services>
<channels>
<channel-definition id="my-cfamf" class="mx.messaging.channels.AMFChannel">
<endpoint uri="http://YOUR-DOMAIN-OR-IP/flex2gateway/" class="flex.messaging.endpoints.AMFEndpoint"/>
<properties>
<polling-enabled>false</polling-enabled>
<serialization>
<instantiate-types>false</instantiate-types>
</serialization>
</properties>
</channel-definition>
</channels>
<logging>
<target class="flex.messaging.log.ConsoleTarget" level="Error">
<properties>
<prefix>[Flex] </prefix>
<includeDate>false</includeDate>
<includeTime>false</includeTime>
<includeLevel>false</includeLevel>
<includeCategory>false</includeCategory>
</properties>
<filters>
<pattern>Endpoint.*</pattern>
<pattern>Service.*</pattern>
<pattern>Configuration</pattern>
<pattern>Message.*</pattern>
</filters>
</target>
</logging>
so I need to use the config XML file? Is it not possible to specify the endpopint in AS code - this seems to be the only piece to the puzzle that's missing and not present in the AS version when compared to the MXML version of RemoteObject.
If there a way to map the files so they don't have to be in "cfusionmx7/wwwroot/" without affecting anything else that might use coldfusion on that server?
Did Stefan's last question ever get answered? How do you specify the endpoint in PureAS3? - I've been looking at ChannelSet, perhaps this is how it's done. Anyone?
I've just installed mamp and cf9 and for some reason my flex classes aren't mapping to the cfc's on the server. Have you had any issues with this?
They work on my remote server so I know the code is correct so it must be something to do with the way my vitual host is set up in mamp. here is my virtual host entry
DocumentRoot "/Users/cyberdaz/Sites/amwaymediaserver"
Alias /CFIDE "/Users/cyberdaz/Sites/CFIDE"
ServerName amwaymedia.local
</VirtualHost>
sorry but I'm not sure what could cause this. Most likely a path issue of some kind?