Mind the Flex

Setting up a Java and Flex Project in Maven 2 for Beginners

March 31st, 2008 | Posted by Martin
Filed under Flex, Java, Maven |

Maven is a tool that provides an uniform and easy build process for your projects. In real life this means generally that you describe your project in one xml file and Maven reads this information to compile and package your project. The pros of this approach are that the project can be set up quickly in new environment, you can quite transparently add new features, and you have all the time clear overview of libraries that are used in your project.

Why this entry was written: to give an hands on overview of how to develop a Flex and Java in one project with Maven 2
Who should read it: Java developers who have no experience with Maven and Flex

We'll start using a multiple module project in this example (a tutorial how to set up Maven can be found here). This means that you'll split the application to different logical units and the project would consist of one Java, one Flex, and one parent project. The project means in current context simply a directory, which contains a file named pom.xml and other project specific stuff like source code, properties etc. The pom.xml stands for Project Object Module and describes usually the contents of the project like where the source code is located, what kind of module it is and so on. This file is freely editable and you can open it with any text editor to change the values in it. When you open a pom.xml file then in case of a minimum pom you can see there following code:

<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                      http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>multiModuleProjectId </groupId>
  <artifactId>multiModuleProjectArtifactId </artifactId>
  <version>1.0</version>
</project>

The modelVersion tag contains the version number of the pom, which is currently 4.0.0 and is used by Maven itself to ensure compatibility with different pom versions. The groupId, artifactId and version are explained later as we start to create a project by ourselves. The projects are generally independent units and a modification in one should not affect usually other projects. This allows to share the development between different persons and it is useful also if you decide to replace one module with some other like trying out JavaFx or SilverLight with your Java module.

In the end of this tutorial the structure of the directory of the project will look similar to the following picture:

We'll start creating the projects using archetypes. Archetype is a term for a template, which allows to create Maven projects (directory structure with initial contents) automatically. The archetype can be written by yourself but the most common ones are already predefined and can be used easily without digging too deep into the Maven world in the beginning.

Creating a Parent Project
Create a directory to your disk where you want to put the project stuff we'll start creating now. Open command prompt, go to this directory and execute the command below. This command will create the parent project to the directory you are in at the moment. Don't be scared of all the stuff that is downloaded after the execution in the first time and later on as it is normal behavior. (In case the mvn tries to unsuccessfully contact the remote server, you should check the settings.xml file in the directory you installed Maven to. It could be the case that you are behind a proxy and therefore you would have to uncomment the proxy entry and update the proxy settings in this file).

mvn archetype:create -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-quickstart -DgroupId=multiModuleProjectId -DartifactId=multiModuleProjectArtifactId -DpackageName=com.mypackage -Dversion=1.0

As you can see the command line has multiple parameters and let's take a closer look to them now. The first two (archetypeGroupId and archetypeArtifactId) mean that you want to use Maven's own archetype and to be more specific "maven-archetype-quickstart". The list of available archetypes can be found here and by just replacing this value in the command you can create skeletons for different type of projects.

The following parameters are your project specific and are meant to be changed by you:

-DartifactId=multiModuleProjectArtifactId
-DgroupId=multiModuleProjectId
-DpackageName=com.mypackage
-Dversion=1.0

On directory level they would look as following:

As you can see the artifactId determines the name of your project and this name is used later as the title of the project when you package it. In the future you would access your module from the following Maven repository path multiModuleProjectId\multiModuleProjectArtifactId\1.0 which would contain a file multiModuleProjectArtifactId-1.0.jar. The 1.0 in the filename is taken from the parameter version and marks the version of your project.

Creating a Java Web Application
Next we'll create a web application as in the end we want to package the Flex and web application together to deploy it to the server. For this purpose we will have to change the archetypeArtifactId to maven-archetype-webapp. We would also have to change the archetypeArtifactId as otherwise it would conflict with the project id we created previously. The groupId can stay the same as these two projects belong to one logical entity. After executing the following command:

mvn archetype:create -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-webapp -DgroupId=multiModuleProjectId -DartifactId=multiModuleProjectArtifactIdWeb -DpackageName=com.test -Dversion=1.0

we should see in our project folder a new folder, which contains following contents that describe the web application:

Creating a Flex Module
Flex project structure is quite similar to the parent project we created earlier but as there is an existing archetype available, we will use this one. Let's execute the command with a new archetype id but as this is not an "official" archetype we will have to change the archetypeGroupId also. Let's execute the following command:

mvn archetype:create -DarchetypeArtifactId=maven-archetype-flex -DarchetypeVersion=1.0 -DarchetypeGroupId=dk.jacobve.maven.archetypes  -DgroupId=multiModuleProjectId -DartifactId=multiModuleProjectArtifactIdFlex -DpackageName=

This will create a new folder with name multiModuleProjectArtifactFlex and the skeleton of the multimodule project is ready now.

Configuring the Parent project (pom.xml)
If everything went well then your project tree should look following:

As the next step we will have to modify the pom.xml in the multiproject since at the moment this project has no idea of being a parent to the Java and Flex project. Open the pom.xml and

  1. change
    <packaging>jar</packaging>

    to

    <packaging>pom</packaging>
  2. add after
    dependencies

    tag following code

    <modules>
      <module>../multiModuleProjectArtifactIdFlex</module>
      <module>../multiModuleProjectArtifactIdWeb</module>
    </modules>

    This means that this project has two modules (multiModuleProjectArtifactIdFlex and multiModuleProjectArtifactIdWeb), which are located in the same directory.

Configuring the Flex project (pom.xml)
As we used the predefined archetype, which did the most of the job for us, we only have to take care that the property flex.home in Flex projects pom.xml refers to the correct path like C:\Program Files\Adobe\Flex Builder 3 Plug-in\sdks\3.0.0. In the pom.xml you can see also definition of the Maven Flex plugin. The plugin by itself includes some kind of functionality that can be applied to your project. In our case this plugin is meant to take the flex sourcecode and compile it.

<plugin>
 <groupId>net.israfil.mojo</groupId>
 <artifactId>maven-flex2-plugin</artifactId>
 <extensions>true</extensions>
 <configuration>
   <flexhome>${flex.home}</flexhome>
   <usenetwork>true</usenetwork>
   <main>Main.mxml</main>
 </configuration>
</plugin>

As you can see, the definition of plugin is quite self-explanatory. The tag extensions, which is set to true means that you don't have to worry when the plugin is executed as it has own lifecycle.  In addition to that the configuration tag includes the parameters, which are needed by the plugin to get a picture of what and where it has to do something.

Configuring the Webapp project (pom.xml)
In configuring the web application you'll have to also add the dependencies. The dependencies tag is used to describe the resources that are needed for building the project. In the pom.xml in the web application project we need to refer to our flex project as it has to go to our web application war file we want to deploy later on. This is done using the depenencies tag that can include multiple dependency tags, which in our case would look as following:

 <dependencies>
  <dependency>
    <groupId>multiModuleProjectId</groupId>
    <artifactId>multiModuleProjectArtifactIdFlex</artifactId>
    <version>1.0-SNAPSHOT</version>
    <type>swf</type>
  </dependency>
</dependencies>

As the last step in configuring the Maven we need to define two plugins, which would take the compiled flex project and copy it to the web application project so it could be put to the war file and in addition to that we need a plugin, which would create index.html for displaying compiled swf. For compiling the Flex application we would use again the plugin maven-flex2-plugin we used earlier to compile the flex source. As you can see below, we have added the executions tag because we don't want to execute the default goal of the plugin but the copy-flex-applications goal, which would take the already compiled swf module from defined path and would put it to the path where the Maven war plugin could access it and put into the war file. To add plugins to the pom, you should add plugins tag after the finalName tag and put the following plugins between these tags.

<plugin>
  <groupId>net.israfil.mojo</groupId>
   <artifactId>maven-flex2-plugin</artifactId>
   <executions>
     <execution>
       <phase>compile</phase>
       <id>copy-flex</id>
       <goals>
         <goal>copy-flex-applications</goal>
       </goals>
       <configuration>
         <modules>
          <swfModule>
            <groupId>multiModuleProjectId</groupId>
            <artifactId>multiModuleProjectArtifactIdFlex</artifactId>
            <targetPath>target/multiModuleProjectArtifactIdWeb/</targetPath>
          </swfModule>
         </modules>
        </configuration>
      </execution>
   </executions>
</plugin>

In addition to this plugin we have to create a html wrapper for the swf file we just copied to the webapp. Since there is no suitable plugin for this purpose we have to use a workaround. As Adobe has created an Ant task for generating such wrappers and Maven has an Ant plugin, we will put these two together.

<plugin>
  <artifactId>maven-antrun-plugin</artifactId>
  <executions>
    <execution>
        <phase>compile</phase>
        <configuration>
            <tasks>
               <taskdef
                   className="flex.ant.HtmlWrapperTask" name="html-wrapper"
                   classpath="${flex.home}\ant\lib\flexTasks.jar" />
               <property name="FLEX_HOME" value="${flex.home}" />
               <property name="APP_ROOT" value="target/multiModuleProjectArtifactIdWeb" />
               <html-wrapper
                      title="Welcome to My Flex App"
                      file="index.html"
                      height="300"
                      width="400"
                      bgcolor="red"
                      application="app"
                      swf="multiModuleProjectArtifactIdFlex-1.0-SNAPSHOT"
                      version-major="9"
                      version-minor="0"
                      version-revision="0"
                      history="true"
                      template="express-installation"
                      output="${APP_ROOT}" />
           </tasks>
         </configuration>
         <goals>
           <goal>run</goal>
         </goals>
      </execution>
   </executions>
</plugin>

You should also add a property tag with correct flex home to this pom.xml. You could copy it from the pom.xml from flex module or copy-paste it from here after the url tag

<properties><flex.home>C:\Program Files\Adobe\Flex Builder 3 Plug-in\sdks\3.0.0</flex.home></properties>

This plugin will take care of the wrapper generation and copy it to the correct target directory from where the war plugin will pick it up and put into the war file.

Building and deploying the application
Now you should go on the command prompt to the folder where the pom.xml of parent project is located. In this folder you should execute the command mvn clean install. The result of plugin executions is put to the project subfolder named target, which is created by Maven during the command execution. To clean up previous results of execution you should add clean goal to the mvn command as was done previously. After executing this command you should find a file named multiModuleProjectArtifactIdWeb.war in your web application project target directory. This file can be deployed directly to the Tomcat webapps directory and you should be able to access the application on the following url http://localhost:8080/multiModuleProjectArtifactIdWeb/

18 Responses to “Setting up a Java and Flex Project in Maven 2 for Beginners”

  1. Java classes to Actionscript3 classes using Maven 2 | Mind the Flex Says:

    […] (an example how I use it can be seen below). As I’m developing a multimodule project (you can read here how to set it up) I had […]

  2. junico Says:

    hello Martin,
    how could i set up a project with maven using Flex 3 Modules?

    I can’t find a way on how to split the SWFs…
    thank you

  3. Jim Jones Says:

    Oh man.. when I run the final command I get…

    [ERROR] BUILD ERROR
    [INFO] ————————————————————————
    [INFO] Cannot execute mojo: clean. It requires a project with an existing pom.xml, but the build is not using one.

    :( I even copied the 3 pom.xml files right from the site here and I get the same thing. What am I missing?

  4. Susan Says:

    Cool! Jim, you need to be in the parent project directory (where the first POM you generated lives) in order for it to work.

    Is there a next article in the series? This is great stuff!!!!!

  5. Ravi Says:

    These examples are good, but not clear instructions given to create the directory structure initially

  6. Ravi Says:

    I take back my previous statement. I did not realize the maven arche type code embedded in the inner grids.

  7. Chris Says:

    Very cool demo, exactly what I was looking for. As a next step to the tutorial perhaps you merge the output into an IDE such as Eclipse.

  8. Jeff Says:

    This is great. How does this work with LCDS jars and config files that are potentially used in the application (i.e., remoting-config.xml)? Thanks

  9. maxconfus Says:

    thanks, great tut! i’m a maven user but have not done the flex so it was good to read.

  10. Vince Says:

    Excellent web site I will be visiting often

  11. Ajay Says:

    Great article, is there any way maven compile the mxml to swf using remoting argument of compiler (without using ant task def)

  12. Don Says:

    well done, it took a couple of attempts, but the best Flex/Maven tut I’ve found.

  13. Uma Shankar Says:

    Hi,

    While executing the first command string, I received this error code. Can you please let me know where did i failed.

    Thanks

    H:\test-maven> mvn -e archetype:create -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-quickstart -DgroupId=multiModuleProjectId -DartifactId=multiModuleProjectArtifactId -DpackageName=com.mypackage -Dversion=1.0
    + Error stacktraces are turned on.
    [INFO] Scanning for projects…
    [INFO] Searching repository for plugin with prefix: ‘archetype’.
    [INFO] ————————————————————————
    [ERROR] BUILD FAILURE
    [INFO] ————————————————————————
    [INFO] Invalid task ‘.apache.maven.archetypes’: you must specify a valid lifecycle phase, or a goal in the format plugin:goal or pluginGroupId:pluginArtifactId:pluginVersion:goal
    [INFO] ————————————————————————
    [INFO] Trace
    org.apache.maven.BuildFailureException: Invalid task ‘.apache.maven.archetypes’: you must specify a valid lifecycle phase, or a goal in the format plugin:goal or pluginGroupId:pluginArtifactId:pluginVersion:goal
    at org.apache.maven.lifecycle.DefaultLifecycleExecutor.getMojoDescriptor(DefaultLifecycleExecutor.java:1830)
    at org.apache.maven.lifecycle.DefaultLifecycleExecutor.segmentTaskListByAggregationNeeds(DefaultLifecycleExecutor.java:462)
    at org.apache.maven.lifecycle.DefaultLifecycleExecutor.execute(DefaultLifecycleExecutor.java:175)
    at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:328)
    at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:138)
    at org.apache.maven.cli.MavenCli.main(MavenCli.java:362)
    at org.apache.maven.cli.compat.CompatibleMain.main(CompatibleMain.java:60)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.codehaus.classworlds.Launcher.launchEnhanced(Launcher.java:315)
    at org.codehaus.classworlds.Launcher.launch(Launcher.java:255)
    at org.codehaus.classworlds.Launcher.mainWithExitCode(Launcher.java:430)
    at org.codehaus.classworlds.Launcher.main(Launcher.java:375)
    [INFO] ————————————————————————
    [INFO] Total time: < 1 second
    [INFO] Finished at: Tue Sep 08 18:30:14 IST 2009
    [INFO] Final Memory: 2M/4M
    [INFO] ————————————————————————

  14. Gunjan Says:

    Excellent for beginner maven+java+flex project.

  15. Ankur Says:

    Great article man. this saves my lot of time :) :)

  16. Ankur Says:

    Just wanted to know how We can add swc dependencies.

  17. Nick Maiorana Says:

    Nice plug-in! How do I tell it to use 3rd party swc files? We have these in a directory called libs.

  18. Pieter Says:

    Hey Martin,

    Awesome post. Simply perfect.

    I have one small question, as I don’t really understand it…
    In the second to last paragraph (Configuring the Webapp project) you are actually modifying the POM for the .Web part of this combined application and not the ‘parent’ part of this application?

    Could you elaborate why you are modifying the POM for the web-app and not the parent app?
    Is it because the entire app is to be deployed as a web-app ?

Leave a Reply