Director Article

Using Web Services in Macromedia Director MX 2004

Dan Sadowski

www.directordev.com

I’ve been reading about web services for years. They have often been discussed in articles in technical journals and referred to on websites. However I haven’t actually had any occasion to make direct use of web services in my own coding. I figured out it was time to dive in and try to use some web services myself. I believe you get a better understanding of a topic like this when you work on code rather than just read about the process. In this article I will describe the steps I went through to access web services in Macromedia Director, working with several examples which are based on SWFs created in Macromedia Flash. I will then access some web services using the Director programming languages.

Web services provide a way to share information. So you want to use web services in Director? This article describes how and provides examples using SWF cast members as well as examples completely scripted in Director. The world of web services is a big one, and the sample code doesn’t cover all the possibilities. But this article will get you started working with them in Director.

There are quite a few Macromedia Developer Center articles about web services, but none of them discuss using web services in Director. You may find the following articles to be helpful in understanding the basics of web services and issues such as proxy servers that won't be covered in this article.

Requirements

To complete this tutorial you will need to install the following software and files:

Product

Note: Although not required for the examples, if you wish to modify some of the example Flash files you will need Macromedia Flash MX Professional 2004.

Tutorials and sample files:

Note: This ZIP file contains the following sample files:

  • tips.swf
  • postNetText.htm
  • Example With Flash.dir
  • Web Service Test.dir
  • WebService Behavior.dir
  • flash-db example.fla

Prerequisite knowledge:

To get the most out of this article, you should be familiar with the basics of programming in Macromedia Director. Although some Flash examples will be discussed, and several SWF files used in Director, you do not need to have Macromedia Flash to work with the examples.

Tutorial Example from Macromedia Flash MX 2004 Professional

The first sample uses the web services tutorial that is included with Flash Professional. It relies on a SWF member to do all the communication and control with the service. Director is serving as the host environment for the Macromedia Flash movie. This is a really simple example; use it to get the process of learning about web services started and to verify that everything works as expected. The Flash tutorial walks through all the steps necessary to create the SWF file, but you can just use the file included with the examples.

Just import the SWF, drag it to the Stage, and play it. You should be able to use the pop-up menu control to select a product and the Get Tip button to access a tip. This example uses a minimal web service, and there are just a couple of tips provided by the server. If this example isn’t working for you, make sure you are using version 10.1 of Director, since version 10.0 doesn’t support web services.

You can publish this movie and play it in a projector or in Shockwave Player. In Shockwave Player you will see the network security dialog since the web service is hosted on a different domain than your movie. The Macromedia Developer Center has some articles that discuss using proxy servers to address this type of cross-domain security issue.

Using a Web Service with a SWF Sprite

For the next web services exploration, I first went through the tutorial by Jeffrey Hill called Using the Flash MX 2004 Web Service Classes and hosted on the flash-db website. This is a nicely written tutorial that provides an introduction to the ActionScript interface to web services. I’ve already created a Director movie that includes the SWF file that you would create if you worked through the tutorial. This Director movie has been designed to incorporate several variations of the Flash example. The movie contains several different SWF files. In subsequent steps, I will review each of these in turn. While the movie is playing, you will use the Message window to explore what's happening. If you stop the movie, just start it again–no need to rewind. Go ahead and open the Example With SWFs movie and play it. Then click the button to see what happens.

Well, you probably didn’t notice any effect when you pressed the button. The reason for this is that the original tutorial example SWF is focused on using ActionScript and uses trace statements to present the output of the web service. When running in Director, ActionScript trace statement output appears in the Message window. Open the Message window and check the output pane to verify that the web service request is working. You will see a few statements about a company stock. However the trace statement approach won't do much good if you play this movie in a projector or through Shockwave Player─trace statements do not appear in these playback environments.

For the first revision to the example, I simply added a dynamic text field in Flash to display the output of the web service. I associated a Flash variable named service_output with the text field using the Property inspector in Flash. I modified the button handler to store the output text in the variable rather than using trace statements. Continue to the next section within the Director movie. Now when you press the button in the SWF, you can see the web services results displayed in the Flash sprite on the Stage. This is much better for the exploration. This technique will work in a projector or Shockwave Player. But what if you want to access the results of the web services in Director? Well, one easy way to access this information is to just use the getVariable() method for Flash sprites. Activate the Message window and type the following. If you are using Lingo, type:

sprite("webservice").getvariable("service_output")

If you are using JavaScript type:

trace(sprite("webservice").getvariable("service_output"));

You will see the same results displayed in the Message window. You can easily store this text in a Director text member or a variable and use it for whatever you want.

This stock information web service offers more information than is currently being presented in the Flash sprite. How can you access all of the available information? Continue on to the next revision of the modified SWF that appears in the Director movie. This time, the ActionScript was changed to save the web service result as an ActionScript object in a Flash variable called serviceObj. You will use the direct access to ActionScript objects feature of Director to investigate the web service output. Press the button in the SWF to call out to the web service. After the response appears, open the Object inspector and enter the following in the left column:

sprite(1).getvariable("serviceObj", false) 

Click the expander arrow for your new entry, and you will see output like that shown in Figure 1:

The expanded view in the Object inspector

Figure 1. The expanded view in the Object inspector

Cool! You can see ALL of the properties that this web service method is returning. You can easily get at any of these properties with some code in Director. For example, you may use your choice of the following code syntax alternatives to access the tradedTime property of the object. Try the following in the Message window:

serviceObj = sprite("webservice").getvariable("serviceObj", false)

Then use the Lingo put command or JavaScript trace command to check the property using either of these code choices:

serviceObj.tradedTime
serviceObj["tradedTime"]

Using Lingo you can also use a property list method and a symbol constant such as:

put serviceObj.getaProp(#tradedTime)

You can also find out what properties are available in a Flash object programmatically using the dbgPropList method that Director provides for Flash objects. Try the following Lingo in the Message window:

put serviceObj.dbgPropList()

You will see output something like this:

[#symbol, #company, #lastPrice, #tradedDate, #tradedTime, #change, #changePercent, #volume, #averageVolume, #bid, #ask]

Here is an example using this─the following Lingo handler obtains a list of all the properties returned in the web service response and lists them and their values in the Message window:

on listProps()
  serviceObj = sprite("webservice").getVariable("serviceObj", false)
  theProps = serviceObj.dbgPropList()
  repeat with aProp in theProps
    put string(aProp) && "=" && serviceObj.getaProp(aProp)
  end repeat
end

This handler is already defined in a movie script cast member in the sample movie, so you can try it out by entering listProps() in the Message window.

Direct access to the dbgPropList() method is not available in JavaScript, but your movie can define a very simple Lingo handler

on getPropList(serviceObj)
  return serviceObj.dbgPropList()
end

to provide the property list to a JavaScript function.

function jsListProps()
{
   var serviceObj = sprite("webservice").getVariable("serviceObj", false);
   var theProps = getPropList(serviceObj);
   for (var i=1; i<=theProps.count; i++)
   {
     aProp = theProps[i].toString();
     trace(aProp + " = " + serviceObj[aProp.substring(1)]);
   }
}

Since both these routines have already been defined in the sample movie, you can execute this function in the Message window with the following code:

jsListProps()

Say you want to call the web service from Director without relying on the user clicking the Flash button. For example, perhaps you want to call the web service at a particular time─Easily done. You will not even need a SWF with updated ActionScript to do this. You can easily access the Flash component in the sprite directly and just call the method in your Director code. Try using the following in the Message window:

button = sprite(1).getvariable("result_btn", false)
button.onPress()

You will see that the web service gets called and displays the result as soon as it is returned.

There is one more obvious enhancement to consider when working with this web service–to be able to use the web service to check a different stock symbol. So step the Director movie to the next variation we’re looking at. Originally the Flash movie simply had the stock symbol entered as a constant value in ActionScript. An easy approach is to add an editable text object to the Flash movie so the user can enter a stock ticker symbol. In Flash, the text field has been associated with the ticker_symbol variable. The ticker_symbol value gets passed along as a parameter to the web service in ActionScript. Type in a different symbol, such as ADBE for example, and press the button. With scripts in Director, you can easily set and use this value–try the following code in the Message window

sprite(1).setvariable("ticker_symbol", "AAPL")
sprite(1).getvariable("result_btn", false).onPress()
listProps()

Now you know how to use a simple Flash sprite, along with some short snippets of ActionScript code to provide access to web services from Director. Note that web service support is only offered in the Professional version of Flash.

One note of caution─there is a bug in Director related to using the Object inspector to inspect ActionScript objects that are stored in global variables. You might use this code to get a reference to an ActionScript object:

_global.button = sprite(1).getvariable("result_btn", false)

While the movie is playing, you can investigate the button in the Object inspector. But if you leave the button entry on display in the Object inspector, Director crashes when you stop and start the movie. So always clear the entry from the Object inspector before stopping the movie. Or instead, you can safely use a local variable or a sprite reference in the Object inspector.

Accessing Web Services without a SWF Sprite

To use web services in Director, it is not necessary to use a Flash-generated SWF as a sprite in the Director movie. You can communicate with a web services server using the NetLingo commands in Director to send information to the server and use the XMLParser Xtra to interpret the responses you get. This requires more involved programming, but this approach may provide you with a better understanding of the details of a web service transaction from a client-side perspective. Note that the world of web services is complicated, and this code has just been tested with some simple service examples. You will be working with some Director behaviors for this section of the article.

Web services make use of oodles of web standards and protocols. You may notice that there are loads of acronyms used in this area of software integration. Honestly, I sometimes start laughing when reading some of the articles in journals and there is a sentence that is mostly acronyms. I’ll only be using a few of these standards: SOAP (Simple Object Access Protocol), WSDL (Web Services Description Language), and RPC (Remote Procedure Call). Detailed technical specifications for all of these are available on the Internet. Some starting links are provided at the end of this article. All of these protocols are XML-based, so you will need to be working with XML to access the web service. In addition, you need to make use of a recently updated postNetText command that now supports an optional mimeType. The updated command is available starting with version 10.1 of Director or Shockwave Player. You can find a description of the new postNetText command in the file postNetText.htm that is included with downloads for this article.

The steps to programmatically use a simple web service are as follows:

  1. Make a request to find out about the web service.
  2. The result from this request is XML, formatted as a WSDL.
  3. Extract information about the service from the WSDL.
  4. Build a SOAP RPC request for the method you want to call.
  5. Post the request to web services host.
  6. Get the result back, formatted as a SOAP response.
  7. Extract the result of the method from the SOAP response.

Normally, the web service APIs don’t change as frequently as the data they return. So you might only do items one through three on the list once when authoring a movie. But your users would end up running steps four through seven more frequently, perhaps every time they run your movie. To take advantage of this architecture, I split the process into two parts. The first phase is handled by a behavior that manages steps one through three. It communicates with a server, and finds out about the methods available in the web service. After it processes the XML response it gets back, this behavior generates additional behavior cast members. In fact, a separate behavior is created for each method of the web service. The second phase, consisting of the final four steps, is handled by these generated behaviors.

Since web services are based on network transactions, I decided to start off working with code based on the Get Net Text behavior that comes in the Text Behaviors Library of Director MX 2004. This behavior requests some information from a server on the Internet and updates the text or field sprite with the contents. I started with a copy of this behavior, trimmed out properties and methods that didn’t apply, and added some new ones specifically for web services. One newly added property is a feedback property, which I found useful as an aid to debugging. Three different levels are supported:

  • #none - no debugging output provided
  • #status - status information appears in the sprite during the transaction
  • #log - lots of output is added to a separate field member called networkLog

First, you should take a look at a simple movie that uses the sample behaviors. Open the file Web Service Test.dir and play it. Click any of the three text fields to call a web service method. Open the Behavior tab of the Property inspector and try changing some parameters associated with the behaviors. You can trigger several web service calls at the same time. Go ahead and add a new text sprite and apply one of the behaviors to it. Browse the code for the behaviors in the script window to get acquainted. You will notice that the code is very similar for each separate service. I made a few additional coding changes to the generated behaviors in this movie; just adding some #range property values for the propertyDescriptionList at the bottom of each behavior script.

You can make a web service call from the Message window with:

sendSprite("weatherSprite").mPopulate

Here’s a function like the one used in the first part of this article. It’s a bit simpler since I don’t have to deal with the ActionScript object. These are defined in the movie, so you can just run them in the Message window after using the company web service field in the movie by entering listProps() or jsListProps().

on listProps()
  theProps = sprite("company").mResult()
  repeat with i = 1 to theProps.count
    tmp = theProps.getPropAt(i)
    put string(tmp) && "=" && theProps.getaProp(tmp)
  end repeat
end

And here you have the JavaScript equivalent:

function jsListProps()
{
   var theProps = sprite("company").mResult();
   for (var i=1; i<=theProps.count; i++)
   {
     trace(theProps.getPropAt(i) + " = " + theProps[i].toString());
   }
}
 

Next, open the Web Service Generator movie so you can take a look at the origin of the behaviors you just worked with. This movie has a single behavior in it. This Web Services Behavior Generator behavior supports four properties:

  • URL –the URL for the WSDL for the web service
  • Timeout duration – so you can time out if the network doesn’t respond
  • Activation mode – how the network transaction gets triggered
  • Feedback – added to help in debugging

Here’s a brief synopsis of how this behavior works. After the operation gets triggered, the WSDL URL gets retrieved with getNetText(). Like the original Get Net Text behavior, this is handled in the mActive and mCheckNetworkOp methods. Next, in the mLoadedWSDL() method, the XML Parser Xtra is called on to parse the information. Finally the mProcessWSDL() method is called. This analyzes the WSDL structure of the XML and builds a master property list describing the facilities offered by the web service. Items such as the name and the URL for the method calls are added as properties. In addition, a method property list is created with information about parameters, return values, etc., of each method. The structure of the master property list ends up something like this:

[#serviceName: "A Service", 
 #url: http://somewhere.com, 
 #documentation: "helpful service",
 #method1: 
   [#name : GetRandomValue,
    #input: "choice",
    #parameterList: ["arg0", "string"]
   ]
 ]

After the WSDL has been processed, a new behavior to handle the SOAP part of the web service gets generated for each method. This happens in createBehavior. Most of the behavior code is taken from a script template stored in a separate cast member named WebServiceTemplate. A few items in the template are customized based on the information obtained about the method and the service. In particular, notice that the property list generated from the WSDL is added as a property of the newly generated behavior.

The template that is used for the newly created behaviors is also based on the code in the Get Net Text behavior from the standard library. With this variation there doesn’t need to be a URL property since the URL is determined by information that came from the WSDL. But since a web service method may take one or more parameters, the propertyDescriptionList has parameters added as necessary.

When this action gets triggered, the postNetText command will be used to communicate with the server for the web service. The data for the post network call is formatted as SOAP XML by the mRequest method. The XML Parser Xtra cannot be used to generate a new XML string, but the necessary SOAP formatting isn’t too complicated to manage with a bit of code. The contents are determined using information from the WSDL property list as well as the custom parameter values specified for the behavior. The proper mime type information is determined based on the WSDL property list and the SOAP rules. The results of the request come back as a SOAP response. One or more response strings are pulled out by the mResponse method and stored in the text sprite.

Where to Go from Here

Working in a software development environment you may often find it helpful to develop your own custom tools to help solve a programming workflow problem. As you can see it’s fairly easy to create scripts that can also be used in Director. You can even generate the behaviors and dynamically add them to sprites while the movie is running. However, the simplest way for you to use a new set of behaviors is to add them to your authoring interface. Simply create a new external cast file and copy the generated behaviors there. Use the operating system to move this cast file to the /Configuration/Library/ folder and you can use these behaviors in any movie you are editing. Note that you will have to restart Director to see the new items in the Library palette.

Here’s a link to a reference page for many of the formal specifications about web services standards.

www.w3.org/2002/ws/

About the author

Dan Sadowski has been involved with Macromedia since 1984 when the company was called MacroMind. He works out of his home in Colorado Springs, Colorado, as a software engineer for the Director development team.