|
|
||||||||||||||||||
|
|
||||||||||||||||||
![]() |
![]() |
Issue 9 - Revision 8 / February 7, 2005
|
|||
|
Building Web Applications with Flash and Zope - - - - - - - - - - - - By Jim Allman | November 27, 2004
Zope and Macromedia's Flash are a powerful combination for building rich Internet applications (RIAs). The depth and flexibility of the Zope server, combined with an expressive Flash client, can be used to make applications that are data-driven, ubiquitous, and drop-dead gorgeous. But this is not a well-traveled path, and as with any complex system there are pitfalls. In this article, I'll describe some of the challenges I've encountered, and share some proven ways to overcome them. Some of the ideas here are specific to Flash apps; others will apply equally to any browser-hosted application. Deployment challengesAny runtime environment has prerequisites to start and run correctly, and browser-hosted Flash is no exception. Here are a few tips to make sure your user has the proper Flash Player, and that your Flash movies will be able to receive special instructions from the hosting Web page. Plugin detectionFirst and foremost, you need to accurately determine whether a user has the proper runtime environment (Flash Player) for your application. But with the current crop of incompatible browsers, foolproof plugin detection is a real challenge. Happily, Macromedia has a vested interest in solving this problem, as well, so they maintain a robust, cross-browser plugin detection scheme that will test for a specified version of Flash.
If the plugin is missing or outdated, and the browser doesn't prompt for a Player download automatically, the test movie will redirect to a second Web page that points to the required Flash Player download. If the required plugin was detected, it redirects to your main Flash movie instead, so most users won't even notice the test. In Flash MX 2004, this feature can be added in the Publish Settings dialog of any Flash document (see Figures 1 and 2). If you're using an older version of Flash, you'll find the same files on Macromedia's site, in the free Flash Detection Kit.
In either case, you'll likely want to modify the boilerplate HTML pages to suit your application or Website. These pages can be modified like any other to include ZPT or DTML code--just be careful around the OBJECT and EMBED tags. And keep in mind that any changes you make to the Flash (SWF) file's source URL, to its quality settings, or to its query-string, should be repeated in both the OBJECT and EMBED tags for best results in all browsers. Browser differencesOne issue to consider when planning a browser-based Flash app is that some browsers have quirks in their Flash support. Older versions of the Netscape browser, for instance, would reload plugin media when a browser window was resized. This forced a complete reload of any embedded Flash document, which typically meant that all the user's current data would be lost. Modern browsers don't have such drastic bugs, but Flash support can also be compromised by user choices. Naturally, a user who has removed or disabled the Flash plugin is out of luck. Similarly, if a user has disabled Javascript, then your Flash movie will be unable to communicate with its hosting page. One failsafe method for passing initial values into the main embedded SWF is to send key-value pairs on its query string (for example: src="myMovie.swf?name=Jim&color=blue). This works in all browsers, and sets the named variables (with string values) in the main Flash timeline. This technique is best used with a small "stub" SWF, since the changing query-string will cause the initial SWF to frequently reload from the server (more on this topic below).
In my projects, I've used XML-RPC for communication between the Flash client and Zope server. Zope's built-in support for XML-RPC make this an easy choice, and so far I haven't needed the extra features or crust of a SOAP connection. Since Flash's built-in XML object handles the XML request/response over HTTP, we just need to add an XML-RPC wrapper. This is a simple "messenger" class that reports errors, makes RPC calls transparent to the client, and gracefully handles delayed responses from the server. There are several solutions available now (just search the Web for "Flash XML-RPC"). I've been very happy with the simple xml-rpc.as script by Pedro Ornelas. The more recent Flash MX 2004 Professional includes classes that support Web services of all kinds, including a proprietary protocol called Flash Remoting or AMF. In some cases, AMF can improve performance by passing more complex, serialized objects (a la Python's Pickle module). This is not currently supported by Zope or Python, but one never knows--the AMF protocol is already supported in Perl and PHP. However you decide to manage client-server communication, more interesting design decisions lie ahead. Will you use Flash as a thin/dumb client or a smart one? Depending on your project, and your fluency with Actionscript and Python, you might choose to embed your "business logic" in either program. In my own projects, I've used Flash as a smart client, and Zope mainly for deployment and data storage, for two reasons. This allows for a more "loosely-connected" client that can be used offline, with temporary storage on the local hard disk. Also, a smart client can typically be more responsive to user actions like drag-and-drop, validation of form input, and so on. Debugging the live siteLike any client-server application, your Flash app can be tricky to debug without special tools. I've found the Flash and Python debuggers fairly useful, and you might also choose to build your own. The Flash runtime debuggerFlash now includes a modern, breakpoint debugger that lets you monitor, inspect, and debug Flash movies in the authoring environment. With a little effort, it can also be used to debug "remote" files running in the local browser. The Flash debugger includes breakpoints; a browser for examining local and other variables; and a watch window for monitoring especially interesting values.
To debug your movie, you'll need to permit debugging in its Publish Settings dialog. You can also set an optional password for each movie, so that only authorized people will be able to use the debugger. When you publish the movie, a companion SWD file will also be generated with information to support the debugger; be sure to upload both files to the same location on the server. Finally, you'll need to install the "debugging version" of the Flash Player on any computer you'll use to debug the remote SWF. You can find the debugging Flash Player in the configuration folders of the Flash authoring tool, or on the Web at http://www.macromedia.com/support/flash/downloads.html. Python's pdb debuggerFinally, Python's included pdb debugger can also be useful, particularly when troubleshooting failed XML-RPC calls. pdb is a fairly primitive debugger that runs in the Zope console window, so you'll need ongoing shell access to the running Zope server to use this. NOTE that pdb halts the Python interpreter while in use, so this is not a tool to use on a public server. But if you have a separate development server, and especially if you run a Zope server on your development workstation, this can be a very effective tool. To enable the pdb debugger in your Zope application, just add this import statement to any server-side Python:
In my project, I simply added this method to a Python mdule in the server-side Extensions folder, then added an External Method 'debug' (at the root of my Zope application) that refers to it. This lets a tester invoke pdb through the Web, by simply calling this External Method in any URL:
When this request reaches the server, expect Zope to stop cold while the debugger appears in the Zope console window and waits for your input. You can also add a call to the external debug() method to any other Python module; the next time that particular bit of Python is interpreted, it will trigger pdb immediately. Remember, pdb should only be used on a development server, since it will stop Zope dead in its tracks! Custom debugging toolsTo test the XML-RPC calls in Zope, I also built an XML-RPC "test harness" in Flash. This is a bare-bones movie that runs in a Web page. Using a crude, form-based interface, a tester can build XML-RPC requests, send them to the Zope server, and display the returned values.
Special-purpose tools like this are easy to build and very useful in testing APIs and components. In this case, I was able to test and refine the XML-RPC methods of my application while we were still designing the primary Flash UI. Configuration managementBecause of the unique nature of the Flash runtime environment, it's not always obvious how an app should be constructed--should you use one Flash document, or many? The path you choose will affect loading time, performance, and future maintenance of the application. A view from the inside (nested timelines)A key concept in Flash is the "timeline", a series of display frames containing artwork, shapes, and script. Many new users treat Flash as a simple animation tool, placing these items in the timeline to choreograph linear presentations. To build more complex Flash programs, we gradually shift control from the timeline to Actionscript. But the operating environment is the same, and timelines continue to play a key role, by providing context and scope for all scripts. Every Actionscript runs within a timeline, which serves as the namespace for local variables. (When nothing else will do, there is also a _global namespace but this is best used sparingly.) Using keywords like _parent and _root, scripts can communicate between timelines. Obviously, Flash timelines are similar to Python modules, and should be used to organize complex behavior. There are some important differences, however. One is that each timeline is not just a logical container, but a visible one, with expressive properties like scale, rotation, and an internal "canvas" for sound and graphics. Actionscript treats each timeline as an instance of the MovieClip class, with a host of built-in properties and methods related to display, collision detection, load status, etc. Unlike a Python module, a single Flash document can contain many nested timelines, which in Flash are called movie clip instances. (This sort of hierarchy is often used to build complex objects in Flash by composition.) Any Flash document can also load another SWF into its timeline hierarchy. At runtime, all are treated the same regardless of their file of origin.
Given this flexibility, it's possible to build a Flash application as a single large SWF file, a few major component SWFs, or using a large collection of special-purpose SWFs and other asset files. Each Flash document has its own URL, a library of media assets, and embedded scripts. There are also provisions in Flash for creating "shared libraries" that can be used in any SWF once loaded. This is a great way to package assets like font outlines, UI components, or common scripts for use in multiple SWFs. The choices you make here will largely determine the size of your SWF files and the app's loading times. Using many files keeps things lean and modular; this is definitely the way to go if you're interested in skinning or re-usable components. But it also makes you responsible for finding and keeping track of these files (more on this later) and for managing one of Flash's more unusual features--streaming code. The Flash Player was designed to present rich media on a low-bandwidth network. To do this, it streams Flash "movies" from the server frame by frame, and shows each frame as soon as its contents have loaded. Since Actionscript is anchored to a frame in the timeline, or to an object in a frame, it's possible for scripts in frame 1 to run while the scripts in frame 5 are still on the server! There are several ways of managing this. You should always place callable methods in the early frames of a Flash timeline, before any caller appears. Flash symbols can also be placed in frame 1 (or specially marked for preload in the Flash library) to ensure that they're ready when needed. Managing the browser cache with a manifest fileAfter it has loaded once, a Web app built using Flash often starts and plays immediately, thanks to the browser's client-side cache. But the cache is also a hindrance to building apps on the Web, since it tends to retain "stale" files that might have changed on the server. This makes it difficult to ensure that a user has a complete working app, and creates bugs that can only be fixed by reminding all users to "clear the cache" frequently. How can we avoid this problem, while still enjoying the cache's benefits? By subtly altering the URL of each of an application's files each time it changes. (See the sidebar "URLs and the client-side cache" for details on why this works.) I generally use a dynamic XML file on the Zope server called 'manifest.xml' (see code listing for a sample). This lists all the component files used by the app, and a current URL for each:
Naturally, this file uses headers to make sure that it's never cached. This page will list all files (of the specified types) found in the current Zope folder, and build a special URL for each that adds its timestamp. All requests from Flash for one of these files are guaranteed to reflect the latest changes, but if the client-side cache has a fresh copy it will always be used. Here's some typical output:
The manifest file is loaded by our initial SWF, often called the "stub movie." A typical stub movie has only minimal startup logic; it simply loads the XML manifest, then uses the URLs listed there to find and load the main component files of the app. ConclusionIf you’ve wondered about using Flash with Zope, I hope this article will encourage you to give it a try. As we’ve seen, there are some technical hurdles, but all of them can be handled with a thoughtful approach. The reward is certainly worth the effort. Flash provides a rich, responsive, cross-platform web client. A skilled programmer can use it to build refined, truly unique displays, suitable for data visualization, graphical data browsing and modeling, or simulation.
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ZopeMag is committed to bringing you the best in Zope Documentation. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
![]() |
Reproduction of material from any of ZopeMag's pages without prior written permission is strictly prohibited. Copyright 2003 - 2005 ZopeMag |
|