4 August 2008
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.
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:
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:
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:
search.HttpController.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.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:
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:
public function set controller(controller:Controller):void
Then, I add the following line to the SearchComponent.mxml file:
<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.
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:
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:
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.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:
<object> tags to download the Flash player and run the Flex application.Of these three tasks, you only need to work with mxmlc and html-wrapper.

This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License