|
|
Want to know more about Packt's Article Network? Interested in contributing your article ideas? Please visit our FAQ for more information. See More BROWSE
All Titles WordPress Web Services SOA BPEL Web Graphics & Video Web Development RAW Portugues, Espanol, Italiano, French PHP/MySQL Oracle Open Source Networking & Telephony Moodle Microsoft & .NET Linux Servers jQuery Joomla! JBoss Java e-Learning e-Commerce Dynamics Drupal CRM Cookbook Content Management Beginner Guides Architecture and Analysis AJAX Future Titles Recently Published Titles |
Building a Web Service-driven Application with Flash in Drupal
So, let's take a step-by-step approach on how to accomplish this on the Flash side, which as far as I am concerned, is the fun side! Click here to access all the codes used in this article. Step 1: Creating our Flash applicationWith our chapter2 project open, we can shift our focus to the Actions panel within the Flash IDE. Although working with the Actions panel is great for small applications, we will eventually build onto this Flash application, which might make it impractical to keep all of our ActionScript code within the Actions panel. Because of this, we will first need to create a separate ActionScript file that will serve as our main entry point for our Flash application. This will allow us to easily expand our application and add to the functionality without modifying the Actions panel for every addition we make. Step 2: Creating a main.as ActionScript fileFor this step, we will simply create an empty file next to our chapter2.fla file called main.as. After you have created this new file, we will then need to reference it within our Actions panel. To do this, we will use the include keyword in ActionScript to include this file as the main entry point for our application. So, shifting our focus back to the chapter2.fla file, we will then place the following code within the Actions panel: include "main.as"; Now that we are referencing the main.as file for any of the ActionScript functionality, we will no longer need to worry about the Actions panel and add any new functionality directly to the main.as file. Now, for the following sections, we will use this main.as file to place all of our ActionScript code that will connect and extract information from our Drupal system, and then populate that information in a TextField that we will create later. So, let's jump right in and write some code that connects us with our Drupal system. Step 3: Connecting to DrupalFor this step, we will first need to open up our empty main.as file so that we can add custom functionality to our Flash application. With this file open in our Flash IDE, our first task will be to connect with Drupal. Connecting to Drupal will require us to make a remote call to our Drupal installation, and then handle its response correctly. This will require the use of asynchronous programming techniques along with some standard remoting classes built into the ActionScript 3 library. I will spend some time here discussing the class used by ActionScript 3 to achieve remote communication. This class is called NetConnection. Using the NetConnection classThe NetConnection class in ActionScript 3 is specifically used to achieve remote procedure calls within a Flash application. Luckily, this class is pretty straight forward and does not have a huge learning curve on understanding how to utilize it for communicating with Drupal. Using this class requires that we first create an instance of this class as an object, and then initialize that object with the proper settings for our communication. But let's tackle the creation first, which will look something like this in our main.as file: // Declare our Drupal connection Now, you probably noticed that I decided to name my instance of this net connection drupal. The reason for this is to make it very clear that any place in our Flash application where we would like to interact with Drupal, we will do so by simply using our drupal NetConnection object. But before we use this connection, we must first specify what type of connection we will be using. In any NetConnection object, we can do this by providing a value for the variable objectEncoding . This variable lets the connection know how to structure the XML format when communicating back and forth between Flash and Drupal. Currently, there are only two types of encoding to choose from: AMF0 or AMF3. AMF0 is used for ActionScript versions less than 3, while AMF3 is used for ActionScript 3. ActionScript 1 and 2 are much less efficient than version 3, so it is highly recommended to use ActionScript 3 over 1 or 2. Since we are using ActionScript 3, we will need to use the AMF3 format, and we can provide this as follows: // Declare our Drupal connection Now that we have an instance ready to go, our first task will be to connect to the Drupal gateway that we set up in the previous section. Connecting to a remote gatewayConnecting to a remote gateway can be performed using the connect command on our drupal NetConnection object. But in order for us to connect, we must first determine the correct gateway URL to pass to this function. We can find this by going back to our Drupal installation and navigating to Administer | Services. In the Browse section, you will see a link to the servers available for remote procedure calls as shown in the following screenshot:
For every listed server, we can click on each link to verify that the server is ready for communication. Let's do this by clicking on the link for AMFPHP, which should then bring up a page to let us know that our AMFPHP gateway is installed properly. We can also use this page to determine our AMFPHP gateway location, since it is the URL of this page. By observing the path of this page, we can add our AMFPHP server to our main.as file by combining the base URL of our site and then adding the AMFPHP services gateway to that base. // Declare our baseURL and gateway string. It is important to note that the connect routine is synchronous, which means that once this function is called, we can immediately start using that connection. However, any remote procedure call that we make afterwards, will be asynchronous, and will need to be handled as such. The function that can be used to make these remote procedure calls to Drupal is called call. Flash with Drupal
Using the NetConnection call routineIf you look at the Adobe Help section about the NetConnection call function, you will find the following arguments: function call( command:String, The first argument, called command, is very easy to understand and use. It is the command that you will send to your remote server to execute. In Drupal, this will be the Service functions that are provided by the System and Node Services that we installed on our server. Since our first task is to simply connect to Drupal, we will first need to use the system.connect command to send to our System Service on our Drupal installation. The second argument is the responder. This is simply the object that holds the callback functions that are used when the server returns from a remote function call. One callback is used to handle the return value on a successful transfer, while the other callback function is used to handle any error that might have occurred. Since we are programming asynchronously here, we need to first create these two callback functions and then create a new Responder object using both our success and error callback functions. Within our main.as file, we can create the responder with the callback functions as follows: // Declare our baseURL and gateway The third argument to the call routine, and each subsequent argument afterwards, is what will be passed as argument(s) to the remote function that we are calling. You will notice in the function declaration that there are "…" in front of the arguments variable. This is called a variable argument function, which means that it can accept any number of arguments into this function. This allows us to provide any number of arguments, which will then be sent as arguments to the remote function that we are calling. For system.connect service, there are not many required arguments, so we can just omit this for now. So, here is the ActionScript code that illustrates how to connect to Drupal using the function call. // Declare our baseURL and gateway Step 4: Session handlingNow that we are connected to Drupal, our next intuition is for us to dive in and start extracting data from our Drupal site; but this cannot be accomplished without first handling the session ID for our connection with Drupal. The session ID is simply a unique identifier for every connection made with any web site. The session ID allows a web site to keep a track of every single person navigating the site, and therefore, give them certain permissions depending on whether that person is logged in as a user who can perform certain tasks. Each browser then uses cookies to store the session ID of that user so that the next time they open up their browser, their session is restored by setting the session ID to the same value as what was saved in the cookie. We will use this session ID in our application for every call that we make to Drupal to validate our connection. By default, the Services module assumes that any application making calls to the Drupal system is an "anonymous" application, and therefore, does not allow that application to perform specific tasks. By utilizing the session ID, we are allowing our Flash application to validate itself with our Drupal installation so that the typical user management system that Drupal employs to access content is utilized. With that said, let's modify our previous code to handle the session ID for our connection with Drupal. Connecting to Drupal using system.connectAlthough session handling may sound complicated, the effort involved is minor since the ID is returned to us after the Drupal connection has been made using the system.connect call. And since we will be using this session ID for other routines, we need to declare the following: // Declare our variables We can now verify that this works by running our application. We should see, within the output panel, our connection with Drupal followed with a valid session ID. We are now ready to move on. Step 5: Drupal says "Hello World"Now, we are getting to the fun part… loading Drupal data into our Flash application. But before we can write the ActionScript to load node data from Drupal, we must first revisit our Drupal web site and create a new node that we will use to say "Hello". Moving back to our Drupal web site, let's create a new node by going to Create Content | Page. The page title is what we will use to say hello, so where it asks for a title, put in the text "Hello World!", and then go down to the very bottom of the page and hit the Submit button. We should then see our new page created that says, "Hello World!" for the title. It is very important for us to also remember the node ID of the node that we just created. We can do this by simply looking at the URL in our browser and writing down the number that comes after http://locahost/drupal6/node/. We will use this number to load our node in Flash, so just make sure you either remember it or write it down. Loading a node in FlashNow that our node is ready, we can write the code in ActionScript that loads this node and then parses out the title. This is how we are going to build our "Hello World" application using Flash and Drupal. So, let's move back to our Flash IDE and take a look at the code that we have so far. Picking up where we left off, we are finally at the point where we have successfully connected to our Drupal web site and received the session ID. The next step in this process is to get the node information from the node that we just created in our Drupal site. To accomplish this, we will be using the Service method called node.get , which takes two arguments: the session ID, and the node ID of the node we wish to load. This is where our variable arguments come into play, since we have two arguments that we need to provide. At this point, it is considered best practice to create a separate function that combines the functionality of creating our responder with the Drupal service call to load a node. For the sake of simplicity, we will call this new function loadNode, where it will take a single argument (the node ID), and then use that argument and pass it along to the node.get service function. The Drupal node service will then return the node object for the node that we are requesting by calling the callback function that we provided within the responder. Within each node object, we will have access to the Title, Body, and any other fields of data that are associated with a Drupal node. Since we used the node title to say "Hello World", we can create an onNodeLoad function to print out the title field for the node object returned from Drupal. Each of these functions will look as follows: // Connect to Drupal We can now use the loadNode function to load any Drupal node by passing in the node ID for the node we wish to load. For example, if we wish to load a node with an ID of 2, we can simply call loadNode(2), and all the complex functionality is now abstracted within that single function. Now for the big question…where do we place the call to loadNode so that we can load our "Hello World!" node that we just created? This seems simple enough, but leads to a significant gotcha where asynchronous software becomes a little confusing. To illustrate, let's take a look at the following code where I am attempting to connect to Drupal and then make a simple call to loadNode directly afterwards. Many developers who just start out using web services very often attempt to do the following and get very frustrated when they discover that it just does not work. // Connect to Drupal If we were to run this application, we will quickly see an issue by looking at the Output panel. This panel prints out the response returned from our Services module after we make our call to load a node. Since an error occurred, our onError function is called, and then the following error is printed out:
This error is the result of an elusive software bug called race condition. Programming without race conditionsIf we take another look at the previous code, we will see that we are making a call to loadNode directly after the system.connect function call. In the world of synchronous software, this would work just fine, but since we are dealing with web service communication, our function calls to Drupal are not returned after each call is made. Instead, each call that we make to Drupal can take any amount of time before the result is returned using a callback function . To the trained eye, this is obvious, but for the developers just learning asynchronous software behavior, this can be quite the head scratcher. Taking asynchronous software interaction into account, we can now determine that our error occurred because we were making the call to get the node information before we received any indication that we have successfully connected, from the system.connect command. There is no guarantee that a response from the server will make it back in time before we end up making the call to loadNode. In asynchronous programming, this is most commonly referred to as a race condition, where you are betting that the return from system.connect will beat the call to loadNode. Unfortunately, you will most likely lose this bet, and the result will be a strange error that does nothing to expose the smoking gun. Programming with race conditions is considered very poor programming practice, and will most often lead to an extremely elusive software bug in your application. In fact, I can easily say that with all my experience debugging software in complex applications, it is always the race condition that is the hardest bug to find and correct. So, let's take a moment and learn how to modify the previous code so that it will never hit a race condition. The trick is to simply move the call to loadNode after we receive notification from Drupal that we are connected and have a valid session ID. After we look at the following code, it will seem very obvious, but you would be surprised how often this gotcha seems to crop up in complex software applications. The modified code should look like the following (assuming the node ID you created was 2): // Connect to the Drupal gateway So, after we run this application, we should get a very nice surprise… a "Hello World" from Drupal! But we are still not done here; our next step is to hook up the text in our Flash TextField to show this exciting text. Step 6: Hooking up the textIn this next step, we will open up our chapter2.fla project file, where we will give our TextField an instance name so that it can be referenced within ActionScript. Fortunately, this step is very simple and only requires that we select the TextField, and then give it an instance of title in the PROPERTIES panel as shown in the following screenshot:
Now that we have given our TextField an instance, the next step is to remove the text "Hello Drupal" from thisTextField so that we can determine if Drupal node data is used instead.
We can now shift our focus back to the main.as file, where we will change our trace statement within our onNodeLoad function so that it sets the text of this TextField instead of just printing it to the Output panel. We can do this in ActionScript by using the following code: // Called when Drupal returns with our node. We can now run our application and see our TextField show the title for our Hello World! node.
Now that our application is starting to look like a real Flash application, we need to take some extra steps to make sure that it is flexible by allowing any node ID to be used to say "Hello World". Step 7: Passing the node ID using FlashVarsSince the goal of our Flash application is to dynamically load Drupal node information, we will need a way to tell our Flash application which node to load. We can easily hard code the node ID of our "Hello World" Drupal node, but this approach does not give us much flexibility to apply it to any node within our Drupal system. We can solve this issue by utilizing FlashVars to pass the node ID to our Flash application. Using FlashVars in a Flash applicationFlash variables (or FlashVars) are special variables that are passed to a Flash application that are used to provide a specific functionality for a common application. They are passed to the Flash application when it is embedded within an HTML page using the object element. For example, we can tell our Hello World application to load the node data from node 2 using the following HTML code: <object width="320" height="240"> Within ActionScript, the node variable is then passed to the root structure and can be referenced within our main.as file using the root.loaderInfo.parametersconstruct. For example, we can determine the node ID passed to our Flash application by using the following code within our main.as file: root.loaderInfo.parameters.node Using this information, we can now create a nodeID variable at the top of our main.as file, where we will set it to the node ID passed to our Flash application. We can then replace our hard-coded node value with this variable so that our Flash application is no longer dependent on a specific node value. // Declare our variables We are now finished with our "Hello World" application. At this point, we can run our Flash application so that it will create the chapter2.swf file, which we will then use to add to our Drupal web site. Step 8: Adding it to DrupalIn this step, we can go back to the lessons learned from the previous chapter where we used the FlashNode module to add a SWF file to our Drupal website. To start, we will create a new Flash node by navigating to Create Content | Flash, and then give it a title of "Hello World Application". After we have done that, we can select our newly created SWF file using the Flash file input field. The next step, however, will require us to pass in the FlashVar so that we can tell our application which node to load. To do this, we will simply expand the Advanced flash node options, and place node=2 within the FlashVars text field.
We can now save our new node, and see our new dynamic Flash application in action.
SummaryWhen dealing with web services, it is very important to understand how two remote applications communicate and how to develop our software to account for its asynchronous interaction. This is typically always overlooked when developers create their first Flash applications for Drupal, and can easily be avoided if the concepts of web service interaction are understood and taken into account. Each key concept is highlighted as follows:
If you have read this article you may be interested to view :
Flash with Drupal
About the AuthorTravis Tidwell is the founder and CTO for TMT Digital (http://www.tmtdigital.com), a company that specializes in the development of Flash applications for the Drupal Content Management System. He is also the sole developer for the Dash Media Player (http://www.tmtdigital.com/project/dash_player,http://www.drupal.org/project/dashplayer), which is a media player built specifi cally for Drupal. As well as contributing to this media player, Travis is also the author and co-maintainer for the FlashVideo module (http://www.drupal.org/project/flashvideo), which is a complete video solution for Drupal. Travis graduated with a degree of Bachelors of Science in Electrical and Computer Engineering from Oklahoma State University and has worked as an EmbeddedSystems Engineer for companies specializing in automotive and agricultural GPS products. Travis then fell in love with web development and more specificallywith Drupal and Flash, where he has developed numerous sites including http://www.delicioso.com for Food Networks, Ingrid Hoffmann. In his spare time (which is rare these days), Travis enjoys the performing arts where he sings, plays the guitar, and even tap dances (go to http://www.youtube.com and search for "Soul Man Tap" to see him in action). Books from Packt |
|
| ||||||||