I have been really digging into Flex lately and I have been complimenting Flex’s incredibly nice UI capabilities with services written on Grails. I am extremely impressed with Flex and Grails really helps me get things up and running very quickly (you already know this if you are using Grails). Let’s look at a quick example of where I am using one domain class and a few simple Grails actions in a controller in order to provide search and editing capabilities to a simple Flex application based on a datagrid.
The Grails domain class, Item.groovy:
...
class Item {
String name
String brand
String line
}
...
The Grails controller class ItemController.groovy:
...
class ItemController {
def search = {
if(!params.max) {
params.max = 100
}
if(!params.name) {
params.name = ""
}
def itemList = Item.findAllByNameLike("$params.name%",[max:params.max])
render(contentType:"text/xml") {
items {
for(i in itemList) {
item {
id(i.id)
name(i.name)
brand(i.brand)
line(i.line)
}
}
}
}
}
def save = {
if(params.id) {
def item = Item.get(params.id)
if(item) {
item.properties = params
if(!item.hasErrors() && item.save()) {
render ""
}
else {
render ""
}
}
}
}
}
...
I also added this to the conf/BootStrap.groovy so I would have some data to work with once I started up the Grails applicaiton. The code below creates 1,000 items during start-up:
...
def init = { servletContext ->
(1..1000).each {
new Item(name: "Item $it", brand: "My Brand", line: "My Line").save()
}
}
...
I mostly worked with only 1,000 items, but I increased this up to 100,000 items to put it through some tests and it worked very nicely.
Now let’s dive right into the MXML. Here is the entire itemlist.mxml file:
...
<?xml version="1.0"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.events.DataGridEvent;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
[Bindable]
private var itemId:String;
[Bindable]
private var itemName:String;
[Bindable]
private var itemBrand:String;
[Bindable]
private var itemLine:String;
private function sendItemData(event:DataGridEvent):void
{
var myEditor:TextInput = TextInput(event.currentTarget.itemEditorInstance);
itemName = myEditor.text;
itemId = event.currentTarget.editedItemRenderer.data["id"];
itemBrand = event.currentTarget.editedItemRenderer.data["brand"];
itemLine = event.currentTarget.editedItemRenderer.data["line"];
itemSaveService.send();
}
protected function filterList():void
{
itemSearchService.send();
}
private function fault_Handler(event:FaultEvent):void
{
Alert.show(event.fault.message, "Could not load items.");
}
]]>
</mx:Script>
<mx:HTTPService
id="itemSaveService"
method="POST"
url="http://localhost:8080/itemlist/item/save"
resultFormat="e4x"
fault="fault_Handler(event);"
showBusyCursor="true">
<mx:request xmlns="">
<id>{itemId}</id>
<name>{itemName}</name>
<brand>{itemBrand}</brand>
<line>{itemLine}</line>
</mx:request>
</mx:HTTPService>
<mx:HTTPService
id="itemSearchService"
method="GET"
url="http://localhost:8080/itemlist/item/search"
resultFormat="e4x"
fault="fault_Handler(event);"
showBusyCursor="true">
<mx:request xmlns="">
<name>{searchBox.text}</name>
</mx:request>
</mx:HTTPService>
<mx:Panel title="Item List" height="100%" width="100%" paddingTop="10" paddingLeft="10" paddingRight="10">
<mx:Label text="Search:"/><mx:TextInput id="searchBox" enter="filterList();"/>
<mx:DataGrid id="dg" width="100%" height="50%" rowCount="5"
dataProvider="{itemSearchService.lastResult.item}"
editable="true"
itemEditEnd="sendItemData(event);">
<mx:columns>
<mx:DataGridColumn dataField="id" headerText="Id" editable="false"/>
<mx:DataGridColumn dataField="name" headerText="Name"/>
<mx:DataGridColumn dataField="brand" headerText="Brand" editable="false"/>
<mx:DataGridColumn dataField="line" headerText="Line" editable="false"/>
</mx:columns>
</mx:DataGrid>
</mx:Panel>
</mx:Application>
...
Now that all of the code is out on the table, we can start to dissect what is happening with the Flex UI.
When the application starts up:

Once we type in “Item ” and press enter:

When we click on a value under the “Name” column in our datagrid:

We have 2 HTTPService’s setup to send requests back to our Grails controller at http://localhost:8080/itemlist/item/save and http://localhost:8080/itemlist/item/search. The first service call will send all the item data to the ItemController’s save action and the second one will send our search box’s text to the ItemController’s search action. We have ActionScript functions that handle the “Enter” key press event on the search box and we also have a function that will be called after the datagrid field has been edited.
Most of the code is pretty self explanatory but if you have any questions, feel free to contact me. Also, Marcel Overdijk has some great posts on Grails and Flex that can really help out when you get stuck.