So you are building a enterprise Flex application that uses automated builds with ant. You are running into the issue of multiple modules and assets that use the same name but you want to identify the swf by the specific version of the build and maybe even deploy multiple builds in the same structure allowing them to share un- changed resources. Or just maybe you want to make sure that when you deploy a new production build, that the swfs are not cached. The below code will help with both scenarios. As a quick background, when using RSLs, the RSL contains a digest or UID that when the application is compiled, it is compiled against that digest. When requesting RSLs, the application request RSLs by name but then also validates the digest against what the application was compiled against to ensure it is using the latest / correct library.
/**
* property in the build file that identifies the version number used to build swfs
* @private
*/
private static const BUILD_PROPERTY_VERSION_IDENTIFIER:String = 'version';
/**
* The regular expression that only allows numbers, dashes, and period from the build
* property string
* @private
*/
private static const BUILD_PROPERTY_VERSION_REG_EXP:RegExp = /[^0-9-.]/g;
[Embed(source="../build/build.properties", mimeType="application/octet-stream")]
/**
* Embedded build property file
*/
private static const embeddedBuildFile:Class;
/**
* With searching if an item is not found it return -1, so anything 0 or greater means the
* item has been found at least once in the string.
*/
private static const ITEM_FOUND:int = 0;
/**
* The version of the application
* @private
*/
private var _appVersion:String = '';
/**
* If the property is not already set, loop through all build properties that have been embedded
* when compiled until the property contains an identifier related to the build version. Once found,
* clean up any characters that are not of a build number and set property
* @return build version number
*
*/
public function get version():String
{
if (_appVersion == '')
{
// Create a new class of the embedd type and cast as a string to initialize
var buildProperties:String = String(new embeddedBuildFile());
// Split all line breaks into an array
var arr:Array = buildProperties.split("\n");
var i:int = 0;
var len:int = arr.length;
var buildProperty:String;
// Loop through all poperties untile the identifier is found and set
for (; i < len; i++)
{
buildProperty = arr[i];
if (buildProperty.search(BUILD_PROPERTY_VERSION_IDENTIFIER) >= ITEM_FOUND)
{
_appVersion = buildProperty.replace(BUILD_PROPERTY_VERSION_REG_EXP, '');
break;
}
}
}
return _appVersion;
}
We want to essentially copy this same structure while also promote caching when possible. In most build scenarios you are versioning the application and maybe using automated incremental build numbers. This is a great thing and something we want to take advance of, so the first step is to embedded the build.properties file (properties.xml would require parsing as XML) so we have the incremented version or build number that the swf is being built as. When embedding the properties file, you can try decompiling the swf, but you will not be able to read out the file – only during runtime initialization will the values be available. This may be a great thing if you are using encryption keys in the application. So the file has the latest build so then the next step just comes to instantiating and looping through the values until the expected property is found and then just clean up the property values based on your versioning scheme.
The next step to this is to build out your applications, modules, and runtime assets with the build version appended. Example; Application.1.2.3-45678.swf or module.1.2.3-45678.swf. This allows a visual identifier of the build version and ability to deploy multiple applications of different builds to the same directory. Now the real reason we have embedded the version in the application is we need to know the URL for the assets or the modules – we know the identifier but need to append the version. This will allow an application to only load the correct module or asset swf for the specific build. This example can also be extended to custom libraries or even as RSLs.
The other benefit to this approach is caching, when building Flex application we have all run into informing the client to clear there cache and try again – but no more. In this scenario the application.html page will be requesting a completely different swf file because it will be referencing the swf with the appended build, so it will always be fresh – but not just that, we also will be leveraging the caching of the swf in the browser. If the application.html file is pointing to the same swf consecutively it will use the cache of the swf and you will no worry about the client having the latest and greatest. You can use this in a singleton or static through-ought the application if there are other properties that might be worth noting like server build time . Can definitely go into more detail but hopefully this can help other out and is a good start.