graniteds.orgCommunity Documentation

Chapter 1. Getting Started

1.1. Requirements (Free Tools)
1.2. Hello World, POJO
1.3. Hello World, revisited with EJB3

This section introduces:

You need at least the following four free development tools:

  • Java 6+ (5+ supported): Download Sun JDK and install it.

  • Eclipse 3.2+: Download Eclipse 3.2+ and unzip it somewhere (NOTE: It is always a good idea to avoid paths with whitespace). You may, of course, use another IDE, but you will not be able to use Eclipse specific plugins and example projects.

  • Flex 4.1 SDK (3+ supported): Download Flex 4.1 SDK and unzip it somewhere (NOTE: idem), say /flex_sdk_4.

You may also read and follow the recommendations in this excellent article in order to customize your development environment.

This section will guide you through the setting up of a very basic GraniteDS project deployed in Tomcat. Expected result is a typical "Hello, world" application as shown below:

When you type a name in the text field and click Say Hello, a request is sent to a POJO service that replies with a string made by this concatenation:



"Hello " + <typed name> + "!"
        

The result is then displayed in white under the "Hello World Sample" panel.

You may download this example project here if you don't want to copy-paste the code in the following sections below.

In order to create, build, and deploy this sample application you need these free tools:

  • Java 5+ (6+ working): Download Sun JDK and install it.

  • Eclipse 3.5+: Download Eclipse and unzip it somewhere.

  • Flex 4.6 SDK: Download Flex 4.6 SDK and unzip it somewhere. For example, /flex_4_6_sdk (for Windows users: C:\flex_4_6_sdk).

  • Tomcat 7+: Download Tomcat and unzip it somewhere. For example, /apache-tomcat-7.0.29 (for Windows users: C:\apache-tomcat-7.0.29).

  • granite.jar: You may take it from any of the GraniteDS sample applications or from GraniteDS source distribution in the build folder. Download it here.

Creation of the project in Eclipse:

Start Eclipse and create a new Java project named helloworld. You may just type in helloworld for Project name and accept all other default settings.

Because we are going to have two types of sources, Java and Flex MXML, it is better to rename the default Java source folder src to java. You can do this by right-clicking on the src source folder and selecting Refactor / Rename.

We are now going to create a new POJO service named HelloWorldService. Right-click on the java source folder and select New / Class, enter org.test for Package and HelloWorldService for Name in the following dialog, and then click on the Finish button. In the Java source file editor, modify the code so it is just as follows:



package org.test;
public class HelloWorldService {
    public String sayHello(String name) {
        return "Hello " + name + "!";
    }
}
        

You should now see something like the following picture under Eclipse:

Now let create the Flex client code. Create a new folder named flex by right-clicking on the helloworld project and selecting New / Folder. Create a new file directly in this new folder and name it HelloWorld.mxml by right-clicking on the flex folder and selecting New / File. In the file editor, which may be Flah Builder or a simple text editor depending on your Eclipse installation, type in the following code:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application
    xmlns:mx="http://www.adobe.com/2006/mxml"
    backgroundGradientColors="[#0e2e7d, #6479ab]"
    layout="vertical"
    verticalAlign="middle">

    <mx:Style>
        .Panel {
            padding-left: 8px; padding-top: 8px;
            padding-right: 8px; padding-bottom: 8px;
        }
        .Result { font-size: 26px; color: white; }
    </mx:Style>

    <mx:RemoteObject id="srv" destination="helloWorldService" />

    <mx:Panel styleName="Panel" title="Hello World Sample">
        <mx:Label text="Enter your name:"/>
        <mx:TextInput id="nameInput" />
        <mx:Button label="Say Hello" click="srv.sayHello(nameInput.text)"/>
    </mx:Panel>
        
    <mx:Label styleName="Result" text="{srv.sayHello.lastResult}"/>

</mx:Application>
        

You should now see something like the following picture under Eclipse:

Now we have to create the two main GraniteDS configuration files services-config.xml and web.xml at the root of the project. You should now see:

Copy and paste the following code into these files:



<?xml version="1.0" encoding="UTF-8"?>
<services-config>

    <services>
        <service
            id="granite-service"
            class="flex.messaging.services.RemotingService"
            messageTypes="flex.messaging.messages.RemotingMessage">
            <destination id="helloWorldService">
                <channels>
                    <channel ref="my-graniteamf"/>
                </channels>
                <properties>
                    <scope>application</scope>
                    <source>org.test.HelloWorldService</source>
                </properties>
            </destination>
        </service>
    </services>

    <channels>
        <channel-definition id="my-graniteamf" class="mx.messaging.channels.AMFChannel">
            <endpoint
                uri="http://{server.name}:{server.port}/{context.root}/graniteamf/amf"
                class="flex.messaging.endpoints.AMFEndpoint"/>
        </channel-definition>
    </channels>
</services-config>
        


<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
                        http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

    <!-- general information about this web application -->
    <display-name>Hello World</display-name>
    <description>Hello World Sample Application</description>

    <!-- read services-config.xml file at web application startup -->
    <listener>
        <listener-class>org.granite.config.GraniteConfigListener</listener-class>
    </listener>

    <!-- handle AMF requests ([de]serialization) -->
    <filter>
        <filter-name>AMFMessageFilter</filter-name>
        <filter-class>org.granite.messaging.webapp.AMFMessageFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>AMFMessageFilter</filter-name>
        <url-pattern>/graniteamf/*</url-pattern>
    </filter-mapping>

    <!-- handle AMF requests (execution) -->
    <servlet>
        <servlet-name>AMFMessageServlet</servlet-name>
        <servlet-class>org.granite.messaging.webapp.AMFMessageServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>AMFMessageServlet</servlet-name>
        <url-pattern>/graniteamf/*</url-pattern>
    </servlet-mapping>

    <!-- default content for helloworld application -->
    <welcome-file-list>
        <welcome-file>HelloWorld.swf</welcome-file>
    </welcome-file-list>

</web-app>
        

Put together, those four files (HelloWorldService.java, HelloWorld.mxml, services-config.xml, and web.xml), define an entire Flex/GraniteDS application. Here are some highlights (partial/pseudo code):



public String HelloWorldService.sayHello(String name)
        


<mx:RemoteObject id="srv" destination="helloWorldService" />
<mx:Button label="Say Hello" click="srv.sayHello(nameInput.text)"/>
<mx:Label ... text="{srv.sayHello.lastResult}"/>
        


<destination id="helloWorldService">
    <channel ref="my-graniteamf"/>
    <scope>application</scope>
    <source>org.test.HelloWorldService</source>
</destination>
<channel-definition id="my-graniteamf" ...>
    <endpoint uri="http://{server.name}:{server.port}/{context.root}/graniteamf/amf" .../>
</channel-definition>
<url-pattern>/graniteamf/*</url-pattern>
        

From top to bottom:

  • The HelloWorldService Java class declares a method sayHello() that takes a String argument and returns another String.

  • The HelloWorld.mxml Flex application declares a RemoteObject named srv and maps it to a destination named helloWorldService.

  • When you click on the Say Hello button, the RemoteObject triggers a server request that will call a sayHello() method with the text typed in the TextInput named nameInput as argument: srv.sayHello(nameInput.text).

  • The result of this call will be displayed, when available, in a Label by binding the text of this component to the property srv.sayHello.lastResult that contains the last received value for this method call.

  • The helloWorldService destination is declared in services-config.xml and uses a channel named my-graniteamf. The Java class (source) used as a service for this destination call is org.test.HelloWorldService and its scope is application. The Java class will be created when the service is first accessed, and this same and unique instance will be used for all subsequent calls; other possible values are request and session.

  • The channel named my-graniteamf, used by the helloWorldService destination, declares an endpoint whose URL will be resolved to http://localhost:8080/helloworld/graniteamf/amf for a local call; it could also be resolved, for example, to http://www.helloworld.com:80/helloworld/graniteamf/amf for remote calls.

  • AMFMessageFilter and AMFMessageServlet are both mapped in web.xml to the same URL-pattern /graniteamf/*. Inside the helloworld web application, all requests that match this pattern will be go through this filter and this servlet such as http://localhost:8080/helloworld/graniteamf/amf.

Here is basic flow chart that summarizes the expected communication between the Flex client application and the Java server:

The last thing to do is to build and deploy the application.

First we have to add the granite.jar library and create a build file, here using Ant.

Create a new folder named lib at the root of the project and put granite.jar into this new folder. Create a new file named build.xml at the root of the project. Copy and paste the following content into it; you may have to modify the properties FLEX_HOME and TOMCAT_HOME to reflect your environment:



<?xml version="1.0" encoding="UTF-8"?>
<project name="hello-world" default="deploy">

    <!-- Modify FLEX_HOME/TOMCAT_HOME properties to reflect your environment -->
    <property name="FLEX_HOME" value="/flex_sdk_3"/>
    <property name="TOMCAT_HOME" value="/apache-tomcat-6.0.18"/>
    
    <!-- Declare Flex Ant tasks (such as mxmlc used below) -->
    <taskdef resource="flexTasks.tasks" classpath="${FLEX_HOME}/ant/lib/flexTasks.jar" />

    <!-- Compile MXML source code to SWF -->
    <target name="mxmlc">
        <mxmlc
            file="flex/HelloWorld.mxml"
            output="build/HelloWorld.swf"
            services="services-config.xml"
            context-root="helloworld">
        </mxmlc>
    </target>

    <!-- Build a war suitable for Tomcat (and other) -->
    <target name="war" depends="mxmlc">
        <mkdir dir="build"/>
        <war destfile="build/helloworld.war" webxml="web.xml">
            <zipfileset file="services-config.xml" prefix="WEB-INF/flex" />
            <fileset dir="build" includes="*.swf"/>
            <lib dir="lib"/>
            <classes dir="bin"/>
        </war>
    </target>

    <!-- Deploy the war in Tomcat -->
    <target name="deploy" depends="war">
        <copy todir="${TOMCAT_HOME}/webapps" file="build/helloworld.war"/>
    </target>

</project>
        

You should see something like the following picture:

You may now right-click on the build.xml file and select Run As / Ant Build. This will launch the build process, compile the MXML code to an SWF, create a WAR (Web Archive), and copy it into your Tomcat webapps directory.

Finally start Tomcat and test the application. To start Tomcat, go to the directory bin just under your Tomcat installation directory, /apache-tomcat-6.0.18/bin for example, and double-click on startup.bat, or startup.sh for Unix/Mac users. After a short while, you should see in the console that Tomcat has started. You may now point your Web browser to http://localhost:8080/helloworld/.

The Flex example application should appear and you may start playing with "Hello, world" ... a fascinating game.

This tutorial shows an evolution of the basic "Hello, world" example application with some Hibernate persistence operations (JPA). When finished and deployed it should look like this picture:

In this picture, you see a small data grid that displays the history of all previous say hello operations. This history is persisted in the database by means of a JPA entity bean and those objects are serialized back to the Flex client each time you enter a new name.

This example also shows basic usage of the Granite Eclipse Builder and externalization configuration.

If you don't want to follow this tutorial step by step you may download it as a zip archive here.

In order to create, build, and deploy this sample application you need these free tools:

  • Java 5+ (6+ working): Download Sun JDK and install it.

  • Eclipse 3.3+: Download Eclipse and unzip it somewhere.

  • Flex 3 SDK: Download Flex 3 SDK and unzip it somewhere. For example, /flex_3_sdk (for Windows users: C:\flex_3_sdk).

  • JBoss 4.2.3.GA: Download JBoss and unzip it somewhere. For example, /jboss-4.2.3.GA (for Windows users: C:\jboss-4.2.3.GA).

  • granite.jar, granite-hibernate.jar and granite-essentials.swc: You may take it from any of the GraniteDS example applications or from GraniteDS source distribution in the build folder. Download it here.

  • GraniteDS Eclipse Builder: You may download it here (follow these installation instructions here).

Creation of the project in Eclipse:

Start Eclipse and create a new Java project named helloworld2. You may just type in helloworld2 for Project name and accept all other default settings. Because we are going to have two types of sources, Java and Flex MXML, it is better to rename the default Java source folder src to java. You can do this by right-clicking on the src source folder and selecting Refactor / Rename.

Create a new directory named lib at the root of this project and put granite.jar, granite-hibernate.jar and granite-essentials.swc into it. Also add these two JBoss jars: ejb3-persistence.jar and jboss-ejb3x.jar, which you will find in the /jboss-4.2.3.GA/server/default/lib directory. Right-click on those JBoss jars and select Build Path / Add to Build Path.

You should now see something like the following picture under Eclipse:

Right-click on the java source folder, select New / Class and fill the New Java Class dialog as follows:

Copy and paste the following code in the Java editor:



package org.test;
import java.io.Serializable;
import javax.persistence.Basic;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Entity
public class Welcome implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id @GeneratedValue
    private Integer id;
    @Basic
    private String name;
    public Welcome() {
    }
    public Welcome(String name) {
        this.name = name;
    }
    
    public Integer getId() {
        return id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
        

This basic JPA entity bean declares a read-only id field, auto incremented primary key in the database, and a name field, the name of the person that was entered in the Flex application when saying hello.

We are now going to create an EJB 3 session bean that will handle the say hello and persistence operations.

Create a new Java interface named HelloWorldService by right-clicking on the org.test package and choosing New / Interface. Then copy and paste the following code:



package org.test;
import java.util.List;
public interface HelloWorldService {
    public String sayHello(String name);
    public List<Welcome> findWelcomeHistory();
}
        

Create a new Java class named HelloWorldServiceBean that implements the HelloWorldService interface by right-clicking on the org.test package and choosing New / Class. Then copy and paste the following code:



package org.test;
import java.util.List;
import javax.ejb.Local;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
@Stateless
@Local(HelloWorldService.class)
public class HelloWorldServiceBean implements HelloWorldService {
    @PersistenceContext
    protected EntityManager manager;
    @Override
    public String sayHello(String name) {
        manager.persist(new Welcome(name));
        return "Hello " + name + "!";
    }
    @SuppressWarnings("unchecked")
    @Override
    public List<Welcome> findWelcomeHistory() {
        Query query = manager.createQuery("from " + Welcome.class.getName());
        return query.getResultList();
    }
}
        

We now have a complete EJB 3 stateless session bean that will persist each name passed to the sayHello() method and return the list of all previous welcome operations with the findWelcomeHistory() method.

Your Java project should look like that after this step:

Now let create the Flex client code. Create a new folder named flex by right-clicking on the helloworld2 project and selecting New / Folder. Create a new file directly in this new folder and name it HelloWorld.mxml by right-clicking on the flex folder and selecting New / File. In the file editor, which may be Flah Builder or a simple text editor depending on your Eclipse installation, type in the following code:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application
    xmlns:mx="http://www.adobe.com/2006/mxml"
    backgroundGradientColors="[#0e2e7d, #6479ab]"
    layout="vertical"
    verticalAlign="middle"
    creationComplete="srv.findWelcomeHistory()">

    <mx:Style>
        .Panel {
            padding-left: 8px; padding-top: 8px;
            padding-right: 8px; padding-bottom: 8px;
        }
        .Result { font-size: 26px; color: white; }
    </mx:Style>

    <mx:RemoteObject id="srv" destination="helloWorldService" />

    <mx:Panel styleName="Panel" title="Hello World Sample">
        <mx:Label text="Enter your name:"/>
        <mx:TextInput id="nameInput" width="200" />
        <mx:Button label="Say Hello"
           click="srv.sayHello(nameInput.text);srv.findWelcomeHistory()"/>
        
        <mx:Label text="History:"/>
        <mx:DataGrid dataProvider="{srv.findWelcomeHistory.lastResult}"
          width="200" height="200"/>
    </mx:Panel>
        
    <mx:Label styleName="Result" text="{srv.sayHello.lastResult}"/>
    
</mx:Application>
        

Some explanations:

  • This Flex application uses a RemoteObject named srv that will be bound to the stateless session bean we have created earlier. The actual binding between the destination named helloWorldService and the Java service is specified in the services-config.xml that we will create later.

  • When the Flex application is completely created, see the creationComplete event handler, it first calls the findWelcomeHistory() method of the Java service. The result of this call is displayed in the DataGrid, see the dataProvider="{srv.findWelcomeHistory.lastResult}" attribute.

  • When you click on the Say Hello button after entering a name in the TextInput field, it calls the sayHello() method on the server with the supplied name and then the findWelcomeHistory() method whose result is used to update the DataGrid content. See the click="srv.sayHello(nameInput.text);srv.findWelcomeHistory()" attribute.

  • The returned String of the sayHello() method, "Hello " + name + "!" in the Java service, is displayed in a Label just below the Panel. See the text="{srv.sayHello.lastResult}" attribute.

We are now going to configure the Granite Eclipse Builder that will generate the Welcome entity bean ActionScript3 equivalent. First download the builder and install it; just drop the jar in your Eclipse plugin directory and restart. In your package explorer, right-click on the helloworld2 project and select Add GraniteDS Nature:

In the configuration wizard, click on the Add Folder button and select the java source folder:

Select the Excluded subnode and click on the Edit button. In the following dialog, change the Output Directory to flex, instead of the default as3, and add the **/*Service*.java exclusion pattern, as we don't want code generation for services, just for entities:

After those short configuration steps, you may accept all other default options and click directly on the Finish button in the wizard. The generation process starts and produces two files as shown in the following picture:

There is no need to modify those files for our short example but, if you want to add specific methods to your ActionScript 3 bean, you must put it in the Welcome.as class and not in the WelcomeBase.as class that may be overwritten by subsequent generation processes. If you look at the WelcomeBase.as class, you will see that the generated code reproduces the Welcome.java fields and accesses (read-only id and read-write name). It also implements the code required for externalization mechanisms with lazy loading support. See Externalizers documentation for details.

The rest is only a matter of configuration files. First, create a new file named granite-config.xml at the root of the helloworld2 project directory with this content:



<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE granite-config PUBLIC "-//Granite Data Services//DTD granite-config internal//EN"
    "http://www.graniteds.org/public/dtd/3.0.0/granite-config.dtd">

<granite-config>

    <class-getter type="org.granite.hibernate.HibernateClassGetter"/>

    <externalizers>
        <externalizer type="org.granite.hibernate.HibernateExternalizer">
            <include annotated-with="javax.persistence.Entity"/>
        </externalizer>
    </externalizers>

</granite-config>
        

This configuration instructs GDS to externalize all Java classes annotated with the @Entity annotation (such as our Welcome.java entity bean).

Next we need a Flex services-config.xml as follows. Create it in at root of the project, as for granite-config.xml:



<?xml version="1.0" encoding="UTF-8"?>

<services-config>

    <services>
        <service
            id="granite-service"
            class="flex.messaging.services.RemotingService"
            messageTypes="flex.messaging.messages.RemotingMessage">
            <destination id="helloWorldService">
                <channels>
                    <channel ref="my-graniteamf"/>
                </channels>
                <properties>
                    <factory>ejbFactory</factory>
                </properties>
            </destination>
        </service>
    </services>
    
    <factories>
        <factory id="ejbFactory" class="org.granite.messaging.service.EjbServiceFactory">
            <properties>
                <lookup>helloworld/{capitalized.destination.id}Bean/local</lookup>
            </properties>
        </factory>
    </factories>

    <channels>
        <channel-definition id="my-graniteamf" class="mx.messaging.channels.AMFChannel">
            <endpoint
                uri="http://{server.name}:{server.port}/{context.root}/graniteamf/amf"
                class="flex.messaging.endpoints.AMFEndpoint"/>
        </channel-definition>
    </channels>

</services-config>
        

This is where the destination id HelloWorldService is bound to our stateless EJB 3 session bean service. When the RemoteObject in HelloWorld.mxml is called, the destination id is used in the EjbServiceFactory to lookup the EJB; helloworld/{capitalized.destination.id}Bean/local is resolved to helloworld/HelloWorldServiceBean/local, that is the JNDI name used in JBoss to access the EJB.

We then need three additional configuration files: application.xml, persistence.xml and web.xml. All are standard J2EE configuration files and you will find detailed documentation on them on the Internet. Here is their contents. Again, create them at the root of the project:



<?xml version="1.0" encoding="UTF-8"?>

<application>
    <display-name>GraniteDS HelloWorld</display-name>
    <module>
        <web>
            <web-uri>helloworld.war</web-uri>
            <context-root>/helloworld</context-root>
        </web>
    </module>
    <module>
        <ejb>helloworld.jar</ejb>
    </module>
</application>
        


<?xml version="1.0" encoding="UTF-8"?>

<persistence>
    <persistence-unit name="ejb3">
        <jta-data-source>java:/DefaultDS</jta-data-source>
        <properties>
            <property name="hibernate.hbm2ddl.auto" value="update"/>
        </properties>
    </persistence-unit>
</persistence>
        


<?xml version="1.0" encoding="UTF-8"?>

<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
                        http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

    <!-- general information about this web application -->
    <display-name>Hello World</display-name>
    <description>Hello World Sample Application</description>

    <!-- read services-config.xml file at web application startup -->
    <listener>
        <listener-class>org.granite.config.GraniteConfigListener</listener-class>
    </listener>

    <!-- handle AMF requests ([de]serialization) -->
    <filter>
        <filter-name>AMFMessageFilter</filter-name>
        <filter-class>org.granite.messaging.webapp.AMFMessageFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>AMFMessageFilter</filter-name>
        <url-pattern>/graniteamf/*</url-pattern>
    </filter-mapping>

    <!-- handle AMF requests (execution) -->
    <servlet>
        <servlet-name>AMFMessageServlet</servlet-name>
        <servlet-class>org.granite.messaging.webapp.AMFMessageServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>AMFMessageServlet</servlet-name>
        <url-pattern>/graniteamf/*</url-pattern>
    </servlet-mapping>

    <!-- default content for helloworld application -->
    <welcome-file-list>
        <welcome-file>HelloWorld.swf</welcome-file>
    </welcome-file-list>

</web-app>
        

You should now see something like this in your package explorer:

The last thing to do is to build and deploy the application.

Create a new file named build.xml at the root of the project. Copy and paste the following content into it; you may have to modify the properties FLEX_HOME and TOMCAT_HOME to reflect your environment:



<?xml version="1.0" encoding="UTF-8"?>

<project name="hello-world" default="deploy">

    <!-- Modify FLEX_HOME/JBOSS_HOME properties to reflect your environment -->
    <property name="FLEX_HOME" value="/flex_sdk_3"/>
    <property name="JBOSS_HOME" value="/jboss-4.2.3.GA"/>
    
    <!-- Declare Flex Ant tasks (such as mxmlc used below) -->
    <taskdef resource="flexTasks.tasks" classpath="${FLEX_HOME}/ant/lib/flexTasks.jar" />

    <!-- Compile MXML source code to SWF -->
    <target name="mxmlc">
        <mxmlc
            file="flex/HelloWorld.mxml"
            output="build/HelloWorld.swf"
            services="services-config.xml"
            context-root="helloworld">
            
            <source-path path-element="flex" />

            <!-- Make sure that the Welcome.as class is compiled into
                 our HelloWorld.swf (otherwise mxmlc doesn't include it
                 because there are no explicit reference to this class
                 in HelloWorld.mxml -->
            <includes symbol="org.test.Welcome" />
            
            <!-- Make sure that all "essentials" GDS classes are included into
                 our HelloWorld.swf (otherwise mxmlc doesn't include them
                 because there is no explicit reference to these classes
                 in HelloWorld.mxml and Welcome.as -->
            <compiler.include-libraries dir="lib" append="true">
                <include name="granite-essentials.swc" />
            </compiler.include-libraries>
        </mxmlc>
    </target>

    <!-- Build an ear suitable for JBoss -->
    <target name="ear" depends="mxmlc">
        <mkdir dir="build"/>
        <jar destfile="build/helloworld.jar">
            <fileset dir="bin" includes="**/*.class"/>
            <zipfileset file="persistence.xml" prefix="META-INF" />
        </jar>
        <war destfile="build/helloworld.war" webxml="web.xml">
            <zipfileset file="services-config.xml" prefix="WEB-INF/flex" />
            <zipfileset file="granite-config.xml" prefix="WEB-INF/granite" />
            <fileset dir="build" includes="*.swf"/>
        </war>
        <ear destfile="build/helloworld.ear" appxml="application.xml">
            <fileset dir="build" includes="*.jar,*.war"/>
            <zipfileset dir="lib" includes="granite*.jar" prefix="lib" />
        </ear>
    </target>

    <!-- Deploy the ear in JBoss -->
    <target name="deploy" depends="ear">
        <copy todir="${JBOSS_HOME}/server/default/deploy" file="build/helloworld.ear"/>
    </target>

</project>
        

Basically, this Ant build compiles our Flex code in a swf and package everything in an ear suitable for JBoss deployment.

Warning

Read the comments in the above build.xml about including AS3 classes/SWC libraries into the compiled SWF! Missing this point leads to a very common Flex runtime error because of unexpected mxmlc compiler optimizations!

You may now right-click on the build.xml file and select Run As / Ant Build. This will launch the build process, compile the MXML code to an SWF, create an ear (Enterprise ARchive) and copy it into your JBoss deploy directory.

Finally start JBoss and test the application. To start JBoss, go to the directory bin just under your JBoss installation directory, /jboss-4.2.3.GA/bin for example, and double-click on run.bat, or run.sh for Unix/Mac users. After a short while, you should see in the console that JBoss has started. You may now point your Web browser to http://localhost:8080/helloworld/.