Bill Bejeck

Created

4 August 2008

Requirements
     
Prerequisite knowledge
Required products Sample files  
Prior experience working with Flex Builder to create applications would be helpful. Some experience using the Grails framework would also be helpful, but it is not required. For additional background, see "Creating components and enforcing separation of concerns with Flex." This article builds on the code developed in that article.

Flash Builder (Download trial) 

Flex 3 (Download trial)

flex_grails.zip (1514 KB)  
User level      
Intermediate      
 
The Grails framework greatly simplifies the task of building a Java web application. This article illustrates one approach to integrating a Flex application with a Java server application using Grails. The sample application for this article is a simple Flex search application, but the principles shown here still apply for building more complex applications.
 
While there are many great options available for connecting Flex applications with a server application, for example, LiveCycle Data Services ES or its open source counterpart BlazeDS, the sample application uses a RESTful approach for client-server communication. It is true that using the aforementioned frameworks offer several powerful advantages, but there are benefits to using a XML/RESTful approach that should not automatically be discounted. Chief among these are:
 
  1. RESTful services are straightforward to implement and maintain.
  2. The server and client applications, respectively, either respond with XML or parse responses sent in XML, freeing them from dependence on any particular platform. Note: Using XML is not required; the approach outlined here could be used with JSON.
  3. No mapping files of any kind are required.
  4. There is less of a learning curve if this is the first experience building a Flex client with a Java server application.
Though this article focuses on Flex with Grails, since it uses a RESTful approach, you could easily use Spring MVC or a non-Java framework, such as Ruby on Rails.
 
The file flex_grails.zip contains the source code for this article. The top level directory of the extracted file is named sources and will be referred to as <SOURCES_DIR> from this point forward. The <SOURCES_DIR> directory contains the following:
 
  • /flex – the top level directory of the Flex client. To use this with Flex Builder, open Eclipse and then choose File > Import > Existing Project and select <SOURCES_DIR>/flex
  • /flex-grails – the top level directory of the Grails application. Everything is there for a complete Grails application. To use this in Eclipse, open Eclipse and then choose File > Import > Existing Project then select <SOURCES_DIR>/flex-grails. Note: If you decide to import as a project into Eclipse, I suggest installing the Groovy Eclipse Plugin available at http://groovy.codehaus.org/Eclipse+Plugin.
  • /sql – this directory contains files sakila-schema.sql and sakila-data.sql
  • /FlexTasks.groovy – a Gant file that uses the Flex Ant tasks.

 
Refactoring

The sample application discussed in Creating components and enforcing separation of concerns with Flex asynchronously communicates with the sever application using the HTTPService class. In this article, I am going to use the same approach and the same code, but I will refactor and add a level of abstraction. Specifically I will:
 
  1. Add an interface, Controller, with one method, search.
  2. Add an implementation of the Controller interface, named HttpController.
  3. Add a class, URLConstants, which simply holds static strings that the controller will use to connect to the server application. This provides the ability to change the connection strings in one place and have those changes propagate throughout the application.
  4. Add the ability to set the fields and labels properties of the SearchResultGrid class as array literals in the SearchPanelView.mxml file, where the SearchResultGrid class is declared, for increased reusability.
The Controller interface will look something like:
 
public interface Controller { public void search(searchParams:Object, callback:Function=null); }
The parameter searchParams is an object literal in the form {key:value, key:value} that contains the parameters of the request. The parameter callback is a function object that will be executed once the response is returned. The implementation class, HttpController will look like the following (not all of its code is shown):
 
public class HttpController implements Controller{ private _searchService:HTTPService; public void search(reqParams:Object, callback:Function=null){ _searchService.method="GET"; _searchService.url = URLConstants.SEARCH; _searchService.resultFormat=HTTPService.RESULT_FORMAT_E4X; _searchService.addEventListener(ResultEvent.RESULT,onSearchComplete); _searchService.addEventListener(FaultEvent.FAULT,onError); var token:AsyncToken = _searchService.send(params) token.callback=callback }
The code in the SearchPanel needed to execute the search is reduced to one line:
 
_controller.search({text:_searchTerm.text},_searchResultGrid.displaySearchResults);
The URLConstants class will look like:
 
public final class URLConstants { private static BASE_URL = "/application" public static SEARCH_URL = BASE_URL+"/search" }
Over time this class may grow as the application provides access to other services.
 
Finally, the SearchResultGrid declaration in the SearchPanelView.mxml file will now look like:
 
<comp:SearchResultGrid id="searchResultGrid" percentWidth="100" percentHeight="60" resultElementName="film" fields="{['title','length','price','date']}" labels="{['Title','Running Time','Rental Rate','Year Released']}" />
What have I gained from this refactoring? In the search component all the details of the HttpService class, specifically how and where the client communicates with the server, are now abstracted into one method call, _controller.search(), but the callback and the processing of the result remains exactly the same. Why the separate interface and implementation? Here are a few reasons:
 
  1. This allows me to completely abstract from the search component where or how it is getting its information, which means I can change how it connects to the information source with no impact on the search component.
  2. Testing the search component is now much easier. (Testing is not covered here, but it will be in a future segment).
  3. If at some point I want to start taking advantage of Flex remoting frameworks, I can seamlessly plug in BlazeDS at the controller level by creating a new class that implements Controller with no additional impact on the client code.

 
Dependency Injection

Now that I have abstracted details of the search process, I need to add an instance of type Controller to the SearchComponent class.
 
First, I add a setter method in the SearchComponent class:
 
Then, I add the following line to the SearchComponent.mxml file:
 
public function set controller(controller:Controller):void
<comp:HttpController id="controller" />
This is a kind of "poor man's dependency injection". Once the Flex application is loaded,
 
the HttpController object defined above will be automatically be injected into the SearchComponent class via the setter method defined above.
 

 
Setting up the Grails project

At this point the refactoring of the Flex search client is complete, and I am ready to build the Grails application. A discussion of how to build a Grails application is beyond the scope of this article. To run the sample application, first follow these steps to set up Grails and MySQL:
 
  1. After downloading Grails, extract the archive to a directory and set an environment variable GRAILS_HOME pointing to the directory where you extracted Grails. Also add GRAILS_HOME/bin to your path.
  2. If it is not already installed, download and install MySql. This article is based on version 5.0.51a running on a Mac (Leopard). Start the MySql server after installation.
  3. Change to the directory <SOURCES_DIR>/sql, which contains two files, sakila-schema.sql and sakila-data.sql.
  4. From the command line type mysql -u root -p and enter your password when prompted.
    1. To build the sakila database, at the mysql prompt, type SOURCE sakila-schema.sql; and press Enter.
    2. To load the data, at the mysql prompt type SOURCE sakila-data.sql; and press Enter.
    3. At the mysql prompt type GRANT ALL PRIVILEGES ON sakila.* TO 'sa'@'localhost' IDENTIFIED BY 'pass' WITH GRANT OPTION; and press Enter. Then type quit to disconnect from the MySql server.

 
Grails controller

Now that you know how the Flex client will communicate with the server, let's go over how the Grails application will respond to the Flex client. Fortunately, Grails makes this extremely simple. The file FilmController.groovy in <SOURCES_DIR>/flex-grails/controller has only one method:
 
def search = { def movies = Film.createCriteria().list{like("title","%${params.text}%")} render(contentType:"text/xml") { films { for(i in movies) { film { title(i.title) length(i.length) rate(i.rate) date(i.releaseYear) } } } } }
This method searches the Film table for titles that contain the text entered by the user. While it's not a great search effort, it works for demonstration purposes. As you examine this code, note the following:
 
  • The line that reads films { will be the root node of the XML response and is ignored by E4X.
  • film is the parent node for each result returned and corresponds to the property resultElementName in the SearchResultGrid class of the Flex client. Basically, this is how E4X determines where each row goes in the SearchResultGrid.
  • title, length, rate, and date correspond to the entries in the fields ArrayCollection in the SearchResultGrid class, and E4X uses the text value in each node to populate the respective column in each row.

 
Deployment

With the Grails application and Flex search client complete, I am ready to deploy them. While there are several ways to deploy a Flex client - Grails/Java server application, Flex Ant tasks are a good option. There are three Flex Ant tasks:
 
  1. mxmlc – used to compile all of the ActionScript and MXML files into one SWF file that becomes the "executable" for the Flash player.
  2. html-wrapper – used to generate a simple HTML page with <object> tags to download the Flash player and run the Flex application.
  3. compc – used to compile ActionScript library files into SWF files.
Of these three tasks, you only need to work with mxmlc and html-wrapper.
 
 
To use the Flex Ant tasks:
  1. Place the flexTasks.jar file in <GRAILS_INSTALL_DIR>/ant/lib directory. The flexTasks.jar file can be found in <FLEX_SDK_DIR>/ant/lib or <FLEX_BUILDER_DIR>/sdks/3.0.0/ant/lib.
  2. Copy <SOURCES_DIR>/FlexTasks.groovy to the <GRAILS_INSTALL_DIR>/scripts directory.
  3. In the file <SOURCES_DIR>/flex-grails/flex.properties, set 'FLEX_HOME' to the location of the Flex SDK, either the standalone Flex SDK or the one included with Flex Builder. If you use the SDK included with Flex Builder, be sure to use version 3. There are several other properties in this file that have default values; the Flex documentation has detailed descriptions of the settings and the implications of each.
 
To complete the deployment process:
  1. Change to the <SOURCES_DIR>/flex-grails directory
  2. From the command prompt run grails flex-tasks.
  3. When the code finishes executing, the web-app directory should contain the following:
    • mainView.swf, a file run by the Flash player
    • index.gsp, a wrapper file that will load the Flash player
    • AC_OEtags.js, a file used in loading the Flash player
    • history, a directory that contains three files: history.css, history.js, and historyFrame.html
  4. From the command prompt run grails run-app.
  5. Point your browser to http://localhost:8080/movies to see the application.

 
Where to go from here

  1. Be sure to check out LiveCycle Data Services or the open source version BlazeDS for further remoting options.
  2. For more information on Grails development, visit http://www.grails.org or the excellent series of articles on Grails by Scott Davis.
  3. You may want to try the Grails Flex Plug-in, which makes it easy to use BlazeDS with a Flex client.
  4. There is also some great information about using Maven with Flex in Jacob von Eyben's blog.