[FDS-128] Using FusionDebug to debug Flash Remoting and Gateway Messaging Requests

Description

Debugging Flash Remoting and Gateway Messaging

Non-Intrusive debugging has been introduced in FusionDebug 3.5, which allows breakpoints to only fire when requests are coming from a specified IP address. This makes it possible for a developer to debug and set breakpoints against a central server, leaving the system untouched and unaffected for everyone else.

This article will demonstrate that the breakpoint IP filter can be used to debug Flash Remoting and Gateway Messages. In order to demonstrate that FusionDebug’s non-Intrusive debugging functionality is effective across a wide range of message types, below is a short example of testing the filter functionality in regards to Flash Remoting messages and Gateway messaging. I have based these tests on the test classes found at http://www.cftips.net and http://www.fusioncube.net .

Flash Remoting

I created a Flex project with an mxml file containing a script that has two functions; a function that simply populates a data grid with the results returned by a remote CFC and a second function that accepts a fault event and displays an error message in case of problems. I also need a remote object call specifying a destination named ColdFusion (which is configured with the appropriate channel for the passing of messages) and specified the location of the CFC you would like to access as well as creating a data grid to store the retreived results.

Remoting.mxml
<mx:Script>
      <![CDATA[
            import mx.controls.Alert;
            import mx.rpc.events.FaultEvent;
            import mx.rpc.Fault;
            import mx.rpc.events.ResultEvent;
            
            private function result(evt:ResultEvent):void {
            	mygrid.dataProvider = evt.result;
           }

            private function fault(evt:FaultEvent):void {
                  Alert.show(evt.fault.message);                 
            }
      ]]>
</mx:Script>

<mx:RemoteObject id="mycfc" destination="ColdFusion" showBusyCursor="true" source="flashRemote" result="result(event)" fault="fault(event)">
</mx:RemoteObject>     
      <mx:Button label="Button" click="mycfc.GetData()"/>
      <mx:DataGrid id="mygrid" width="487" height="169"/>
</mx:Application>

Below are some changes that I found needed to be made to CF8 and CF9 Application servers’ configuration before the Flash Remoting test class would function correctly;
Within flex-messaging-gateway.cfg. If your Flex server is installed as part of your CF app server, comment out localhost ‘#host=localhost’. Specify ‘localhost’ if Flex is on this machine but not installed as part of ColdFusion.

For the Remoting-config.xml add the following code within the “ColdFusion” destination properties . You are setting use-mappings to true and setting the method-access-level to remote. use-mappings is a Boolean value specifying whether the source attribute can be relative to a ColdFusion mapping. Changing the method access level to remote basically specifies the access attribute values the destination CFC must have for ColdFusion to respond to the request. The code within the property-case tags simply state to make query column names, and structure keys lowercase when converting to ActionScript.

Remoting-config.xml
<destination id="ColdFusion">
   <channels>
      <channel ref="my-cfamf"/>
   </channels>
   <properties>
      <source>*</source>
   <access>
      <use-mappings>true</use-mappings>
      <method-access-level>remote</method-access-level>
   </access>
.....

Next you will need to adjust the access rights within the CFC function definition. Placing in whatever access level has been defined within the Remoting-config.xml. Flex can can access functions that are both remote or public. This CFC server side can just be a simple database query, so long as the function returns data to populate the data grid. The CFC in this example performs a query on a table within a defined data source. If you wanted to do the same, simply create a table within MYSQL or MSSQL and set it as a data source within the ColdFusion administrator.

Destination.cfc
<cffunction name="GetData" access="remote" returntype="query">


Configuring FusionDebug

Start up Eclipse with the FusionDebug Plug-in installed. Create a new Debug Configuration (Run->Debug Configurations…) for FusionDebug and configure the debugging port for your app server. In the IP Restrictions enter the IP address(es) of the server(s) that you want breakpoints to fire for. This means that when the request originates from one of the IP addresses you’ve entered it, the breakpoint should fire but for other requests the breakpoint will be ignored.

You then will have to navigate to the Source Code Lookup tab. Here you will simply need to select the project you want to debug and reference it’s source in the directory. Add the lookup and you are ready to start debugging.

Start debugging by pressing the Debug button at the bottom of the debug configuration screen. Once the debugger is attached open the CFC and add some breakpoints where you want to stop execution of the code.

Now run your Flex application up and make a request from an IP address that is in the list of IP Restrictions. FusionDebug halts the activity for only the flash remoting requests whose IP addresses have been entered into the IP filter, so if you make a request for a different machine then the breakpoint doesn’t fire. If you are using an app server on your local machine, CF8 and CF9 use loopback addressing and as a result uses the Ipv6 address 0:0:0:0:0:0:0:1 for localhost if you are using Windows Vista or 7 operating systems.

Whereas request from clients that are not in the IP restrictions list run to completion without the breakpoints firing! That’s Non-Intrusive Debugging!


Messaging Gateways

Below is a short example of testing the non-Intrusive debugging functionality in regards to ColdFusion Gateway messages.

Create a Flex project with a main mxml that contains a script block with a function that creates a producer and consumer object along with event listeners and remote destinations.

MessagingGatewayTest.mxml
import mx.messaging.Consumer;
import mx.messaging.Producer;

private var publisher:Producer;
private var subscriber:Consumer;

private function createChat():void
{
   publisher= new Producer(); 
   publisher.addEventListener(MessageFaultEvent.FAULT, producerFault);
   publisher.destination = "ColdFusionGateway";

   subscriber= new Consumer();
   subscriber.addEventListener(MessageAckEvent.ACKNOWLEDGE, acknowledge);
   subscriber.addEventListener(MessageEvent.MESSAGE, receiveMessage);
   subscriber.destination = "ColdFusionGateway";
   subscriber.subtopic = "test";
   subscriber.subscribe();
}

The you will need to write a function for the handling of the acknowledgement event from the consumer, functions for sending and receiving messages and a function for handling a fault event from the producer.

MessagingGatewayTest.mxml
private function producerFault(faultEvent:MessageFaultEvent):void
{
   output.text += "[Error: " + faultEvent.message.toString() + "]\n";
}
private function acknowledge(ackEvent:MessageAckEvent):void
{
   output.text += "[Contact with the Consumer has been established.]\n";
}

private function sendChatMessage():void 
{
   var msg:AsyncMessage = new AsyncMessage();
   msg.body = input.text;
   msg.headers["uname"] = "tester";
   msg.headers["gatewayid"] = "flexgateway";
   publisher.subtopic = "test";
   publisher.send(msg);
   input.text = "";
}

private function receiveMessage(msgEvent:MessageEvent):void
{
   var msg:AsyncMessage = AsyncMessage(msgEvent.message);
   output.text += msg.headers["uname"] + ": " + msg.body + "\n";
}

Within the content root of your CF app server (a.k.a wwwroot folder) you should place the CFC that you are using to interact with. This will contain a function that will return a message to the caller via the same destination and channel.

InterceptFlex.cfc
<cfcomponent output="false">
   <cffunction name="onIncomingMessage" returntype="any">
         <cfargument name="event" type="struct" required="true" />	 
	  <cfscript>
		x = structNew();
	        x.body = "Hello Friend";
		x.destination = "ColdFusionGateway";
		x.headers = structNew();
		x.headers['uname'] = "system";
		x.headers['DSSubtopic'] = "test";
		x.lowercasekeys = "yes";
      </cfscript>
   <cfreturn x /> 
 </cffunction>
</cfcomponent>

Some changes that may need to be made to CF8 and CF9 Application servers’ configuration before Flash Gateway usage, the first being within the corssdomain.xml file, make sure the contents allows all domain policies, all domains and all ports. Obviously there would be security issues with the following changes, but since this is just an example of Flash Remoting we will allow all ports and domains, but in reality these should be appropriately restricted.

crossdomain.xml
<cross-domain-policy>
   <site-control permitted-cross-domain-policies="all" />
   <allow-access-from domain="*" secure="false" to-ports="*"/>
   <allow-http-request-headers-from domain="localhost"/>
</cross-domain-policy>

Within the messaging-config.xml set the server properties as shown below within the destination “ColdFusionGateway” properties.

messaging-config.xml
<destination id="ColdFusionGateway">
   <adapter ref="cfgateway" />
      <properties>		
         <server>
            <durable>false</durable>
            <allow-subtopics>true</allow-subtopics>
         </server>
.....

A subtopic is a property of both the producer and consumer components, within the xml you are configuring the destination “ColdFusionGateway” to allow the subtopic to be used as a message destination. Setting the server configuration durable to false allows for messaging without the JMS (Java Messaging Service) API. If you are running Flex server with ColdFusion comment out the “host=localhost” line within the flex-messaging-gateway config file. This is located within the root ColdFusion directory \gateway\config\, else if Flex is on this machine but not installed as part of ColdFusion specify localhost.

You can configure your app server gateways for CF8 and CF9 as shown below in order to create the appropriate gateway needed for this example:

CF8

CF9

The counter of your Gateway should be 0 before the test has been executed. After the test is run both the ‘in’ and ‘out’ counter should display one message each in their fields (The in-going message being the call for the CFC via the ColdFusion channel. The outgoing message being the response from the CFC I.E. the body of the cfscript) When the program is first launched you should see the confirmation of contact from the Consumer.

Once some message has been entered, you should then see the message coming from the CFC.

FusionDebug halts the process of the CFC for specific users listed within the IP Restriction configuration options. All IP’s not entered within the filtering box will simple run the app as normal.


Conclusion

The non-Intrusive debugging feature ultimately provides a development team with the ability to debug their code without affecting other team members. It could even be that you need to debug a request from a specific client because they are the only one that experiences a problem. Non-Intrusive debugging can be used here to filter the requests that fire the breakpoints to only the problem client. This results in saving time and allowing bugs to be spotted earlier on within the development stage of production and can also lead to decreasing time consumed by debugging newly implemented components.

Source Code: FD128source.zip

Issue Details

Type: DevNet
Issue Number: FDS-128
Components: Breakpoints
Environment:
Resolution: Fixed
Added: 10/11/2010 11:45:34
Affects Version:
Fixed Version: 3.5
Server:
Platform:
Related Issues: None

Comments are closed.