Notes: Adobe AIR Local Data Storage Options

The following are my notes during the Adobe AIR Local Data Storage Options webinar that was presented during Adobe Developer Week. It was presented by Greg Hamer and the slides and demo code are already online.

Before getting started, note how Microsoft and Adobe are taking two different approaches: Microsoft is trying to bring the .Net desktop development community to the web. Adobe is conversely trying to bring web developers to the desktop! (Kevin Lynch)

There are four main options for AIR local storage: Local Shared Objects, File System, Encrypted Local Store, and the embedded SQLite database. Shared Objects are available in the Flash Player as well; all of these options are obviously available in AIR. Note that the data size limitation for Shared Objects does not exist in the AIR runtime!

Performance considerations. Shared Objects read and write very quickly. File system access and encrypted local stores are typically be slow in writing. Embedded SQLite databases are typically the best combination of speed and random access of items. Greg highlighted the AIR_LocalStorage_Demo app created by Jason Williams that demonstrates the speeds of the four storage methods.

Local Shared Objects. You can serialize memory resident data structures. Great! However, it runs in synchronous mode.

Encrypted Local Store. Used to store sensitive data. The price is the slow write speeds.  Also runs in synchronous mode. All data is serialized using ByteArray.

File System. Obviously important for management of documents. Can run in sync and async mode. The File and FileStream objects work together to point to a file and read/write data. The File object helps remove you from the pain of dealing with Mac vs. Windows environments with properties like File.userDirectory, File.documents.Directory, File.desktopDirectory, etc. It also has methods for opening Open and Save dialog boxes native to the environment as well as copying/moving/deletion methods.

Embedded SQLite Database.  Nice thing about them is that they are self-contained in a single file and require no external software installation to begin using them (support is built into the AIR runtime). Even supports transactions. And the database supports large amounts of data: SQLite has a theoretical limit of over 2TB. Supports ANSI-SQL 92.

However, it’s not a full-blown enterprise database server, obviously. So you lose things like stored procedures, enforcing data type constraints, foreign key constraints, and primary keys must be integers. It also isn’t a multiuser environment.

Session evaluation. I am unhappy to say that I was disappointed with the session. It was high-level, the coverage of code samples (when they weren’t passed over completely) consisted of merely reading the code back to us. I recommend viewing the recording if you have zero knowledge of data storage in Flex and AIR, as it would serve as a decent first-baby-step introduction for you.

The Solution to Flex Remoting Over SSL

If you've tried calling ColdFusion CFCs with RemoteObject over SSL in your Flex apps, you probably feel my pain already, because you have either tried to get it working and gave up, or had a heck of a time getting it working. Adobe's documentation for this specific need wasn't helpful to me, and discussion about it online is relatively sparse and unsure as well, from what I've seen. My intranet environment at work demanded that I get remote communication with CFCs working over SSL, so as I neared completion of my first couple Flex apps, I needed to get an understanding of this issue. Hopefully it will be useful to others.

So, what's the problem? In a nutshell, when you try to use the RemoteObject component in a Flex app to communicate with CFCs, the default installation of ColdFusion 8 and Flex Builder 3 will compile your app to communicate with the ColdFusion server over HTTP (http://yourserver.com/flex2gateway/), not over HTTPS (https://yourserver.com/flex2gateway/cfamfsecure), regardless of whether the SWF was loaded over HTTPS or not.

If your site exists in both HTTP and HTTPS, you may not even be aware this is happening. I wasn't aware of it while I was developing on my local machine. But our production server hosts its site only in HTTPS and the site on port 80 is a nearly empty site that redirects all requests to the SSL-protected version of the site. So this behavior broke my Flex app.

If your site exists only in SSL or sensitive data is being transmitted to and from the Flex app and the CFCs, you probably are trying to get RemoteObject to communicate over SSL.

Quick workarounds. If you have time and leniency to skirt the issue, you can avoid the RemoteObject/SSL issue. You can always use the HTTPService and WebService components instead of RemoteObject. But like most workarounds, this has its disadvantages and limits you from the benefit of using RemoteObject.

I imagine you also could set up a ColdFusion mapping to make the CFCs available on the HTTP site, but this solution is viable only if you really don't care about security, in which case you probably wouldn't have your site wrapped in SSL anyway.

The solution. What makes the solution tricky is that there are a few things that have to be configured properly, and there are some pitfalls along the way that can be misleading. The primary solution lies in some changes to the ColdFusion server's config files services-config.xml and remoting-config.xml. These both reside in {ColdFusion installation}\wwwroot\WEB-INF\flex\. For instance, on my Windows workstation, this is located at c:\ColdFusion8\wwwroot\WEB-INF\flex\.

1. Add the secure channel to remoting-config.xml. ColdFusion 8 already has a channel in its configuration for RemoteObject over SSL--it is called "my-cfamf-secure"--it just isn't configured to be used. So you have to add the "my-cfamf-secure" channel to remoting-config.xml. To do this, add <channel ref="my-cfamf-secure" /> to the <default-channels> node and the <channels> node for the "ColdFusion" destination.

In other words, your new remoting-config.xml file should look like this:

XML:
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <service id="remoting-service" class="flex.messaging.services.RemotingService" messageTypes="flex.messaging.messages.RemotingMessage">
  3.     <adapters>
  4.         <adapter-definition id="cf-object" class="coldfusion.flash.messaging.ColdFusionAdapter" default="true"/>
  5.         <adapter-definition id="java-object" class="flex.messaging.services.remoting.adapters.JavaAdapter"/>
  6.     </adapters>
  7.     <default-channels>
  8.         <channel ref="my-cfamf-secure"/>
  9.         <channel ref="my-cfamf"/>
  10.     </default-channels>
  11.     <destination id="ColdFusion">
  12.         <channels>
  13.             <channel ref="my-cfamf-secure"/>
  14.             <channel ref="my-cfamf"/>
  15.         </channels>
  16.         <properties>
  17.             <source>*</source>
  18.             <!-- define the resolution rules and access level of the cfc being invoked -->
  19.             <access>
  20.                 <!-- Use the ColdFusion mappings to find CFCs, by default only CFC files under your webroot can be found. -->
  21.                 <use-mappings>false</use-mappings>
  22.                 <!-- allow "public and remote" or just "remote" methods to be invoked -->
  23.                 <method-access-level>remote</method-access-level>
  24.             </access>
  25.             <property-case>
  26.                 <!-- cfc property names -->
  27.                 <force-cfc-lowercase>false</force-cfc-lowercase>
  28.                 <!-- Query column names -->
  29.                 <force-query-lowercase>false</force-query-lowercase>
  30.                 <!-- struct keys -->
  31.                 <force-struct-lowercase>false</force-struct-lowercase>
  32.             </property-case>
  33.         </properties>
  34.     </destination>
  35. </service>

This brings me to the first pitfall to watch out for. Be sure to list <channel ref="my-cfamf-secure" /> ahead of <channel ref="my-cfamf" /> so that ColdFusion will try the secure channel first.

2. Add a property to make IE happy. At this point, your configuration will be adequate for Firefox. However, IE still seems to get tripped up and tries to access the insecure channel. To fix this, just add <add-no-cache-headers>false</add-no-cache-headers> to the <properties> node of the <channel-definition> nodes for "my-cfamf" and "my-cfamf-secure" in services-config.xml.

I won't display the entire services-config.xml file here, but your "my-cfamf" channel definition will now look like this:

XML:
  1. <channel-definition id="my-cfamf" class="mx.messaging.channels.AMFChannel">
  2.     <endpoint uri="http://{server.name}:{server.port}{context.root}/flex2gateway/" class="flex.messaging.endpoints.AMFEndpoint"/>
  3.     <properties>
  4.         <polling-enabled>false</polling-enabled>
  5.         <serialization>
  6.             <instantiate-types>false</instantiate-types>
  7.         </serialization>
  8.         <add-no-cache-headers>false</add-no-cache-headers>
  9.     </properties>
  10. </channel-definition>

And the "my-cfamf-secure" channel definition:

XML:
  1. <channel-definition id="my-cfamf-secure" class="mx.messaging.channels.SecureAMFChannel">
  2.     <endpoint uri="https://{server.name}:{server.port}{context.root}/flex2gateway/cfamfsecure" class="flex.messaging.endpoints.SecureAMFEndpoint"/>
  3.     <properties>
  4.         <polling-enabled>false</polling-enabled>
  5.         <serialization>
  6.             <instantiate-types>false</instantiate-types>
  7.         </serialization>
  8.         <add-no-cache-headers>false</add-no-cache-headers>
  9.     </properties>
  10. </channel-definition>

Some more pitfalls to consider. These can be really misleading, making you think your changes aren't working.

A. Flex Builder incorporates these settings into your app when it compiles the SWF. Go to your Flex project's properties, under "Flex Compiler", and you'll see a reference to your services-config.xml file. If your SWF is compiled on a workstation that hasn't had these changes, it will not work on your server, even if you did change your server's config files. So be sure that your local installation of ColdFusion has its services-config.xml and remoting-config.xml files updated just like your production server.

B. On a related note, be sure to recompile an app if you've compiled it before making these config changes. You can recompile in Flex Builder by going to Project > Clean. That option will ensure that you have a clean, recompiled SWF.

C. If your SWF file is actually served on port 80, it will not be allowed to communicate over the secure channel unless you tell it that it is permissible to do so by setting up a crossdomain.xml file. Check out Shannon Whitley's post SSL, crossing domains, and Flex to read a bit on that.

Tools for the job. With the right tools, you can test all of these things out on your own. For instance, Firebug and Fiddler are great tools for Firefox and IE respectively that clearly show your Flex app's behavior, and whether it is attempting to access the secure or insecure channel. They also show the app attempting to access a crossdomain.xml file when the SWF file was loading over HTTP, because it's first attempt is to make a cross-domain connection to the secure HTTPS channel.

The great thing about this configuration is that your SWFs will use the secure channel when they can, but silently fail over to the insecure channel. So your development workstation doesn't have to use SSL, but your compiled apps will utilize it when you move them to your production server. This is cleaner than setting up a separate "Destination" in remoting-config.xml, or other solutions that require changes to your app's code. Alas, I am still green in the Flex universe and don't claim anything different. Nevertheless, this solution is working perfectly for me and I hope it proves useful for you.

iPhone AIR?

So, with Apple preparing to hold an iPhone Software Roadmap event this Thursday, people are eagerly anticipating news about how Apple will handle an SDK for the iPhone environment.

Many developers were frustrated--and many web developers had our curiosities pleasantly piqued--when Apple initially announced that "software" would be available for the iPhone in the form of Ajax web applications. Naturally, many of the disappointed folks were irritated because the web platform is something that they're entirely unfamiliar with, probably having backgrounds in Objective C or something similar; probably a minority were disappointed because their target application legitimately could not be powered by HTML and Ajax.

That said, it is indeed a very thought-provoking concept: Using web technology as your application environment. As most web developers will attest to, there honestly isn't that much that a typical application does that cannot be accomplished with web technology. With the advent of Ajax frameworks, applications built with web technology can have very similar responsiveness and dynamics of a "classic" application. Especially when you remove the burden of cross-browser compatibility, in the iPhone's case.

But with the iPhone/iPod Touch scenario, it is irritating that the application has to reside in Safari and has to be loaded off the web. It almost feels as if Apple was trying to push something that wasn't...quite...ready. Something like AIR!

AIR accomplishes everything that Apple was suggesting for the iPhone environment, but for the desktop. Use web technology, but write a "compiled", stand-alone application that really doesn't even have to use the web. Use HTML. Use Ajax. Use Flex and Flash. Have a nice encapsulated application on your desktop. Especially when you throw the Flash technology into the platform, it is now a very capable environment for a large variety of applications, without being constrained to the browser. Wouldn't it be great if that same cross-platform environment, AIR, worked on the iPhone as well?

Oops, Flash technology isn't currently supported by the iPhone. That is actually another source of contention. And the AIR environment does lose some of its punch without Flash and Flex, even though its HTML/Ajax implementation can do a very decent job with most typical applications.

Steve Jobs has made it clear that he likes the idea of web technology powering iPhone apps. Now, consider some of the facts. Apple announces the iPhone SDK will be released in February, and then fails to deliver. Meanwhile, Flash still isn't found on the iPhone, and Adobe "invents the wheel" by getting web technology to drive native apps through its work with AIR. Is there a common theme with these events? Perhaps something like: Are Apple and Adobe working together to get the much-needed Flash technology onto the iPhone and, subsequently, releasing an SDK that uses AIR technology, with hooks into the iPhone system just like AIR currently has hooks into the Linux, Windows, and Mac OS X desktop operating systems?

It wouldn't be the first time Apple has had to wait for its partners, or take the heat for them. For instance, Apple has clearly been taking a lot of heat for many factors of the iPhone that are clearly not in Apple's interest, but in AT&T's.

And this scenario would fit the circumstances around Adobe's development of AIR. Adobe has been working on AIR since well before the iPhone was released, but AIR wasn't officially released until February 25, 2008. Even if Apple and Adobe were working closely together, there just hasn't been enough time for AIR to get released and hooks to be developed to provide iPhone-specific functionality in AIR. Adobe has understandably concerned itself with its own business first. With that done, attention can turn to Apple to support them in concluding their own business.

Of course, this prediction is a reflection of my own desires as much as it fits the circumstances. As a developer that uses Adobe technology including Flex and AIR, and an Apple enthusiast for more than 20 years, I would love to see things happen this way. Undoubtedly we will have a clearer idea of Apple's iPhone development roadmap after this Thursday.

As if the thought of an "iPhone AIR" isn't confusing enough. :-)

Notes: BlazeDS Revealed!

These are notes from the presentation by Tom Jordahl about BlazeDS.

History lesson. Flex 1.0 introduced MXML. Originally built to be a server-based compiler. Flex 2.0 fine-tuned the product. ActionScript 3 was introduced, the Eclipse-based IDE was developed, and the server-side component was renamed Flex Data Services. That server-side product continued development and was renamed eventually to LiveCycle Data Services. Finally, a free portion was released as BlazeDS. So, its heart and heritage is in the development of Flex.

So what is BlazeDS? The part that lets your Flash/Flex app have remoting and messaging services via web services, remote objects, data push, etc.

Remoting. Used to be Flash Remoting. Allows mx:RemoteObject tag be used to make RPC calls to the server. Allows you to use CFCs and ActionScript or MXML together! Works with Java classes too, but obviously it is very nicely integrated with ColdFusion. This is the most familiar purpose for this kind of tool. But what else can BlazeDS do?

Messaging. Publish and Subscribe functionality becomes trivial. We can have real-time pushes over the web. What exactly does this mean? Your Flash/Flex apps can push data from one client to the next without refreshes or polling the server.

These services use AMF (Action Messaging Format). It is fast and small: Rather than being verbose text, it is a compact binary protocol. Not that you would ever have to know that, because it just happens behind the scenes. And its specs have been released, which means it can be supported by open source and third party developers.

So why would you still get LCDS? Well, you get certified builds with warranty coverage and support. You're paying for Adobe to back the product. There will even be an LCDS "Community Edition" that will basically be BlazeDS with this support. Somewhat reminiscent to Red Hat vs. CentOS: Why get Red Hat when CentOS is everything Red Hat is? Because Red Hat has official support for its product. So Adobe is making the technology freely available, and giving you the option to pay for support and official builds and bug fixes.

LCDS "Enterprise Edition" is still the mother of data services. This version adds the data management capability of data services.

The installation of ColdFusion 8 gives you the free express edition of LCDS. But this is a single CPU license. If it doesn't meet your needs, you can configure BlazeDS for ColdFusion 8. But to do this, you WILL have to remove the LCDS Express Edition that installed with CF8. Now, if you're just using Flash Remoting, there isn't any burning need to go to BlazeDS with CF8. However, the messaging features have no CPU restrictions with BlazeDS, so if you are using the messaging features, you may want to go with BlazeDS.

What do you use with BlazeDS vs. LCDS? LCDS has the data management features: Real-time data updates, conflict detection, caching, paging, more! RTMP channels: Direct socket connection to server, instead of the more resource-expensive HTTP. Scalability is also better with LCDS.

Tom indicated that Flex and BlazeDS will not be standing still. He certainly implied that Silverlight is in Adobe's sights by indicating that it is "nipping at [Flex's] heels", suggesting that the AIR, Flex, and BlazeDS technologies will be progressing in development at a rapid pace by Adobe.

Tom explained BlazeDS and LCDS very clearly, albeit at a quick pace at first. My development rarely calls for the messaging features that would especially drive me to BlazeDS, but even so, it was beneficial to understand what BlazeDS is and it is good to know even when a product is not needed in your development arsenal, as in my case. For me, I will be using remoting only, so will stick with LCDS Express that comes with CF8.

Thanks, Tom.

  Theme Brought to you by Directory Journal and Elegant Directory.