Most Flex (and AIR) developers like to build, compile and package their applications using Adobe’s Flash Builder (formerly known as Flex Builder). A few use alternative IDE(s) like FDT and IntelliJ IDEA. A smaller few bravely get everything done without an IDE.
As applications mature from sandboxes to production environments, a few developers start leveraging build tools like Apache Ant to automate and ease the process of compilation, packaging and deployment. They often use Ant with their IDE, typically Flash Builder. A popular and supported bundle of readily available Ant tasks, called Flex Ant Tasks, are available both with the open source Flex SDK and with Flash Builder. A few developers go beyond these build scripts and begin to leverage Maven.
Before we go further on Flex and Maven, it would be important to define what Maven is. Long time Maven lovers may be completely shocked that Maven needs introduction. However, among many Flex developers Maven is a complete stranger and so it may be a good idea to get them on the same page as those who swear by this tool.
Lets start out with the official and formal definition, which is:
“Maven is a project management tool which encompasses a project object model, a set of standards, a project lifecycle, a dependency management system, and logic for executing plugin goals at defined phases in a lifecycle. When you use Maven, you describe your project using a well-defined project object model, Maven can then apply cross-cutting logic from a set of shared (or custom) plugins.”
If this sounds complicated or bubbles up ideas of a project management tool with timelines, work allocation and such then the definition has most certainly, if anything, mislead you, perhaps convincing you to run away as far as possible from Maven. Lets try and understand what Maven exactly is.
Simply put, Maven is a super build tool that can not only make it easy to compile, package and deploy applications but also helps do many other value added tasks like resolve dependencies, generate websites, invoke external scripts and keep track of application versions. While it provides these and many more excellent features, it upholds the reuse and DRY (Don’t repeat yourself) principles. It brings object orientation to build management and allows the process to be defined in a “Project Object Model” (POM). POM definition exists in an xml format within a file named pom.xml.
Maven is completely modular, where each of its features is provided by a plugin. A Maven plugin can do one or more things, which are encapsulated and available as goals. So you rely on a Maven plugin goal to carry out what in traditional terms would be called a task. Besides executing tasks, Maven is capable of mapping its plugins and plugin goals to a project lifecycle phase. By default Maven defines the following phases in a build lifecycle:
- Validate – check and verify that the project is correct and all necessary information is available
- Compile - compile the source to byte code or a binary
- Test – run defined unit tests using a unit testing framework
- Package – bundle the compiled code into a desired package format, for example put Java compiled code in a JAR or compiled Flex (MXML and AS3) code in a SWF or a SWC (if the compiled code is defined, distributed and used as a library)
- Integration-test – run integration tests
- Verify – check if package is valid
- Install - install the package in a local Maven repository so that it is can be readily accessed when required to execute relevant plugin goals or resolve dependencies
- Deploy – deploy the package to the production environment
This allows the execution of multiple and all relevant plugin goals simply by execution of a maven build lifecycle phase. Maven phases are sequential so execution of a particular phase triggers execution of all phases prior to the one specified. As an example the install lifecycle phase invocation implies execution of all relevant plugin goals for validate, compile, test, package, integration-test, verify and install phases.
Maven promotes convention over configuration. This means, sticking with Maven defaults lets you get done a lot with very little configuration. This enhances productivity, reduces errors and promotes standardization. Maven, however, does not stop you from customizing your setup, except that in such a case you would need to write a lot more configuration than usual. Maven has a lot of other niceties and a rich set of plugins. You can learn all about Maven with the help of two excellent Sonatype free online books:
Assuming you understand Maven fundamentals by now and are willing to even the learning curve by banking on the free Maven books, let’s start using it to build Flex and AIR applications.
If you don’t already have Maven, then first download and install it on the machine. Installing Maven typically involves four simple steps, which are as follows:
1) Download a release build archive appropriate for your platform
from http://maven.apache.org/download.html. You may want to get the zip file on a Windows
machine and tarred zip or bz2 file on a Linux, Unix or Mac OSX machine.
2) Expand the archive file in a preferred folder within your file system.
3) Create or update a few environment variables, namely:
- JAVA_HOME – point it to your JDK folder. I assume JDK is already installed. If not, go get it before you go further.
- M2_HOME – point it to the folder where Maven is installed. It’s the same that was created when you extracted the Maven archive.
- M2 – point it to %M2_HOME%\bin on windows and $M2_HOME/bin on Linux/Unix/Mac OSX
- PATH – update the PATH environment variable. Add M2 to it.
- MAVEN_OPTS – Add -Xms256m -Xmx512m to this environment variable.
Verify that Maven is installed and working. Open up a terminal window (command window or powershell on Windows7) and type “mvn --version” in it. If you see something as shown in Figure 1 then you are good to go.
Verifying that Maven is working by checking its version
Once Maven is installed we can begin to use it.
You know by now that almost
all of Maven’s features manifest in its plugins. That means to build a Flex and
an AIR application with Maven we need a plugin that can help us do that. In fact there is more than one plugin
that can help us with it. The one that seems most matured and is in active
development is Flexmojos and that is what I will use in this article.
To use Flexmojos, we don’t need to proactively download and install the plugin. In fact we never have to do that for any Maven plugin. Maven plugins are downloaded and installed to the local repository as needed. All we need to do is to reference it in our POM (defined in a pom.xml file). Maven plugins are typically available in and discoverable from public Maven repositories, unless of course if they are private. Private plugins are for consumption within a specific organization. Private repositories for organization wide consumption of plugins can be setup in a manner similar to public repositories. Nexus, a repository management product from Sonatype, makes hosted Maven repository creation and management very easy and effortless. A Maven plugin is downloaded when it is referenced the first time. It is then installed to a local repository so that they it be accessed locally when required again. This caching mechanism boosts performance and avoids unnecessary re-downloading of files. The local repository resides within a folder named “repository”, which lies within a folder named “.m2”. When Maven is first used the “.m2”’ folder is created within a user’s home directory. Which means you will find “.m2” in /home/<username> in Linux, /Users/<username> in Mac OSX and C:\Users\<username> in Windows7.
Maven projects are identified with the help of a unique set of attributes often referred to as the Maven coordinates. Maven coordinates consist of four different parts: groupId, artifactId, packaging and version. Each Maven project is uniquely identified by a unique combination of groupId, artifactId and version. Brief definitions of the coordinate elements are as follows:
- groupId – unique identifier for the organization that owns and manages the project. For example we use our domain name reversed as in “com.treasuryofideas” as the groupId for our Maven projects.
- artifactId – a unique identifier for the project itself.
- version – a specific release of the project.
- packaging – the archive format the project is bundled as. For Flex projects you would use SWF and for Flex library projects you would go with SWC.
Maven plugins follow a similar naming system and are identified with a groupId:artifactId:version combination. For example Flexmojos 3.7.1 can be identified as org.sonatype.flexmojos:flexmojos-maven-plugin:3.7.1.
The Flexmojos plugins are published on the central public Maven repository but to make sure you have access to the latest version and to all the dependencies of the plugin, you should explicitly add the Sonatype Flexmojos repository to your set of repositories. You could add the repository explicitly in a project POM or you could add the repository using Nexus. I will the take the simpler, though not necessarily robust, route of adding the Flexmojos repository in the project POM. You will see this in the next section.
Generating a Flex Project
Automating the task of creating
an initial shell for a Flex project can help avoid complexities and potential
errors around project setup. It helps you get started on the right foot!
Flexmojos has a set of archetypes that facilitates the creation of the following types of Flex projects:
- Flex application – a regular Flex application that gets packaged as a SWF and can be deployed to run in a Flash player.
- Flex Library – a library that gets packaged as a SWC and that is consumed by a Flex or AIR application.
- Flex multi-module project – a project that includes both library projects and a regular application and that is packages as a WAR, a web archive file.
Lets start out by generating a simple Flex application using the respective archetype. Just type the following in your terminal:
mvn archetype:generate \
...and hit the enter/return key.
As soon as you hit the enter/return key, you will see Maven in action. Maven would figure out all the dependencies and start downloading all the plugins it needs to get your task done. It will also download a few default plugins that are pertinent to the typical build lifecycle phases.
After the required plugins are downloaded and installed, you will be presented with an interactive console that will ask you to input the Maven coordinate values (groupId, artifactId and version) for your project. It will also prompt you for the package name for your source code. Look at Figure 2, to see what I was prompted for and how I responded to it. You will notice that I chose default value of 1.0-SNAPSHOT for version and com.treasuryofideas (my groupId) as the package name.
Snippet of my terminal output during Flex application generation, using the Flexmojos archetype
Now browse into your folder from where you ran the Maven archetype generation command and you should see a project called “sampleapp” created for you. Review Figure 3 to see what the project directory structure and hierarchy looks like.
sampleapp project directory structure
The generated “sampleapp” contains 3 important entities:
- pom.xml – the project object model
- source code – within the src folder
- test code – within the test folder
Open pom.xml and you will notice a page full of generated configuration. Apart from the Maven co-ordinates, source directory, test directory, packaging format and plugin specification, you will also see a couple of dependencies on the Flex SDK and on FlexUnit.
Next, browse to src/main/flex and open Main.mxml. You may recall that Maven likes convention over configuration. One such convention is to keep project source code within src/main/<language/framework>/ folder and test code within src/test/<language/framework>/ folder. For Flex and AIR the language/framework value is “flex”. In case of Java you would see the source code in src/main/java.
You should see the following source (trimmed off the comments) contained in Main.mxml:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:Text text="Hello World!"/>
If you are a Flex or AIR developer you instantly know this is Flex 3 code, which it is! You wouldn’t be able to generate the Flex 4 code using the archetype as of now. The latest version of the plugin, i.e. 4.0-alpha-3, still seems to generate Flex 3 code. Although you currently cannot generate a Flex 4 project using Flexmojos, you can build a Flex 4 project using it.
Last but not the least, you may want to browse into src/test/flex. You will see a TestApp AS3 class that extends flexunit.framework.TestCase. This class is the place where you would add your unit tests as you develop your application.
Next, I will build, test and package this application. The shortest way to do this is to run the “install” phase on the Maven project. Running “install” would run all the goals in the phases up to and including “install”. Before, I actually run “mvn install”, I will add the Flexmojos repository in the pom. Open pom.xml and add the following lines below the </profiles> closing tags:
Now run “mvn install” on the terminal and wait for some Maven magic. You should see a lot of activity on the console including downloading of a few plugins and building of the sources. The last few lines should be as shown in Figure 4.
Successful build of the generated sampleapp
Intermittently you may also notice that a Flash player is launched for test. Install runs all the unit tests and that is why this happens. We haven’t defined any unit tests so far though so its possible you may barely noticed the test related activities and tasks.
To understand what all has been added and modified as a part of the Maven install command, let’s first review the folder structure which is illustrated in Figure 5.
sampleapp folder structure after running “mvn install”
The compiled and packaged SWF file, sampleapp-1.0-SANPSHOT.swf, resides in the target directory. Open that file using the local Flash player or any browser with a Flash player plugin and you should see the running application. The application prints out the quintessential first few words: “Hello World!”. Figure 6 shows the application in a local Flash player on Mac OSX.
Now that you have generated and built a sample Flex application, lets also quickly generate and build a Flex library project.