In the previous recipe, we saw how we can scaffold a complete GWT application using Roo. In this recipe, we'll see how Roo simplifies setting up Flex for your Roo project. In the next recipe Scaffolding Flex application from JPA entities we'll look at how Roo generates a fully-functional Flex application to perform CRUD operations on JPA entities.
At the time of writing this book, Flex addon is not compatible with Spring Roo 1.1.3 and above; therefore, download Spring Roo 1.1.2.
At the time of writing this recipe, the Flex addon used is the snapshot version dated 15-Aug-2011 from the Flex Spring Roo addon repository (http://s3browse.springsource.com/browse/maven.springframework.org/snapshot/org/springframework/flex/roo/addon/org.springframework.flex.roo.addon/1.0.0.BUILD-SNAPSHOT/)
. Download the JAR file named org.springframework.flex.roo.addon-xx.jar
and copy it to Roo's bundle
directory or install it using the osgi start
(explained in Chapter 7, Developing Add-ons and Removing Roo from Projects) command.
Flex add-on is an example of an installable add-on. For more information on installable add-ons, see Chapter 7, Developing Add-ons and Removing Roo from Projects.
Create a new directory C:
oo-cookbookch05-flex
in your system and start the Roo shell from the ch05-flex
directory. Enter the help
command and check whether you see flex setup
, flex remoting scaffold
, and flex remoting all
commands in the output. If you see the flex
commands in the output of the help
command, it means you have successfully installed the Flex addon.
Copy the ch05_flex_app.roo
script that accompanies this book to the ch05-flex
directory. Now, execute the ch05_flex_app.roo
script using the script
command. Executing the ch05_flex_app.roo
script creates a flightapp_flex
Eclipse project, sets up Hibernate as persistence provider, configures MySQL as the database for the application, creates Flight
and FlightDescription
JPA entities, and defines a many-to-one relationship between the Flight
and FlightDescription
entities. If you are using a different database than MySQL or your connection settings are different than what is specified in the script, then modify the script accordingly.
Though not required, you may also want to download Flash Builder 4 and install it as the Eclipse plugin to simplify editing MXML and ActionScript files generated by Roo in this recipe.
To set up the flex application, follow the steps given here:
flex
setup
command to create Spring BlazeDS integration-related configuration artifacts in the flightapp_flex
project:... roo> flex setup Created SRC_MAIN_WEBAPPWEB-INFflex Created SRC_MAIN_WEBAPPWEB-INFflexservices-config.xml ... Created SRC_MAIN_WEBAPPWEB-INFspring Created SRC_MAIN_WEBAPPWEB-INFspringflex-config.xml Created SRC_MAIN_WEBAPPWEB-INFspringwebmvc-config.xml ... Created SRC_MAIN_WEBAPPWEB-INFweb.xml Managed SRC_MAIN_WEBAPPWEB-INFweb.xml ... Managed SRC_MAIN_WEBAPPWEB-INFspringwebmvc-config.xml Managed ROOTpom.xml [Added dependency com.adobe.flex.framework:flex-framework:4.0.0.14159] Managed ROOTpom.xml [Added dependency org.springframework.flex:spring-flex-core:1.5.0.BUILD-SNAPSHOT] ... Created ROOT.flexProperties Created ROOT.actionScriptProperties ... Created ROOTsrcmainflexflightapp_flex_scaffold.mxml Created SRC_MAIN_WEBAPPflightapp_flex_scaffold.html Created ROOTsrcmainflexflightapp_flex_scaffold-config.xml
pom.xml
file so that the Flex add-on can download Flex add-on dependencies that are not yet available in milestone or in the release Maven repository of Spring:<repositories> <repository> <id>spring-maven-snapshot</id> <name>Spring Maven Snapshot Repository</name> <url> http://maven.springframework.org/snapshot </url> </repository> ... </repositories>
http://repository.sonatype.org/content/sites/flexmojos-site/3.8/plugin-info.html
) in the pom.xml
file, as shown here:<pluginRepositories> <pluginRepository> <id>flexmojos-repository</id> <url> http://repository.sonatype.org/content/groups/flexgroup/ </url> </pluginRepository> ... </pluginRepositories>
perform
eclipse
command to update the project's classpath settings with the newly added dependencies in pom.xml
file. It also adds Flex and ActionScript nature to the flightapp_flex
Eclipse project.The flex
setup
command is processed by the Flex add-on of Roo.
The flex
setup
command configures Spring BlazeDS integration and creates the necessary artifacts that are required for developing a Flex 4 application. The following table describes some of the important directories and files that were created by the flex setup
command:
Directory / File |
Description |
---|---|
|
Contains |
|
The |
|
The |
|
Spring's web application context XML, which is loaded by |
|
The Roo generates a |
|
The |
|
The |
Let's now look at the important configuration files created by Spring Roo.
The webmvc-config.xml
file is Spring's web application context XML file, and is loaded by DispatcherServlet
configured in the web.xml
file of the flightapp_flex
project. The webmvc-config.xml
file imports bean definitions in the flex-config.xml
application context XML file, as shown here:
webmvc-config.xml
<beans ....>
....
<import resource="flex-config.xml"/>
</beans>
For information on other elements defined in webmvc-config.xml
file, please refer to Chapter 4, Web Application Development with Spring Web MVC.
The flex-config.xml
makes use of the <message-broker>
element of Spring's flex
schema to configure and initialize a BlazeDS MessageBroker
, as shown here:
flex-config.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:flex="http://www.springframework.org/schema/flex"
...>
<flex:message-broker mapping-order="1">
<flex:mapping pattern="/messagebroker/*"/>
<flex:message-service default-channels="longpolling-amf" />
</flex:message-broker>
</beans>
By default, the <message-broker>
element considers the /WEB-INF/flex/services-config.xml
file as the configuration file for BlazeDS MessageBroker
. If you change the name or location of the services-config.xml
file in flightapp_flex
, then use the services-config-path
attribute of the <message-broker>
element to specify your BlazeDS configuration XML file.
The <mapping>
element of the flex
schema maps incoming requests from the DispatcherServlet
to /messagebroker/*
path—the path to which BlazeDS MessageBroker
channels are mapped in services-config.xml
, as we'll see shortly.
The <message-service>
element configures a BlazeDS flex.messaging.services.MessageService
object that provides a publish-subscribe messaging between producers and consumers of messages in the application. The default-channels
attribute specifies the message channel(s) used by Flex clients to access MessageService
or to receive messages from it. The longpolling-amf
value refers to the AMFChannel
configured in services-config.xml
, with polling enabled.
It is important to note that even though Roo configures MessageService
, it is not used by the Roo-generated Flex application.
The following listing shows the channels configured in the Roo-generated services-config.xml
file:
services-config.xml <channels> <channel-definition id="amf" class="mx.messaging.channels.AMFChannel"> <endpoint url="http://{server.name}:{server.port}/ {context.root}/messagebroker/amf" class="flex.messaging.endpoints.AMFEndpoint"/> </channel-definition> ... <channel-definition id="longpolling-amf" class="mx.messaging.channels.AMFChannel"> <endpoint url="http://{server.name}:{server.port}/ {context.root}/messagebroker/amflongpolling" class="flex.messaging.endpoints.AMFEndpoint"/> <properties> <polling-enabled>true</polling-enabled> .... </properties> </channel-definition> ... </channels>
This code listing shows channel definitions as created by Roo. A <channel-definition>
element defines a channel. The id
attribute is a unique identifier of a channel and is used by Flex clients to connect to an endpoint. The class
attribute identifies the type of the channel. The enclosing <endpoint>
element defines the endpoint corresponding to the channel. The url
attribute of the <endpoint>
element specifies the URL of the server and class
attribute specifies the endpoint class. Flex components make use of channels to communicate with BlazeDS endpoints. For instance, the above code listing indicates that AMFChannel
is used by Flex to communicate with the AMFEndpoint
.
The {server.name}
and {server.port}
tokens used by the url
attribute value are replaced at runtime based on the URL of the server from which the SWF file is downloaded. The {context.root}
token is replaced with a value that is calculated at compile-time based on the <contextRoot>
configuration option defined in the pom.xml
file for the Flexmojos Maven plugin. Later in this recipe, we'll look at the Flexmojos Maven plugin configuration generated by Roo for the flightapp_flex
project.
The incoming requests to DispatcherServlet
are routed to the BlazeDS MessageBroker
, because the <mapping-pattern>
element value (that is, /messagebroker/*
) in flex-config.xml
maps to the url
attribute value (http://../messagebroker/..)
of the <endpoint>
elements in services-config.xml
.
We saw earlier that the longpolling-amf
channel is used as the default channel by MessageService
for transporting messages. The <polling-enabled>
property of the channel is set to true
, which means that polling is enabled for the longpolling-amf
channel.
The following <services>
element of the services-config.xml
file shows the application-level default channels configuration:
<services> <default-channels> <channel ref="amf"/> </default-channels> </services>
This <default-channels>
element specifies that if a Flex component doesn't specify the channel to be used, then use the amf
channel for communication.
Roo also configures server-side logging in services-config.xml
using the <logging>
element, as shown here:
<logging> <target class="flex.messaging.log.ConsoleTarget" level="Warn"> <properties> <prefix>[BlazeDS] </prefix> <includeDate>false</includeDate> <includeTime>false</includeTime> <includeLevel>false</includeLevel> <includeCategory>false</includeCategory> </properties> <filters> <pattern>Endpoint.*</pattern> <pattern>Service.*</pattern> <pattern>Configuration</pattern> </filters> </target> </logging>
The logging configuration specifies where the log messages are written, what types of messages are written, how they are written, and the log messages generated by each category (like Endpoint, Service, and so on) are written. The class
attribute (of target
element) value of flex.messaging.log.ConsoleTarget
means that the log messages are written to standard ouput. level="Warn"
means that only warning level messages are written. In the above code, the <properties>
element specifies that log messages are prefixed with [BlazeDS]
and include date, time, logging level, and category. The <filters>
element limits the logging to the categories defined by the <pattern>
sub-elements.
Let's now look at the scaffolded MXML file which serves as the main application file—the MXML file that contains the Application
component of Flex's Spark component library.
The following code listing shows the flightapp_flex_scaffold.mxml
file:
flightapp_flex_scaffold.mxml <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx"..> <fx:Script> <![CDATA[ ... protected function entityList_doubleClickHandler(event:MouseEvent):void { ... } ]]> </fx:Script> <fx:Declarations> <s:ArrayList id="entities"> </s:ArrayList> <s:ChannelSet id="remotingChannels"> <s:AMFChannel id="amf" url= "http://localhost:8080/flightapp_flex/messagebroker/amf"/> </s:ChannelSet> </fx:Declarations> <s:Group id="mainGroup" height="100%" width="100%"> <s:layout> <s:HorizontalLayout/> </s:layout> <s:Panel id="entityPanel" title="Entity List" height="100%"> <s:List id="entityList" dataProvider="{entities}" width="100%" height="100%" toolTip="Double-Click the selected Entity" doubleClickEnabled="true" doubleClick="entityList_doubleClickHandler(event)"/> </s:Panel> </s:Group> </s:Application>
This MXML shows the user interface of the flightapp_flex
application. The <Panel>
tag creates a Spark Panel
component which contains a Spark List
component. The List
component shows the list of entities that can be managed from the user interface. The list of entities is defined by the <ArrayList>
tag. Notice that the value of the dataProvider
attribute of the <List>
tag is {entities}
and the id
attribute value of the <ArrayList>
tag is entities
, which means that the list of entities displayed by the List
component comes from the list defined by the <ArrayList>
tag. Well, the <ArrayList>
tag doesn't contain any element; therefore, for now, the list is empty.
The <ArrayList>
tag is populated with child elements when we execute flex remoting all
or flex remoting scaffold
commands to scaffold a remoting destination corresponding to a JPA entity, as we'll see in the Scaffolding Flex application from the JPA entities recipe.
The doubleClick
attribute of <List>
specifies that the entityList_doubleClickHandler(event)
ActionScript method to be invoked when a user double clicks an item in the list. In the Scaffolding remoting destination from the JPA entities recipe, we'll go through the implementation detail of the entityList_doubleClickHandler(event)
method.
The <ChannelSet>
tag creates a ChannelSet
—a set of channels for communication with the BlazeDS server. We saw earlier that Roo defines the amf
channel (channel type being AMFChannel
) as the default application-wide channel in services-config.xml
; therefore, the Roo-generated <ChannelSet>
tag creates an AMFChannel
using the <AMFChannel>
tag. The url
attribute of <AMFChannel>
specifies the corresponding endpoint URL.
As the url
attribute of the <AMFChannel>
tag specifies the location of the BlazeDS server as localhost
, your Roo-generated flightapp_flex
application will work only if your BlazeDS server is running locally. To avoid hard-coded endpoint URLs, it is recommended that you externalize ChannelSet
configuration into an XML file that is parsed when the Flex application is initialized and later used to communicate with the BlazeDS server.
As mentioned earlier, Roo generates a flightapp_flex_scaffold-config.xml
configuration file that overrides the default Flex compiler settings. Notice that the naming convention followed by the file is: <MXML file name>-config.xml
, where <MXML file name> is the name of the MXML file corresponding to the configuration file which was created. When an MXML file named myApp.mxml
is compiled, Flex compiler looks for a configuration file named myApp-config.xml
in the same location as the MXML file, and uses it to override the default compiler options.
The following listing shows the content of the flightapp_flex_scaffold-config.xml
file:
<flex-config xmlns="http://www.adobe.com/2006/flex-config"> <includes append="true"> </includes> </flex-config>
As this code shows, flightapp_flex_scaffold-config.xml
doesn't do anything interesting. In the Scaffolding Flex application from JPA entities recipe, we'll discuss this file in detail once it's updated after the execution of the flex remoting all
or flex remoting scaffold
command.
We mentioned earlier that Roo configures the Flexmojos Maven plugin in the pom.xml
file of the flightapp_flex
project. Let's now look at the Flexmojos plugin configuration in detail.
Flexmojos Maven plugin offers many features, but for brevity we'll focus only on the flexmojos:compile-swf
goal, which is responsible for compiling the Flex project's sources (MXML and ActionScript files) and package it into an SWF file. The following listing shows the configuration of Flexmojos Maven plugin in the pom.xml
file of the flightapp_flex
project:
pom.xml <plugin> <groupId>org.sonatype.flexmojos</groupId> <artifactId>flexmojos-maven-plugin</artifactId> <version>3.7.1</version> <executions> <execution> <id>compile-scaffold-swf</id> <phase>process-resources</phase> <goals> <goal>compile-swf</goal> </goals> <configuration> <incremental>true</incremental> <sourceFile> ${basedir}/src/main/flex/${project.name}_scaffold.mxml </sourceFile> <sourcePaths> <path>${basedir}/src/main/flex</path> </sourcePaths> <output> ${basedir}/src/main/webapp/${project.name}_scaffold.swf </output> <contextRoot>/${project.build.finalName}</contextRoot> <services> ${basedir}/src/main/webapp/WEB-INF/ flex/services-config.xml </services> <debug>true</debug> </configuration> </execution> </executions> <dependencies> <dependency> <groupId>com.adobe.flex</groupId> <artifactId>compiler</artifactId> <version>4.0.0.14159</version> <type>pom</type> </dependency> </dependencies> </plugin>
In this listing, the <configuration>
element configures the Flexmojos Maven plugin. The <sourceFile>
element identifies the main application MXML file to be compiled by the plugin, which is the flightapp_flex_scaffold.mxml
file. The <sourcePaths>
specifies the base directory or directories where the project's ActionScript files are located, which corresponds to /src/main/flex
— the directory, which is created when you execute the flex remoting all
or flex remoting scaffold
command. The <output>
specifies the name and location of the generated SWF file, which is SRC_MAIN_WEBAPP/flightapp_flex_scaffold.swf
for the flightapp_flex
project. The <contextRoot>
element specifies the context root of the web application, which corresponds to the value /flightapp_flex-0.1.0.BUILD-SNAPSHOT
. The value of <contextRoot>
element is used to replace the {context.root}
token specified in the endpoint URLs defined in services-config.xml
file. The <services>
element specifies the services-config.xml
file that defines channels and corresponding endpoints.
The <dependency>
element specifies that the Flexmojos Maven plugin is dependent on Flex compiler. Note that the dependency type is pom
and not jar
. As the dependency type is pom
, dependencies specified in the corresponding pom
file (which you can find at https://repository.sonatype.org/content/groups/flexgroup/) are added to the required dependencies of the Flexmojos Maven plugin.
3.139.239.41