Archive for June, 2009

Southern Irish Farmers

Well, I had my first round of golf in the Tennessee heat yesterday, and came to understand why the Irish emigrated to areas like Boston, New York, Pittsburgh, and Canada. We just ain’t meant for this kind of weather.

Normally, I like to tee about between 6:30 AM and 8:00 AM – even back when I was in Pittsburgh – because that means my round is done when the sun can do the least amount of damage, but our tee time was for 9:15 AM which meant that we started the back nine just before noon.

The first inkling that something was wrong happened on hole 12. I was on the green, and the world shifted slightly and I got a bit dizzy. It was only for a second, so I drank half of a liter of water and tried to stay in the shade, but by the next hole, I realized that something was wrong.

The heat and sun were just too much. Luckily, modern science has created Coppertone Sport which I applied very liberally throughout the morning (and I still got dangerously close to a burn) and saved me from complete agony.

Lesson learned: Play golf between March and May, or October and November, and if it’s in the summer, I have to either only play nine, or tee off at 7:00 AM.

It’s good thing that potatoes don’t like extreme heat, because red-headed, fair skinned, blue eyed Irish farmers couldn’t have survived here.

P.S. If you like in Nashville, and haven’t played it before, I highly recommend Forrest Crossing. It was a beautiful, well-maintained course with just the right mix of hard and easy holes.

LiveCycle Data Services 3 on Adobe Labs!

Can’t wait to play around with it!

LCDS 3 on Adobe Labs

ColdFusion Developers are Suckers

You know why? Because you guys and gals feed the trolls.

Every so often, someone comes along and says “ColdFusion is outdated and dying,” or “Don’t waste your time learning such an antiquated and proprietary language, no one uses it anyways.” Of course, anyone with a brain knows that these people are 1 of 2 things…

  1. Selling themselves, because if they were in the business of sharing knowledge, they wouldn’t purport such an ignorant viewpoint of application technology.
  2. Trying to drive traffic to their site. If there’s one way to bump up your traffic, it’s to draw the ire of the ColdFusion development community.

Next time this happens, just let a few people evenly comment on how misinformed or self-serving the article is and leave it at that. No need to leave 400 comments, have 50 articles on other blogs published attacking the person, and have a Twitter storm for a week, because all that does is serve his/her interests.

I know this is hard to do, especially when someone puts your livelihood in a negative light, but often the best thing to do is let the article evolve into the trashbin of obscurity, where it belongs.

1   Preface

At work, we’re investigating using ColdFusion Event Gateways to handle certain complex types of communication between our Flex user interfaces and ColdFusion, so yesterday I jumped on Google and started researching and ran into some roadblocks. However, after some monkeying around and more poring over of documentation and articles, I finally got a basic example working.

As usual, now that I’ve discovered how to set up a somewhat advanced feature of a platform, I’m sharing the knowledge in a comprehensive article. The documentation available for getting ColdFusion and Flex to communicate via event gateways was scattered, incomplete, or incomprehensible. In many of the articles, there were a lot of words, but little or no code, which does not help developers at all. Don’t tell me how it works, SHOW me how it works.

2   Creating a ColdFusion Listener Component

The listener component is the ColdFusion code that will receive any message sent from your Flex client via the DataServicesMessaging gateway type in your ColdFusion admin (more on that later). The basic structure is simple – just need one method named onIncomingMessage() in your component.

Create a file called InterceptFlex.cfc somewhere in your webroot and put the following code in it.

InterceptFlex.cfc

<cfcomponent output="false">
   <cffunction name="onIncomingMessage" returntype="any">
         <cfargument name="event" type="struct" required="true" />

	</cffunction>
</cfcomponent>

3   Setting Up Your Event Gateway

Now you need to go to your ColdFusion Administrator so that you can create an event gateway that specifies that any message coming in on a certain destination will be sent to the InterceptFlex component.

3.1   Destinations

There is a destination already set up for you in the \WEB-INF\flex\services-config.xml file (or \WEB-INF\flex\messaging-config.xml file if you are running BlazeDS) called ColdFusionGateway, and we’re just going to use that for this example.

You just need to make one change for this sample application to work. Open up the XML file and find the ColdFusionGateway destination. In the <properties> block add the following server property:

<properties>
   <server>
      <durable>false</durable>
      <allow-subtopics>true</allow-subtopics>
   </server>

   ...
</properties>

3.2   Gateway Setup

Now, go to the Gateway Instances section of your ColdFusion Administrator and start creating a gateway.

  1. The gateway ID can be anything, and you can just call it “test” for now.
  2. Select DataServicesMessaging as the type.
  3. The CFC path is the physical path to your InterceptFlex.cfc file you created.
  4. the configuration file is located in the \WEB-INF\cfusion\gateway\config\ directory, and you can use the one already set up named flex-messaging-gateway.cfg. So find that file and enter the path here.
  5. Click the Add Gateway Instance button.
  6. Start the gateway instance you just created.

4   Sending Messages From Flex

This application is a slight modification from the code provided in the Adobe article Introduction to the Flex Message Service, which I highly recommend you read if you’re new to Flex Messaging.

Create a new Flex application called Chat and paste this code into the Chat.mxml file. This code will connect to the ColdFusionGateway destination and send the message object to ColdFusion. ColdFusion, in turn, uses the event gateway instance we set up to send that object to the onIncomingMessage() method of the InterceptFlex.cfc component.

<?xml version="1.0" encoding="iso-8859-1"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns="*"
    pageTitle="Simple Flex Chat" creationComplete="createChat()">

    <mx:Script>
        <![CDATA[

        import mx.messaging.Consumer;
        import mx.messaging.Producer;
        import mx.messaging.events.MessageAckEvent;
        import mx.messaging.events.MessageFaultEvent;
        import mx.messaging.events.MessageEvent;
        import mx.messaging.messages.AcknowledgeMessage;
        import mx.messaging.messages.AsyncMessage;
        import mx.utils.ObjectUtil;

        private var chatPublisher:Producer;
        private var chatSubscriber:Consumer;

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

            chatSubscriber = new Consumer();
            chatSubscriber.addEventListener(MessageAckEvent.ACKNOWLEDGE, onConsumerAck);
            chatSubscriber.addEventListener(MessageEvent.MESSAGE, receiveChatMessage);
            chatSubscriber.destination = "ColdFusionGateway";
            chatSubscriber.subtopic = "simpleChat";
            chatSubscriber.subscribe();
        }

        private function onProducerFault(faultEvent:MessageFaultEvent):void
        {
            output.text += "[Error: " + faultEvent.message.toString() + "]\n";
        }

        private function onConsumerAck(ackEvent:MessageAckEvent):void
        {
            output.text += "[Got ack for subscribe or unsubscribe operation]\n";
        }

        // Note: these are the event-handling methods from above, now moved into the separate source file:

        private function sendChatMessage():void
        {
            var msg:AsyncMessage = new AsyncMessage();
            msg.body = input.text;
            msg.headers["username"] = "Me";
            msg.headers["gatewayid"] = "test";
            chatPublisher.subtopic = "simpleChat";
            chatPublisher.send(msg);
            input.text = "";
        }

        private function receiveChatMessage(msgEvent:MessageEvent):void
        {
            var msg:AsyncMessage = AsyncMessage(msgEvent.message);
            output.text += msg.headers["username"] + ": " + msg.body + "\n";
        }
        ]]>
    </mx:Script>

    
    <mx:Panel title="Simple Flex Chat">
        <mx:TextArea id="output" width="500" height="220" />
        <mx:TextInput id="input" width="500" enter="sendChatMessage()" />
        <mx:ControlBar horizontalAlign="center" width="500">
            <mx:Button id="clearBtn" label="Clear" click="output.text =''" />
        </mx:ControlBar>
    </mx:Panel>

</mx:Application>

5   Respond to the Flex Client

Now that ColdFusion has received the message, we’re simply going to respond back. You can enhance this to do anything you wish – send out emails, update database tables, log messages – but for now we’re just going to send a message back that let’s the Flex client know that the mechanism works.

<cfcomponent output="false">
   <cffunction name="onIncomingMessage" returntype="any">
      <cfargument name="event" type="struct" required="true" />

      <cfscript>
      x = structNew();
      x.body = "hello right back at ya";
      x.destination = "ColdFusionGateway";
      x.headers = structNew();
      x.headers['username'] = "System";
      x.headers['DSSubtopic'] = "simpleChat";
      x.lowercasekeys = "yes";
      </cfscript>

      <cfreturn x />
   </cffunction>
</cfcomponent>

One of those esoteric details that took me forever to find out was how to apply a subtopic to a message in ColdFusion. In Flex, it’s absurdly simply, you simply say message.subtopic = “myTopic”;, but in ColdFusion, you have to set a header key named DSSubtopic with the topic name (see above).

6   Conclusion

To be safe, restart your ColdFusion instance, then fire up the simple Flex chat app and type in a message. After a few seconds, you will receive a message from System in the history box.

After several hours of trying everything I could think of, I finally discovered what was causing the error from my previous post.

Unable to find the Flex adapter for destination ColdFusionGateway
 in the RMI registry on localhost:1099.

The Flex adapter may not be running or the destination may be incorrect.

The error occurred in C:\ColdFusion8\servers\cfusion\cfusion-ear\cfusion-war\webapps\test\scribble.cfm: line 24

22 : x.body = "hello world";
23 : x.destination = "ColdFusionGateway";
24 : sendGatewayMessage("test", x);
25 :
26 :</cfscript>

In the configuration file for the gateway, I had set the allowedIPs property to 127.0.0.1 so that it could only be testing from my machine. Well, for some reason, that was preventing the gateway from working. As soon as I commented out that property, it started to work.

# [Optional] The IP address or addresses of the Flex hosts that
# are allowed to connect and send messages to the Gateway.
# For multiple Flex servers, use a comma separated list: 10.60.1.1,10.60.1.2.
# If not specified, only this host is allowed.
#allowedIPs=127.0.0.1

I noticed comment “If not specified, only this host is allowed”, but it should read “If not specified, only this host is allowed, and you should NOT specify local host”.