thejavajar

{ java, groovy, flex, python, ruby }

Flower

Posts Tagged ‘Adobe Flex’

Adobe Air: Getting Started

I wanted to create this post because I needed a reference to where I am at with Adobe Air/Flex. Plus Vladimir Vivien said I needed to blog about what I have been doing. So here is what I have been doing:

I have mostly been creating Flex form based applications with datagrids that rely on RESTful Web services mostly running on Groovy/Grails but I have also created an Air application that communicates with TIBCO EMS. I want to go over the TIBCO integrated Air app, I call systemStatus. Basically, systemStatus makes an HTTP request to a URL like http://host:port/systemStatus and a TIBCO HTTP Receiver listens and responds after executing some processes on the ESB. The TIBCO project includes processes that execute some simple tasks, like queries on databases, and the results are accumulated and mapped to a pre-defined schema. The response is an XML document that looks something like this:

...
<resources>
    <resource>
        <name>Production Oracle</name>
        <type>database</type>
        <vendor>Oracle</vendor>
        <status>offline</status>
        <instance>server 1</instance>
    </resource>
    .
    .
    .
</resources>
...

The XML is pretty simple, but it does what I need it to do. It basically gives us some META data and a status for each of the resources, like databases, which are dependencies of the deployed TIBCO projects. I am going to stay away from the details pertaining to the TIBCO application but if you need some help setting up something like this, just contact me.

Next we turn to the Air/Flex application. The Air application is made up of only a few major components: <mx:HTTPService>, <mx:Panel>, <mx:TextInput>, <mx:DataGrid> and <mx:Button>. At the simplest level, the <mx:HTTPService> makes the call to the TIBCO service and the <mx:DataGrid> handles and displays the XML results. I have added the <mx:TextInput> component so the app can be configured to point to different TIBCO environments running the deployed systemStatus TIBCO application that provides the XML results. Here is the meat of the Air application:

...
<mx:HTTPService id="systemStatusService" result="r_Handler(event)" resultFormat="e4x" fault="f_Handler(event)" url="http://{serverName}" />

    <mx:Panel title="systemStatus" height="100%" width="100%" paddingTop="10" paddingLeft="10" paddingRight="10">

        <mx:ControlBar horizontalAlign="left">
            <mx:Label text="Server:Port"/>
            <mx:TextInput id="serverNameInput" enter="setServerName()"/>
        </mx:ControlBar>

        <mx:Label text="Systems:"/>

        <mx:DataGrid id="systemDG" width="100%" height="80%"
            dataProvider="{systemStatusService.lastResult.resource}"
            editable="true">
            <mx:columns>
                <mx:DataGridColumn dataField="vendor" headerText="Vendor" editable="false"/>
                <mx:DataGridColumn dataField="name" headerText="Name" editable="false"/>
                <mx:DataGridColumn dataField="instance" headerText="Instance" editable="false"/>
                <mx:DataGridColumn dataField="type" headerText="Type" editable="false"/>
                <mx:DataGridColumn dataField="status" headerText="Status" editable="false"/>
            </mx:columns>
        </mx:DataGrid>

        <mx:ControlBar horizontalAlign="left">
            <mx:Button id="refresh"
                label="Refresh"
                rollOver="refresh_rollOver(event);"
                rollOut="refresh_rollOut(event);"
                click="refresh_clickHandler();"/>
        </mx:ControlBar>

</mx:Panel>
...

Here is a screen shot of the Air application:


systemStatus

The refresh button will initiate another request to the TIBCO service and if anything has changed, the XML results will reflect the changes and the <mx:DataGrid> will be updated.

This is a pretty simple idea, but it demonstrates how we can take one technology and combine it with other tools and technologies to create useful applications to make life easier.

Download the code:
systemStatus.zip

Editable Flex Datagrid and Grails

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.

Tangerine – Product Manager Screen Shot

Well I decided to post a screen shot of Tangerine’s Product Manager. I am still working on the Flex front-end but most of my Grails back-end is in place for now. I think Flex is a great technology for creating Rich UI’s with little effort. I have been working with Flex for a few months now and I think that it will definitely be something that development shops will have to consider when moving forward with a new project.

The Grails back-end is probably less complex(to me the developer) than the Flex front-end. When you have the power of Spring and Hibernate with little effort that is a great thing. When you can leverage those technologies with a Flex front-end, you get the best of both worlds.



Tangerine-Product Manager

Tangerine: Grails and Flex Small Business Web Application Suite

So, I am still working on Tangerine. Some of my colleagues have seen some simple demos of what I have done with the Flex/Grails application that I have been working on for a little while now, but it is not ready for public consumption. I am really trying to wrap things up on the first Beta release of Product Manager so I can work on the Account Manager and Sales Manager and get those releases out before summer.

There are a couple of things that I have been fighting with:

First, time. I should be working on some software that helps me create time. Finding time to work on my projects is one of the things that I have been battling each week.

Second, Flex. Flex is great, but I am not a Flex developer, so I guess I really need to break down and buy Flex Builder 3. I am not trying to do anything too crazy, but I think having FB 3 on my side will at least aid me in my quest to build nice RIA Web applications. I have been using TextMate for everything so far. I have 90% of the UI done, but the last 10% is where I need to bring out the big guns.

Everything on the Grails side is going great. There are a few things I need to tweak, but I am still extremely excited about working with Grails. Speaking of working with Grails…I did a search on Dice and found 10 posts for jobs in the US. That number will get bigger, people just need time.