Flex build numbers using Ant and flexTasks

July 28, 2007

There are times when it is quite handy to be able to verify the version of a Flex Object which is loaded into the browser. These times include occasions when you think the browser is caching content (swf), when there is an errant build process, or when you are swapping a swf application, or even subcomponents in and out for testing some behavior. Having the Ant builder automatically set a build number and timestamp on the swf, by setting a public var with the values, allows you to put the value setting code in a single module, or in multiple modules and use the same mechanism.

To facilitate this with minimal disruption of the remainder of the code, it is handy to utilize the include directive for Flex builder/mxmlc. The import directive is so commonly used, that the include directive is often forgotten. Adobe Livedoc on include directive. Here is an example:

<?xml version="1.0"?>

<!-- example with Version.as -->

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">

    <mx:Script><![CDATA[

        include "Version.as";

        import  mx.controls.Alert;

    ]]></mx:Script>

    <mx:Button id="versionButton" label="Show current version"

               click="Alert.show(build_number + ' ' + build_time);"/>

</mx:Application>

And here is an example of a template Version.as.template file, prior to copying over to Version.as and replacing the @ tokens:

      public var build_number:String="@buildnumber@";

      public var build_time:String="@buildtime@";

Version.as file with @buildnumber@ and @buildtime@ tokens replaced.

      public var build_number:String="1.0.12";

      public var build_time:String="JUL 08 07 10:01 am";

Ant script to copy the template Version.as and then modify the result with the generated build number and buildtime.  Note that this requires a variable set up for modeldir  (the name modeldir is not important, it’s the path to the directory where where the Version.as file will be).

<taskdef resource="flexTasks.tasks"

         classpath="${ANT_HOME}/lib/flexTasks.jar" />

<target name="cvsbuild">

     <buildnumber file="mybuild.number" />

     <tstamp prefix="build"/>

     <tstamp>

         <format property="build.time" pattern="MMM dd yy hh:mm aa"

              offset="-1" unit="hour"/>

     </tstamp>

     <echo>Build Number ${build.number} ${build.time}</echo>

     <copy file="${modeldir}/Version.as.template"

              tofile="${modeldir}/Version.as" />

     <replace file="${modeldir}/Version.as"

            token="@buildnumber@" value="${build.number}" />

     <replace file="${modeldir}/Version.as"

            token="@buildtime@" value="${build.time}" />

</target>

The nice thing about setting vars like this, is it is possible to reach into any such object and pull out the version number for verification. This could be checked at runtime, or in your UnitTesting, or manually to follow up on a user reported issue.

Ant References: BuildNumber , tstamp, replace .

Advertisements

Degrafa – Flex Framework for Visual Elements

July 23, 2007

  When Flex was first introduced, there was, most prevalent, Cairngorm and Arp as support frameworks (Flex *is* a framework, don’t forget).  Both emphasized the data connection element, which was the biggest problem with Flash Remoting, so it makes a lot of sense.  Today, however, we are seeing a real need for the extension of some of that kind of methodology for the designer/graphics side of things.

  The Degrapha framework (http://www.degrafa.com/) promises to help ease some of the pain, or close the divide between the designer and the developer.  Called a “Declarative Graphics Framework” by its designers, Jason Hawryluk and Juan Sanchez, it provides support for re-use and extensibility on the graphics and visual side of the Flex development milieu.

  I took a moment this week to catch up on the Gausax framework developments (http://ablesa.wordpress.com/), and Angel Blesa has done quite a bit of good work there.  Check out the comparison of implementations of the Flex Store using no framework, Cairngorm, and then Gausax.  This treatment helps to easily see the difference.  The simplification of frameworks is what developers want, in order to remain Agile. 

  None of these is a case of replacing one thing with another.  There are benefits and strengths shown by each.  It is always a case of matching the solution with the problem, taking into account the complete context of the project at hand, customer requirements and the available resources. 


For Historical Reasons, Opcode Value 186 is not Used.

July 20, 2007

I run across obscure references from time to time, and they have a tendency to stick in my mind, like part of a pattern that needs to be matched.  As perfect as an abstraction as mathematics may appear to some, it carries its own set of special cases and exceptions.  We assume that these are naturally occurring and just accept them at face value.  It is not very useful to try to figure out why Pi is not a round number.  It is what it is.

  The domain of computer languages and software carries its own set of special cases and exceptions, but often these are the result of human conditions.  And in carrying out whatever pursuits we are engaged in, they are accepted and we say “it is what it is.”  Following is a brief catalog of numbers, mostly with a computer related historical description, but some with related cultural references:

186  (oxBA)-Java opcode which was not used in the first Java virtual machine, for historical reasons.

3:16 – Lecture and Book by Don Knuth, author of the Art of Computer Programming.

0xCAFEBABE – Magic number which appears at the start of every Java class file (bytecode).  Note the presence of 0xBA in 0xCAFEBABE, in the third byte position.

0xCAFEDEAD – Rumored to be the originally desired magic number for Java class files, as the developers were fans of the Grateful Dead. It had already been used for other things, so CafeBabe was used instead.  Note that Java 1.0 was released January 23, 1996, 167 days after the death of Grateful Dead guitarist Jerry Garcia.

0x504B – Magic number at the begining of every ZIP format file.  These are the hex codes for ASCII characters ‘PK’ initials of  Phil Katz, the author of the original zip compression program.

0x4D5A – Magic number at the beginnng of every DOS executable program.  These are the hex codes for ASCII characters ‘MZ’, initials of the developer of the file format, Mark Zbikowski.

8675309 – Seen in many, many more oscure contexts for computing.  From unlock codes for games, to causing a mode change for Microsoft’s WebTV, and various others.  This was Jenny’s Phone Number, in the hit song by Tommy Tutone.

420 – A cultural reference to cannibas. 

404 – Page Not Found Error Code in HTML

2600 – The frequency originally used by AT&T to signal a ready state for a long distance phone line.  Also the same frequency which was produced by a toy whistle which was given as a toy surprise in Captain Crunch Cereal in the mid 1960’s.  As an added curiosity, to no one except for myself, I happen to have the home printer, HP Photosmart 2600.

90125 – The original catalog number of the Yes album, by the same name.

9:15 – Time of the train referenced in The Who’s Quadraphenia in the song by the same name.

90210 – The zip code for a Bevery Hills neighborhood in which a popular 1990’s tv series was based.

The appearance of numbers and codes like those listed is frequent.  The presence of codes and oddities in the digital domain offer an endless supply of curiosities.  The crossing of domains has become more and more commonplace as computers and digital electronics settle into their place in our culture.  Phone numbers become song titles, and song titles become codes in computer file formats, and will continue to do so.  And most of the time, “they are what they are.”


Value Object Bustifiers

July 2, 2007

  I’ve been fashioning Brian Renaldi’s the <a href=”https://howardscholz.wordpress.com/wp-admin/code.google.com/p/cfcgenerator/&#8221; target=”_blank”>Illudium PU-36 Code Generator</a>  package to produce scaffolding for the Cairngorm framework.

People tend to have opinions about code generation, scaffolding being a euphemism for a specific portion of code generation.  I really like the dynamic scaffolding employed by Groovy/Grails and Ruby/Rails, wherin the functionality of the scaffolding is generated, but the code is not.  That seems pretty cool.  It would be Uber Cool to generate the entire application that way, and have no code except for that very special case stuff.  But even generated scaffolding serves its purpose, and helps a group development effort have some consistency.
Typically, what I do in my VO’s is have them accept a parameter that is of type object, and let the constructor act as a sort of copy constructor, if it is fed an object, otherwise leaving the default values.
A further item that is handy in scaffolding, is making the assignment case insensitive.  Coldfusion is case insenstive, and Actionscript, is case sensitive.  So those assignments can be troublespots sometimes.  Also, sometimes there may be a mismatch between the VO properties and the properties returned from the persistent store, so any mismatches are observed and traced to the console output.

To handle these items, I’ve added the following:

/**
* Default constructor.
*/
public function CategoryVO(data : Object = null) : void {
if (data == null) return;
var dataDesc:Object = ObjectUtil.getClassInfo(data);
var myDesc:Object = ObjectUtil.getClassInfo(this);
var props:Array = dataDesc.properties;
var myProps:Array = myDesc.properties;
var found:Boolean = false;
for each (var name:String in props) {
found = false;
for each (var myName:String in myProps) {
if (!found &amp;&amp; myName.toUpperCase() == name.toUpperCase() ) {
this[myName.toUpperCase()] = data[name.toUpperCase()];
found = true;
break;
}
}
if (!found)
trace("CategoryVO - Input Object has extra property " + name);
}

The business delegate layer I’ve seen done in a pretty boilerplate manner, where it acts as kind of a pass through layer to the Commands.  More correctly, any data conversion that may be platform specific, like Coldfusion or PHP related Object constructs, should be handled in the business delegate layer, isolating the platform details from the remainder of the Actionscript code.  That makes this layer a little more interesting for matters of code generation.


Handling Results in Flex from RemoteObject calls in ColdFusion

July 2, 2007

I’m putting together a music library for a client, and I thought I’d take the opportunity to measure the return results from ColdFusion in various forms, and see how they appear in Flex:

1) Calling the songService.cfc to get a list of songs as and ArrayCollection of SongVO So, in the ModelLocator.as, the songList is declared as:

[ArrayElementType("SongVO")]public var songList:ArrayCollection = new ArrayCollection();

The SongVO is tied to the cfc with a meta tag like this:

package com.musiclib.fx.vo
  {
      import flash.events.EventDispatcher;
      [RemoteClass(alias="com.musiclib.db.Song")]
	  [Bindable]         
         public class SongVO extends EventDispatcher         
         {         
         public var song_id:Number = 0;         
         public var owner_id:Number = 0;         
         public var category_id:Number = 0;         
        <snip>        

Finally, the value is returned from the cfc as the ColdFusion equivalent of the AS class. In this case, I am calling getSongList(). In order to type all of the rows, each query result row must be cast into the coldfusion component type. So, when we receive the result, we get:

Charles network capture of result In the debugger, we see the modelLocator songList as null or Empty. Time to reach into the bag of tricks

debugger view of cfc call result

A quick look in the Flex manual tells me:

“Handling service resultsAfter an RPC component calls a service, the data that the service returns is placed in a lastResult object. By default, the resultFormat property value of HTTPService components and WebService component operations is object, and the data that is returned is represented as a simple tree of ActionScript objects. Flex interprets the XML data that a web service or HTTP service returns to appropriately represent base types, such as String, Number, Boolean, and Date. To work with strongly typed objects, you must populate those objects using the object tree that Flex creates.WebService and HTTPService components both return anonymous Objects and Arrays that are complex types. If makeObjectsBindable is true, which it is by default, Objects are wrapped in mx.utils.ObjectProxy instances and Arrays are wrapped in mx.collections.ArrayCollection instances.

NOTE Macromedia ColdFusion is case insensitive, so it internally uppercases all of its data. Keep this in mind when consuming a ColdFusion web service.

But, returning to a previous post, I pull this code, and plop it in:

 var result:Array = resultEvent.result as Array; 

    for (var i:String in result) 

    { 

result[i] = new ObjectProxy(result[i]); 

} 

    ModelLocator.getInstance().myArray = result as ArrayCollection; 

Well, that didn’t help one bit. I have the same results.

Now, if I return a query, directly from the cfc, and assign what comes back directly to the target arrayCollection songList, then everything works just fine.