graniteds.orgCommunity Documentation

Chapter 3. Project Setup

3.1. Server libraries
3.2. Configuring web.xml
3.3. Framework configuration
3.4. Application configuration
3.5. Client libraries and setup
3.6. Developing with Ant
3.7. Developing with Maven
3.8. Using Maven archetypes
3.9. Developing with Flash Builder

GraniteDS consists in a set of Flex libraries (swcs) and a set of Java libraries (jars). It is designed to be deployed in a Java application server and packaged in a standard Java Web application, either as a WAR file or as an EAR file. The configuration of a GraniteDS project will generally involve the following steps :

  1. Add the GraniteDS jars to the WEB-INF/lib folder of the WAR file or the lib folder of the EAR file

  2. Add the GraniteDS listener, servlets and filters in the standard WEB-INF/web.xml configuration file

  3. Define the internal configuration of GraniteDS in the WEB-INF/granite/granite-config.xml file

  4. Define the application configuration of GraniteDS (remoting destinations, messaging topics...) in the WEB-INF/flex/services-config.xml

  5. Link you Flex project with the GraniteDS swcs libraries and define the necessary Flex compiler options

Depending on which framework and application server you use on the server (Spring, Seam...) and on the client, some of these steps may be completely omitted, or implemented differently. For example, when using the Spring framework on the server, almost all the configuration can be defined in the standard Spring context instead of the granite-config.xml and services-config.xml files. GraniteDS tries to be as transparent and integrated as possible with the application environment, however it can be useful to know how things work at the lower level if you have specific requirements.

The GraniteDS jars are available from the build folder of the distribution. You will always need granite.jar. Additionally you will have to include the jar corresponding to your server framework (granite-spring.jar for Spring for example), the jar for your JPA provider (granite-hibernate.jar for Hibernate) and the granite-beanvalidation.jar if you want to benefit from the integration with the Bean Validation API on the server.

At the most basic level, GraniteDS is implemented as a servlet (in fact a servlet and a filter) and thus has to be configured in web.xml. Here is a typical code snippet that maps the GraniteDS AMF servlet to /graniteamf/*. Of course it's possible to define a different URL mapping if required. It is also highly recommended to also add the configuration listener that will release resources on application undeployment.



<listener>
    <listener-class>org.granite.config.GraniteConfigListener</listener-class>
</listener>

<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>

<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>
        

The configuration of the various GraniteDS parts is done in the file WEB-INF/granite/granite-config.xml. There are many options that can be defined here, you can refer to the configuration reference.

As a starting point, you can create an empty file :



<?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/>
        

Or much easier a configuration that will use class scanning to determine the default setup.



<?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 scan="true"/>
        

The last thing to define on the server is the application configuration in WEB-INF/flex/services-config.xml. This is for example the place where you will define which elements of your application you will expose to GraniteDS remoting, or the topic for messaging. You can refer to the configuration reference for more details.

For example a simple configuration for an EJB 3 service would look like :



<services-config>
    <services>
        <service id="granite-service"
            class="flex.messaging.services.RemotingService"
            messageTypes="flex.messaging.messages.RemotingMessage">

            <destination id="example">
                <channels>
                    <channel ref="graniteamf"/>
                </channels>
                <properties>
                    <factory>ejbFactory</factory>
                </properties>
            </destination>
        </service>
    </services>

    <factories>
        <factory id="ejbFactory" class="org.granite.messaging.service.EjbServiceFactory">
            <properties>
                <lookup>myapp/{capitalized.destination.id}ServiceBean/local</lookup>
            </properties>
        </factory>
    </factories>

    <channels>
        <channel-definition id="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 configuration file declares 3 differents things, let's list them in the reverse order :

  • Channel endpoint : this defines the uri on which the remote service can be accessed though GraniteDS remoting. This should match the servlet url mapping defined previously in web.xml.

    Note that the server-name, server-port and context-root are placeholders that are automatically replaced when running the application in the Flash Player. To run the application on the AIR runtime you will have to specify the real name and port of the server as it cannot be determined from the source url of the swf.

  • Service factories : here the configuration defines an EJB 3 factory, meaning that destinations using this factory will route incoming remote calls to EJB 3. GraniteDS provides factories for all popular server frameworks. Most factories require specific properties, here for example the JNDI format for EJB lookup.

  • Service/destinations : this section defines a remoting service (described by its class and message type) and one destination interpreted as an EJB 3 as indicated by the factory property.

Depending on the kind of framework integration that is used, the services-config.xml file may not be necessary and can be omitted. With Spring and Seam for example, everything can be defined in the respective framework configuration files instead of services-config.xml.

GraniteDS comes with two client swc libraries that must be linked with your Flex application. The main library granite.swc should be linked with the standard mode (linked into code), but the core internal library granite-essentials.swc must be linked with the compiler option -include-libraries. When using the Tide client framework, you will also have to specify to the Flex compiler some annotations that should be kept in the swf for runtime usage. The following sections describe in more details the various options for different development environments.

When using a services-config.xml file, it's necessary to use the compiler option -services path/to/services-config.xml so the Flex SDK itself can handle the creation of the channel and other remoting objects. If you don't use this option, you will have to specify manually a channel and endpoint for each destination in ActionScript 3 :

private function init():void {
        srv = new RemoteObject("myService");
        srv.source = "myService";
        srv.channelSet = new ChannelSet();
        srv.channelSet.addChannel(new AMFChannel("graniteamf", 
            "http://{server.name}:{server.port}/myapp/graniteamf/amf"));
        srv.showBusyCursor = true;
}
        

Ant is a very popular and powerful build tool. The Flex SDK comes with a set of ant tasks that can perform various development tasks, notably the compilation of the Flex application to a swf file. The following XML code defines a typical target to build a Flex/GraniteDS application (the variable FLEX_HOME should point to your Flex SDK installation directory) :



<taskdef resource="flexTasks.tasks" classpath="${FLEX_HOME}/ant/lib/flexTasks.jar"/>

<target name="compile.flex" description="Build swf from Flex sources">
    <mxmlc
        file="flex/src/${flex.application}.mxml"
        output="bin-debug/${flex.application}.swf"
        services="path/to/services-config.xml"
        context-root="/myapp"
        use-network="false"
        debug="true"
        incremental="true">

        <load-config filename="${FLEX_HOME}/frameworks/flex-config.xml"/>

        <source-path path-element="${FLEX_HOME}/frameworks"/>
        <source-path path-element="bin-debug"/>
        
        <!-- Definition of runtime annotations, not required when not using Tide -->
        <keep-as3-metadata name="Bindable"/>
        <keep-as3-metadata name="Managed"/>
        <keep-as3-metadata name="ChangeEvent"/>
        <keep-as3-metadata name="NonCommittingChangeEvent"/>
        <keep-as3-metadata name="Transient"/>
        <keep-as3-metadata name="Id"/>
        <keep-as3-metadata name="Version"/>
        <keep-as3-metadata name="Lazy"/>
        <keep-as3-metadata name="Name"/>
        <keep-as3-metadata name="In"/>
        <keep-as3-metadata name="Inject"/>
        <keep-as3-metadata name="Out"/>
        <keep-as3-metadata name="Produces"/>
        <keep-as3-metadata name="Observer"/>
        <keep-as3-metadata name="ManagedEvent"/>
        <keep-as3-metadata name="PostConstruct"/>
        <keep-as3-metadata name="Destroy"/>

        <!-- All granite-essentials.swc classes must be included in the output swf -->
        <compiler.include-libraries dir="${gds.build}" append="true">
            <include name="granite-essentials.swc" />
        </compiler.include-libraries>

        <!-- Actually used only granite.swc classes are included in the output swf -->
        <compiler.library-path dir="${gds.build}" append="true">
            <include name="granite.swc"/>
        </compiler.library-path>
     </mxmlc>
 </target>
        

Maven is a popular build tool. Though GraniteDS is not itself built with Maven, its artifacts are available in the Maven central repository and can thus be easily added as dependencies to any Maven project.

The Java dependencies for the server application are in the group org.graniteds.



<dependency>
    <groupId>org.graniteds</groupId>
    <artifactId>granite-core</artifactId>
    <version>${graniteds.version}</version>
    <type>jar</type>
</dependency>

<dependency>
    <groupId>org.graniteds</groupId>
    <artifactId>granite-hibernate</artifactId>
    <version>${graniteds.version}</version>
    <type>jar</type>
</dependency>

...
        

The Flex application can be built using the Flexmojos plugin. Here is a simple project descriptor for a Flex module :



<?xml version="1.0" encoding="UTF-8"?>
<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>com.myapp</groupId>
    <artifactId>myapp-flex</artifactId>
    <packaging>swf</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>My Flex Module</name>

    <dependencies>
        <dependency>
            <groupId>com.adobe.flex.framework</groupId>
            <artifactId>flex-framework</artifactId>
            <version>${flex.framework.version}</version>
            <type>pom</type>
        </dependency>
        
        <dependency>
          <groupId>com.adobe.flexunit</groupId>
          <artifactId>flexunit</artifactId>
          <version>4.0-rc-1</version>
          <type>swc</type>
          <scope>test</scope>
        </dependency>    
        
        <dependency>
            <scope>internal</scope>
            <groupId>org.graniteds</groupId>
            <artifactId>granite-essentials-swc</artifactId>
            <version>${graniteds.version}</version>
            <type>swc</type>
        </dependency>
    
        <dependency>
            <groupId>org.graniteds</groupId>
            <artifactId>granite-swc</artifactId>
            <version>${graniteds.version}</version>
            <type>swc</type>
        </dependency>
    </dependencies>
  
    <build>
        <finalName>myapp</finalName>
        <sourceDirectory>src/main/flex</sourceDirectory>
        <testSourceDirectory>src/test/flex</testSourceDirectory>
    
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.sonatype.flexmojos</groupId>
                    <artifactId>flexmojos-maven-plugin</artifactId>
                    <version>${flexmojos.version}</version>
                </plugin>
            </plugins>
        </pluginManagement>
        
        <plugins>
            <plugin>
                <groupId>org.sonatype.flexmojos</groupId>
                <artifactId>flexmojos-maven-plugin</artifactId>
                <version>${flexmojos.version}</version>
                <extensions>true</extensions>
                <dependencies>
                    <dependency>
                        <groupId>com.adobe.flex</groupId>
                        <artifactId>compiler</artifactId>
                        <version>${flex.framework.version}</version>
                        <type>pom</type>
                    </dependency>
                </dependencies>
                <configuration>
                    <contextRoot>/myapp</contextRoot>
                    <sourceFile>Main.mxml</sourceFile>
                    <incremental>true</incremental>
                    <keepAs3Metadatas>
                        <keepAs3Metadata>Bindable</keepAs3Metadata>
                        <keepAs3Metadata>Managed</keepAs3Metadata>
                        <keepAs3Metadata>ChangeEvent</keepAs3Metadata>
                        <keepAs3Metadata>NonCommittingChangeEvent</keepAs3Metadata>
                        <keepAs3Metadata>Transient</keepAs3Metadata>
                        <keepAs3Metadata>Id</keepAs3Metadata>
                        <keepAs3Metadata>Version</keepAs3Metadata>
                        <keepAs3Metadata>Lazy</keepAs3Metadata>
                        <keepAs3Metadata>Name</keepAs3Metadata>
                        <keepAs3Metadata>In</keepAs3Metadata>
                        <keepAs3Metadata>Out</keepAs3Metadata>
                        <keepAs3Metadata>Inject</keepAs3Metadata>
                        <keepAs3Metadata>Produces</keepAs3Metadata>
                        <keepAs3Metadata>PostConstruct</keepAs3Metadata>
                        <keepAs3Metadata>Destroy</keepAs3Metadata>
                        <keepAs3Metadata>Observer</keepAs3Metadata>
                        <keepAs3Metadata>ManagedEvent</keepAs3Metadata>
                    </keepAs3Metadatas>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
        

Building a full Flex / Java EE Web application with Maven is rather complex and requires to create a multi-module parent project with 3 modules : a Java server module, a Flex module and a Web application module, each having its own pom.xml, dependencies and plugin configurations. It is thus recommended that you start from one of the existing GraniteDS/Maven archetypes :

Note than using Maven 3 is highly recommended but Maven 2.2 should also work. A project can then be created using the following command :

mvn archetype:generate
	-DarchetypeGroupId=org.graniteds.archetypes
	-DarchetypeArtifactId=graniteds-tide-spring-jpa-hibernate
	-DarchetypeVersion=1.1.0.GA
	-DgroupId=com.myapp
	-DartifactId=springflexapp
	-Dversion=1.0-SNAPSHOT
        

To build the application, just run :

cd springflexapp
mvn install
        

The Spring and Seam archetypes define a Jetty run configuration so you can simply test your application with :

cd webapp
mvn jetty:run-war
		

The CDI archetype defines an embedded GlassFish run configuration so you can test your application with :

cd webapp
mvn embedded-glassfish:run
        

To deploy your application to another application server (for example Tomcat), you may have to change the Gravity servlet in web.xml. Then you can build a war file with :

cd webapp
mvn war:war
		

There are different options for working with Flash Builder. The easiest is to use a single combined Flex/Java project that will contain the source files for both the server and client parts of the application.

You should install the GraniteDS Eclipse Builder plugin (see here) so you can benefit from the automatic Java -> AS3 code generation. In can be installed in a standalone Flex/Flash Builder or in an Eclipse installation with the Flash Builder plugin.

The first step is to create a new Java EE Web project. You can use the Eclipse WTP wizard (File / New / Web / Dynamic Web Project) :

Change the name of the source folder to java instead of src to avoir conflicts with the Flex source folder we will add later.

Then copy the necessary GraniteDS libs in the folder WebContent/WEB-INF/lib. That should be fine for the Java side.

Next add the Flex nature to the project by right-clicking on the project and selecting Add/Change Project Type / Add Flex Project Type.... Then follow the steps on the wizard.

You may want to change the target build folder of Flex to WebContent so the target swf will be directly compiled in the exploded war folder.

You should change the source folder to flex in the project properties in Flex Build Path and set the target url so the Flex debugger will connect to the application deployed on the server :

Next copy the GraniteDS client libraries granite.swc and granite-essentials.swc to the libs folder, and configure the compiler options in the project properties in Flex Compiler :

Finally we add the GraniteDS nature to the project with right-click / Add GraniteDS Nature. Remember to change the target folder to flex. The GraniteDS properties should like this :

If you have configured a target server (Tomcat for example), you now have a complete environment to run your application. All changes to the Flex application will be automatically deployed to Tomcat thanks to the Eclipse WTP publishing of the WebContent folder.