Showing posts with label as3. Show all posts
Showing posts with label as3. Show all posts

Monday, 23 July 2012

Bug: AIR for Android, SharedObject and File


While working on a recent AIR for Android application, I found myself pulling my hair out over a strange bug. To speed up application development, I was persisting some of my application VOs using SharedObject, e.g:

var appSharedObject: SharedObject = SharedObject.getLocal( "appModel" );
appSharedObject.data[ "content" ] = vo;
appSharedObject.flush(  );

This had been working flawlessly for some time, and I had little reason to suspect it. The symptoms were particularly painful: after the application had finished with one View, persisted the data and attempted to move onto the next View, the application would unexpectedly close. There was no error, no crash and no stack trace.

Thankfully, my persistence layer had already been abstracted into a service, and I was able to implement an empty version and plug that in with little effort. With this in place, everything worked fine, so I was confident it had something to do with the SharedObject persistence. I needed to debug things further, but didn't want to spent hours rewriting the application.

Enter the [Transient] metadata. Adobe defines this metadata element as:

Identifies a property that should be omitted from data that is sent to the server when an ActionScript object is mapped to a Java object using [RemoteClass].

However, it can be used to provide hints to the SharedObject serialization system on which fields to ignore: marking any fields with [Transient] will see them ignored by SharedObject. By using this trick, I was able to use a binary search to very quickly identify which field was causing the problem. It turned out that a File instance containing a reference to a captured photo was causing a low-level crash with the AIR runtime, when it was serialized to a SharedObject; the same location stored in a String presents no problem (and, for that matter, files pointing to other locations present no problem).

Hopefully this saves someone else a heap of time!

Monday, 23 January 2012

Calling LiveCycle processes via Remoting, involving Documents

One nice aspect of Adobe's LiveCycle is the ability to easily invoke a process using Flex Remoting. For 'primitive' types, such as Number, XML and String, it's a straight-forward case of passing them to the Remoting call. However, in some instances, it is necessary to pass a LiveCycle Document instance to a Remoting call. The recommended means of doing this involves a two-step process, where the Document is uploaded to the LiveCycle server, which returns a DocumentReference. This reference is passed to the Remoting call and LiveCycle marries everything up on its end.

I encountered an issue with this recently in an enterprise environment, due to the way DocumentReference works. After the Document has been stored on the server, LiveCycle constructs a URL pointing to it - based on the application URL of the Flex application that performed the upload. In our client's case, the application URL does not resolve inside their firewall. This meant that when LiveCycle attempted to load the Document based on the DocumentReference, it was unable to locate it.

Manipulating the DocumentReference on the client side was ruled out, due to the maintenance nightmare and security implications of having internal infrastructure details stored within the application itself. Resolving the issue on the server side was not a straightforward solution, as all processes involving Documents would have to be changed.

It turns out there's a simple solution; instead of performing a HTTP-based Document upload (which also has problems in a HTTPS context on non-IE browsers), it is possible to manually construct a DocumentReference instance, and pass in the file data by hand. For example:

var documentReference: DocumentReference = new DocumentReference(  );
documentReference.referenceType = DocumentReference.REF_TYPE_INLINE;
documentReference.bytes = yourByteArray;

Wednesday, 2 November 2011

Emplore: A Constraint Engine

I've started putting together a framework I'm code naming Emplore. It's a constraint engine that was born out of having data models being manipulated in multiple places in applications and a subsequent need to perform constraint checking in those places.

The general concept is that annotations will be used to decorate the model with constraint definitions. For example:

public class MyModel
{
  [Required]
  [ConstrainLength( minLength=1, maxLength=100 )]
  public var aString: String;

  [ConstrainRange( minValue=-123.4, maxValue=234.5 )]
  public var aNumber: Number;
}
The intention from here is that there will be functionality for automated validator generation and API-based constraint checking. Stay tuned for more.