ZopeMag's mascot the ZOPE fish


Article Finder
People
Issue 9 - Revision 8  /   February 7, 2005 


 
  ZopeMag Links:
Latest Issue
About the Fish
Issue 10
Issue 09
Issue 08
Issue 07
Issue 06
Issue 05
Issue 04
Issue 03
Issue 02
Issue 01
 
 
Downloads
     
  Letter from the Editor:


Interviews:
Each issue we interview important people in the Zope world.

  Joel Burton

Articles:
Throughout the quarter we cover topics of interest to Zope developers, designers, and users.

  Improving WebDAV in Zope

  Profiling Zope (Part II)

  Redesigning the portal with CPSSkins and CPSPortlets

  Zope and Flash

  Localization (Part I of II)

Product Review:
Too many Products, too little time? ZopeMag keeps you up-to-date which Zope Products are worthwhile checking out.

  Corp Calender
  BastionLedger


Book Review:
Thanks to a growing subscriber base we can now offer even more to our readers. Zope and Plone Book Reviews!

  The Definitive Guide to Plone


Guides:
This quarter we bring you a new SuperGuide. Our miniGuides and SuperGuides give you the background knowledge you need to mastering Zope.

  miniGuide to writing Zope 2 Products
 
 
Downloads
     
  URLs / Download
Products we talk about in this issues Articles and Reviews

     


Building Web Applications with Flash and Zope

- - - - - - - - - - - -

By Jim Allman  | November 27, 2004

print

____
 
 
Sidebar - Why use Flash?
Macromedia's Flash Player offers a compelling visual client, a persistent display (send and fetch XML from the server without a page refresh), and a lightweight, good-enough "virtual machine" that looks and behaves consistently on all supported operating systems

From a development standpoint, both Flash and Zope depend on dynamic, high-level scripting languages for all but the simplest behavior. Flash Actionscript is an implementation of the ECMAScript core language, which takes on different names depending on its host app (Javascript or Jscript in a Web browser, MEL in Maya, etc.). The new Actionscript 2 is based on the ECMAScript 4 spec, with improved support for team development, cleaner syntax for classes, and enhanced compile-time error checking.

Now that Macromedia has added a library of common GUI widgets, and the ability to build custom components, Flash is finally gaining recognition as a powerful application toolkit.
 
____
Introduction

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 challenges

Any 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 detection

First 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.

Figure 1 - Enabling Flash Player detection in the Publish Settings dialog


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.

Figure 2 - Naming the destination pages to follow Flash Player detection


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 differences

One 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).

____
 
 
Secure data transport in Flash

Flash depends on its hosting browser to shepherd HTTP data to and from the server, so it can take advantage of SSL (secure sockets) if both the server and browser are capable.

While your Flash client can be easily published as a standalone executable for Mac or Windows, the standalone doesn't support SSL, so your data will be transferred in plaintext. If you want the (many) advantages of a standalone app, VPN software or an SSH tunnel can be used instead of SSL.

 
____
Client/server communication

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 site

Like 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 debugger

Flash 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.

Figure 3 - The Flash runtime debugger, showing breakpoints and variables


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 debugger

Finally, 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:

def debug( ):
   # Activates the step-trace debugger; effectively, this should
   # give us the ability to invoke debugging from ZPT or DTML, like so:
   # <dtml-call "debug"> <!--calls external method 'debug()'-->
   #    # WARNING: This uses Python's 'pdb' debugging module, which means:
   # - we have to be looking at the console running Zope to use it!
   # - it will STOP Zope (like under hypnosis) until you're done!
   import pdb
   pdb.set_trace( )
   return

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:

http://localhost:8080/MyApp/debug

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 tools

To 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.

Figure 4 - This test harness is a simple embedded SWF that makes XML-RPC calls


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 management

Because 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.

____
 
 
URLs and the client-side cache

Why do these techniques work, and why are they needed? Because a web browser's cache is very literal-minded about URLs. Any difference between subsequent requests for a URL--changing query-string values, even changing a letter from lower to upper case--will cause most browsers to ignore the locally cached data and get fresh content from the server.

Most of the time, this cautious behavior is best, since small changes in the URL will often produce a very different response, especially in dynamic Websites. But if the requested resource is a Flash movie or other large file, this is usually a waste of time and bandwidth.

On the other hand, if we request the identical URL twice, the browser will simply use its cached response, unless it finds an HTTP header or other sign that the content is stale or outdated. The difficulty with all such schemes is that we're expected to know this "expiration date" when we post a resource on the site. This makes sense for periodic content (a weekly column, for example), but not if our resource is a software component that might be updated at any time with bug fixes or enhancements.

By tweaking the URL itself, our XML manifest will correctly fetch the latest version of any file. Happily, this solution also works correctly with caching proxy servers.

 
____
Flash (SWF) files and how they relate

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 file

After 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:

<dtml-let appBasePath="absolute_url(relative=1)">
<AppComponents
  baseURL="<dtml-var absolute_url>"
  dataVersion="1.0"
>
  <dtml-in objectItems>
     <<dtml-var expr="id().split('.')[0]">
     modDisplayTime="<dtml-var expr="bobobase_modification_time()" fmt="aCommon">"
     URL="<dtml-var absolute_url>?mod=<dtml-var
expr="bobobase_modification_time().millis()">"
     />
  </dtml-in>
</AppComponents>
</dtml-let>

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:

<AppComponents
  baseURL="http://127.0.0.1:8080/MyApp/Start"
  dataVersion="1.0"
>
    <main
      modDisplayTime="Mar 17, 2004 11:41 pm"
      URL="http://127.0.0.1:8080/MyApp/Start/main.swf?mod=1079584903293"
     />
     <shared_assets
      modDisplayTime="Oct 11, 2004 12:12 pm"       RL="http://127.0.0.1:8080/MyApp/Start/shared_assets.swf?mod=1097511156897"
     />
     <shared_fonts
      modDisplayTime="Mar 17, 2004 11:41 pm"
      URL="http://127.0.0.1:8080/MyApp/Start/shared_fonts.swf?mod=1079584903293"
     />
     <model_viewer
      modDisplayTime="Mar 17, 2004 11:41 pm"
      URL="http://127.0.0.1:8080/MyApp/Start/model_viewer.swf?mod=1079584903293"
     />
      ... etc ...
</AppComponents>

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.

Conclusion

If 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.


Jim Allman:

Jim Allman provides design, programming, and mentoring through his firm Interrobang Digital Media http://ibang.com/. His educational background includes study in the fine arts, film, and industrial design. A self-taught programmer, Jim stubbornly straddles the fence between art and logic, in the belief that truly compelling work is always grounded in both.


shim
shim  ZopeMag is committed to bringing you the best in Zope Documentation. shim
shim


Home   Subscribe   FAQ   Contact   Write for us   Privacy Policy   Weekly News   PyZine   opensourcexperts.com  

Reproduction of material from any of ZopeMag's pages without prior written permission is strictly prohibited. Copyright 2003 - 2005 ZopeMag Zope/Plone hosting by Nidelven IT