Accessibility

Table of Contents

Retrieving Drupal nodes with Flex 2

Creating the Flex application

Use the following steps to create the Flex application.

  1. Open Flex Builder 2 and create a new Flex project of type Basic. I named my Flex project AMFPHPDrupal.
  2. Create a services-config.xml file to describe your service. Create this file anywhere in your project and give it the name services-config.xml. I created a folder in my project called "services" and placed it there.
  3. In this file, you'll want the following code. You will need to specify the <endpoint uri="" to reflect the location of your own installation of the AMFPHP module:

    <?xml version="1.0" encoding="UTF-8"?>
    <services-config>
        <services>
            <service id="amfphp-flashremoting-service"
            class="flex.messaging.services.RemotingService"
            messageTypes="flex.messaging.messages.RemotingMessage">
                <destination id="amfphp">
                <channels>
                    <channel ref="my-amfphp"/>
                </channels>
                <properties>
                    <source>*</source>
                </properties>
                </destination>
            </service>
        </services>
    
        <channels>
            <channel-definition id="my-amfphp" class="mx.messaging.channels.AMFChannel">
                <endpoint uri="http://your_drupal_install/services/amfphp" class="flex.messaging.endpoints.AMFEndpoint"/>
            </channel-definition>
        </channels>
    </services-config>
    
  4. Add a compiler directive for the services-config.xml file you just created by using the following steps:

    • Right-click your project in Flex Builder and select Properties.
    • In the Properties dialog box, select Flex Compiler.
    • In the "Additional compiler arguments" text field, you must add a directive that specifies to Flex the location of your services-config.xml file on your machine.

      In my case this file is in my default Flex Project location, and my directive looks like the block below. You will add something that starts with "-services":

      -locale en_US -services "/Users/your-user-name/Documents/Flex Builder 2/your-project-name/services/services-config.xml".

      Note: In my case it was necessary to provide the full path to the file, and this path reflects the Apple file system structure. This may not be necessary in your case. If you are using a different OS, specify the appropriate path.

    • Click OK in the Properties dialog box.
    • If you experience errors from Flex Builder that say that the services-config.xml file can't be found, then the path is wrong. If the path is wrong, an error will show up immediately in the Problems pane of Flex Builder. If no error messages appear, your services-config.xml file is being compiled into your project when you click Debug or Run.
  5. Add the code for the MXML application file. The code is provided below in bulk and commented, and detailed descriptions are provided afterward:

    <?xml version="1.0" encoding="utf-8"?>
    <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="430" height="270">
    
        <!-- set up a RemoteObject with which to access the services api -->
        <mx:RemoteObject id="node" fault="faultHandler(event)" showBusyCursor="true" source="node" destination="amfphp">
            <mx:method name="load" result="resultHandler(event)" />
        </mx:RemoteObject>
    
        <mx:Script>
            <![CDATA[
            //import the required packages and classes
            import mx.rpc.remoting.RemoteObject;
            import mx.rpc.events.ResultEvent;
            import mx.rpc.events.FaultEvent;
    
            //declare an object to store the data we retrieve
            [Bindable]
            public var resObject:Object;
    
            //declare an event handler to deal with the result
            public function resultHandler(event:ResultEvent):void {
    
                //set the bindable object to the value of the result
                resObject = event.result;
    
                //set the value of the TextArea to the title of the loaded node
                result_text.text = "Success! The title of your node is: " + event.result.title;
            }
    
    
            //declare an event handler to deal with a potential fault
            public function faultHandler (event:FaultEvent):void {
                //set the value of the TextArea to the fault in the event of failure
                result_text.text = "fault: " + String(event.fault);
            }
            ]]>
        </mx:Script>
    
    <!-- note that by naming a RemoteObject the same as the Drupal service, we get a relative mirror of the Services and Drupal api;
        "node" - the service
        "load" - the method
        "node.load" - clear & concise -->
    
    <!-- set up simple ui elements to invoke the service & display the result -->
    <mx:Button id="btn" label="Load that node!" click="node.load(1);" width="115" bottom="5" right="15"/>
    <mx:TextArea width="400" height="200" id="result_text" horizontalCenter="0" verticalCenter="0"/>
    <mx:Label text="Result:" left="15" top="10"/>
    </mx:Application>
    

Here's a quick piece-by-piece analysis of the really important pieces of the MXML application file:

  1. Declare the RemoteObject and method with which you will connect to the node service, which looks like the following code:

    <mx:RemoteObject id="node" fault="faultHandler(event)" showBusyCursor="true" source="node" destination="amfphp">
    	<mx:method name="load" result="resultHandler(event)" />
    </mx:RemoteObject>
    

    Where...

    • The id attribute of the RemoteObject is local to the Flex project, specific to the RemoteObject, and is not associated with the services-config.xml file.
    • The source attribute of the RemoteObject is the node service, identified by its name, "node."
    • The destination attribute of the RemoteObject matches the destination ID of the service declared in the services-config.xml file,
    • The single <mx:method name> is the method of the node service you wish to call. Additional methods would be added in the same fashion.
    • The remaining code refers primarily to event handlers and user feedback during retrieval.
  2. Import the classes and packages you need, which looks like this:

    import mx.rpc.remoting.RemoteObject;
    import mx.rpc.events.ResultEvent;
    import mx.rpc.events.FaultEvent;
    
  3. Declare the button used to invoke the call to the service, which looks like this:

    <mx:Button id="btn" label="Load that node!" click="node.load(1);" y="{result_text.y + result_text.height + 20}" x="{result_text.width - btn.width}"/>
    

    Where...

    • The click event uses the ID you gave your RemoteObject to send the request with a node ID of 1. In my case this is a Drupal page with a title of "TestPage." You can change the node ID to any node that you have published in Drupal.

Make sure you have saved the changes made to your MXML application file and click Debug in Flex Builder. Once the application has launched, click "Load that node!" and wait for a result. If you have assembled these pieces correctly, you will see output in the TextArea that looks something like the following:

Success! The title of your node is: Your node title

Troubleshooting

Here are some common problems you might encounter and their probable causes:

  • For this example to work, at least one user must be logged in to your Drupal installation. This is due to Drupal's permission system. Permissions can be configured on a per-module basis, and Drupal provides contributed modules to expand upon the core permission functionality. You can configure the relevant permissions for the Services module at: http://your_drupal_install/admin/user/access.

    Drupal also provides developer-contributed modules that can, among many other things, expand the core permissions functionality. See the Drupal Module pages for a complete categorized listing of contributed modules.

  • If you experience errors at the AMFPHP - /services/amfphp link, make sure that you have the AMFPHP version 1.9. beta, not the AMFPHP version 2 beta . The AMFPHP 1.9 Beta contains method calls that enable the Services module to override the default AMFPHP gateway and make services available via Drupal directly. As of the time of this writing, these methods were missing from the AMFPHP Beta 2 package. Check the PHP category of the 5 1/2 blog, maintained by Patrick Mineault for any potential updates to this beta, and keep up to date with official AMFPHP distributions at AMFPHP.org.
  • Drupal states that it supports PHP 4.3.0 or greater for much of this functionality to work, however this has not been the experience of myself and others. To avoid any potential problems that may be nebulous and difficult to identify, apply this tutorial to an installation of PHP 5.2.x.

In this tutorial you've accomplished much more than the simple face value task of retrieving a node from Drupal. Rather, upon completion of this tutorial you've armed yourself with a stable, modular, extensive and entirely cost-free back end with which to build Flex and Flash applications for your clients or business. In conjunction with the power of the Flex SDK, the Flex Builder development environment, and the visualization capabilities of Flex components, you wield an impressive set of tool. For development of rich Internet applications and websites for use in low to medium bandwidth and traffic environments, this developer thinks this combination is just the ticket.

Where to go from here

As noted in my conclusion, the possibilities are myriad. For instance, you might leverage Drupal's contributed Flash Video module, Flash Media Server (or ffmpeg) and Flex to create a next-generation video website with the ease of use and the extensibility of Flex components. Or, perhaps you might create a video encoder/decoder for a production environment that could be used by a group of employees, online, concurrently. Drupal's community, networking, and content aggregation/syndication features could be leveraged in conjunction with Flex to create very usable and efficient corporate intranets or management applications. You could develop the next step in social networking websites with new and enticing features that Flex can facilitate at very low cost. The possibilities are exciting.

If you are not already, you take this opportunity to familiarize yourself more with the Drupal framework, node and theme systems, core and contributed modules, and APIs to get a good idea of exactly how powerful and viable this combination of technologies can be. Drupal includes a very solid core group of modules and content-types out of the box, and the list of contributed modules is growing at a pace that is effectively impossible to keep up with. The Drupal community is large, perpetually growing and, largely, very helpful to beginners. The Drupal forums are a great resource for tracking down specific solutions to issues or requesting help with a problem. You might also consider joining Drupal groups that pertain to your specific development needs or interests at groups.drupal.org. Understanding the Services module framework will also be important if you intend to develop your own services for use in your applications. Check out the beginnings of the Services module handbook.

I hope you've found this tutorial to be helpful and inspiring. Happy "Flupaling"!