Continuous Integration with Flex, Hudson, and ArcGIS Server, Part 2

(Part 1Part 3Part 4)

In the last post, I talked about the very basics of getting a Flex project going with Flex Builder and ant.  The current ant script we have just builds the SWF file, which leaves out a bunch of files that Flex Builder uses, and that is bad as defined by what I am trying to blog about here.  So, let’s get going on pulling over the rest of the files.  Well, at least, the important ones.  The most important one is likely the HTML file that wraps our SWF.  If we are going to deploy this SWF in any meaningful (read: web) manner, we need that HTML file.  Actually, we need one that we make ourselves and pull into our build process, but that will left as an assignment for the reader.  For the sake of this series, we’ll just reuse the HTML file that Flex Builder was kind enough to generate.

In the default Flex Builder project, one of the folders is html-template, that looks like:

image

Not much to it, really.  I am not gonna go into the meat of what the files are, if you want that go here.  In a nutshell, what we need to do here is copy this whole directory to our output folder (our ${deploy.dir} for you sharp ones following along).  There is a slight caveat here, tho, and that’s the contents of the index.template.html.  If you open that file in a text editor, you’ll see snippets like:

AC_FL_RunContent(
        "src", "playerProductInstall",
        "FlashVars", "MMredirectURL="+MMredirectURL+'&MMplayerType='+MMPlayerType+'&MMdoctitle='+MMdoctitle+"",
        "width", "${width}",
        "height", "${height}",
        "align", "middle",
        "id", "${application}",
        "quality", "high",
        "bgcolor", "${bgcolor}",
        "name", "${application}",
        "allowScriptAccess","sameDomain",
        "type", "application/x-shockwave-flash",
        "pluginspage", "http://www.adobe.com/go/getflashplayer"
    );

where you may notice the now familiar ${} variables.  So, now our simple copy has turned into a copy and replace all the ${} tokens with their appropriate values.  Nothing is ever as simple as it should be.

The good news is that it’s not so hard either.  Breaking down what we need to do, I think it looks something like this:

  1. Copy the html-template contents.
  2. Parse the index.template.html and replace the tokens.

Let’s create our ant task to get this done.  I’ll it create-html-wrapper, and it looks like this:

<target name='create-html-wrapper'>
    <copy todir='${deploypath.dir}' overwrite="true">
      <fileset dir='${wrapper.dir}'>
         <exclude name='**/index.template.html' />
     <exclude name='**/index.template.html.svntmp' />
         <exclude name='.svn' />
      </fileset>
</copy>

The copy ant task is a standard task from the ant library.  We are excluding some items here:  we don’t want any source control artifacts to end up in the deploy directory.  I am using subversion here, so I explicitly exclude those.  The one that may look odd is the exclusion of index.template.html.  The reason that file is excluded is because we want to rename it.  I don’t want my HTML file to be named index.template.html, do you?

(NOTE:  The Flex ant tasks include an html-wrapper task, but I found it lacking for reasons that now escape me.  I think the parsing of the HTML files was either not there or crappy.  Either way, I dumped it for some very valid reason, I am sure.)

For the index.template.html, we can use another cool ant ask that uses regular expressions to replace content within a file.  The name of that task is replaceregexp, and it’s dead sexy.  Here is the copy command, and it’s a bit of a doozy.  I am not gonna go through each token, as that would be REALLY boring (not super exciting like the rest of this post)

<!-- Copy and rename the index.template.html -->
<copy file='${wrapper.dir}/index.template.html'
tofile='${html.file}' />
<!-- Copy and rename the index.template.html --> <copy file='${wrapper.dir}/index.template.html' tofile='${html.file}' /> <replaceregexp file='${html.file}' flags='gs' match='\$\{width\}' replace='100%'/> <replaceregexp file='${html.file}' flags='gs' match='\$\{height\}' replace='100%'/> <replaceregexp file='${html.file}' flags='gs' match='\$\{title\}' replace='${APP_TITLE}' encoding='utf-8'/> <replaceregexp file='${html.file}' flags='gs' match='\$\{version_major\}' replace='${version.major}'/> <replaceregexp file='${html.file}' flags='gs' match='\$\{version_minor\}' replace='${version.minor}'/> <replaceregexp file='${html.file}' flags='gs' match='\$\{version_revision\}' replace='${version.revision}'/> <replaceregexp file='${html.file}' flags='gs' match='\$\{application\}' replace='${APP_TITLE}'/> <replaceregexp file='${html.file}' flags='gs' match='\$\{bgcolor\}' replace='#FFFFFF'/> <replaceregexp file='${html.file}' flags='gs' match='\$\{swf\}' replace='${application.name}'/>
(BTW, the replaceregexp stuff I blatantly stole from here, which is a GREAT post on using ant with Flex.  Also goes to show you that I am a couple of years behind the cool kids.)

Finally, let’s take another look at our build.properties file, which added quite a bit of properties for this task.

#Copy this file locally to build.properties and change below for your env

# change this to your Flex SDK directory path
FLEX_HOME=C:/Program Files (x86)/Adobe/Flex Builder 3/sdks/3.2.0

# this points to your project's src directory
# {$basedir} is a default variable that can be used in any Antscript
# and it points to the project's root folder [ flex_ant_pt1_Tasks ]
# in this case
srcpath.dir =${basedir}/src

# points to the project's libs directory
libs.dir =${basedir}/libs

# this is the folder we want to publish the swf to
deploypath.dir = ${basedir}/bin-debug

wrapper.dir=${basedir}/html-template

version.major =0
version.minor=9
version.revision = 0
APP_TITLE = Flex Solution
APP_WIDTH = 100%
APP_HEIGHT =100%
locale = en_US
html.file=${deploypath.dir}/index.html
application.name=FlexAGSCI

We have some of our HTML tokens, like width and height, a new directory (wrapper.dir) and the name of our HTML file.  For the ant build, I rename it to index.html because I plan on using ant to actually deploy the application to a web server and I want a default document name to be used.

So, next post will concentrate on adding a unit testing framework and getting ant to run our tests too.  I know the first couple of posts were mongo-basic, but I wanted to lay a bit of a foundation before getting into the cooler stuff.  We’ll get there.  I am about to head off on a mini-vacation, so it might be a week or more before I get to it.  I hope you can manage until then….

Oh, and here’s our build.xml, in full, just for fun:

<project name='Flex Ant Tasks Build Script' default='build-flex-project'>
    <!-- load properties file -->
    <property file='build.properties'/>

    <!-- points to are flexTasks.jar -->
    <taskdef resource='flexTasks.tasks' />    

    <!-- delete and redeploy -->
    <target name='init'>
        <delete includeemptydirs='true'>
            <fileset dir='bin-debug' includes='**\*' excludes='**\.svn'/>
        </delete>

    </target>
    <target name='build-flex-project' depends='init,create-html-wrapper'>
        <mxmlc file='${srcpath.dir}/${application.name}.mxml' output='${deploypath.dir}/${application.name}.swf'>
            <load-config filename='${FLEX_HOME}/frameworks/flex-config.xml'/>
            <include-libraries file='${libs.dir}' />
        </mxmlc>

    </target>

    <target name='create-html-wrapper'>
        <copy todir='${deploypath.dir}' overwrite="true">
              <fileset dir='${wrapper.dir}'>
               <exclude name='**/index.template.html' />
               <exclude name='**/index.template.html.svntmp' />
               <exclude name='.svn' />
              </fileset>
        </copy>
          <!-- Copy and rename the index.template.html -->
         <copy file='${wrapper.dir}/index.template.html'
              tofile='${html.file}' />
          <replaceregexp
              file='${html.file}'
              flags='gs'
              match='\$\{width\}'
              replace='100%'/>
           <replaceregexp
              file='${html.file}'
              flags='gs'
              match='\$\{height\}'
              replace='100%'/>
         <replaceregexp
              file='${html.file}'
              flags='gs'
              match='\$\{title\}'
              replace='${APP_TITLE}'
              encoding='utf-8'/>
         <replaceregexp
              file='${html.file}'
              flags='gs'
              match='\$\{version_major\}'
              replace='${version.major}'/>
         <replaceregexp
              file='${html.file}'
              flags='gs'
              match='\$\{version_minor\}'
              replace='${version.minor}'/>
           <replaceregexp
              file='${html.file}'
              flags='gs'
              match='\$\{version_revision\}'
              replace='${version.revision}'/>
         <replaceregexp
              file='${html.file}'
              flags='gs'
              match='\$\{application\}'
              replace='${APP_TITLE}'/>
          <replaceregexp
              file='${html.file}'
              flags='gs'
              match='\$\{bgcolor\}'
              replace='#FFFFFF'/>
         <replaceregexp
              file='${html.file}'
              flags='gs'
              match='\$\{swf\}'
              replace='${application.name}'/> 

    </target>
</project>
Advertisements

About Ruprict

I am a nerd that is a Nerd Wannabe. I have more kids than should be allowed by law, a lovely wife, and a different sense of humor than most. I work in the field of GIS, where I am still trying to find myself on the map. View all posts by Ruprict

3 responses to “Continuous Integration with Flex, Hudson, and ArcGIS Server, Part 2

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: