Flex Front End For Seam & JBoss

This covers the front end of the server side app I talked about in my previous post.

The demo Oracle database I’d linked my Seam app to had a little table with addresses so I decided to display them in a datagrid and use a Google Map display to go to any address selected in the datagrid.

I swiped the Google Map code from some experiments I’d done with that API so it also has a function that will display the lat,long for a position clicked in the map. It doesn’t really serve any purpose here so consider it a little extra demo.

Here’s the code:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:ns1="com.google.maps.controls.*" applicationComplete="ro.getResultList()">
<mx:RemoteObject id="ro" destination="seam-userDB"/>
<mx:Script>
<![CDATA[

import com.google.maps.LatLng;
import com.google.maps.Map;
import com.google.maps.MapEvent;
import com.google.maps.MapType;
import com.google.maps.MapMouseEvent;
import com.google.maps.InfoWindowOptions;
import com.google.maps.controls.MapTypeControl;
import com.google.maps.controls.ZoomControl;
import com.google.maps.services.ClientGeocoder;
import com.google.maps.services.GeocodingEvent;
import com.google.maps.overlays.Marker;
import com.google.maps.overlays.MarkerOptions;

import mx.controls.Alert;

private function onMapReady(event:Event):void {
this.map.setCenter(new LatLng(40.736072,-73.992062), 14, MapType.NORMAL_MAP_TYPE);
this.map.addEventListener(MapMouseEvent.CLICK, onMapClick);
this.map.addControl(new ZoomControl());
this.map.addControl(new MapTypeControl());
}

private function onMapClick(event:MapMouseEvent):void {
map.openInfoWindow(event.latLng, new InfoWindowOptions({title: "Location", content: event.latLng.toString()}));
}

private function mapGoto():void {
// Geocoding example
var geocoder:ClientGeocoder = new ClientGeocoder();

geocoder.addEventListener(
GeocodingEvent.GEOCODING_SUCCESS,
function(event:GeocodingEvent):void {
var placemarks:Array = event.response.placemarks;
if (placemarks.length > 0) {
map.setCenter(placemarks[0].point);
var marker:Marker = new Marker(placemarks[0].point);

marker.addEventListener(MapMouseEvent.CLICK, function (event:MapMouseEvent):void {
marker.openInfoWindow(new InfoWindowOptions({content: placemarks[0].address}));
});
map.addOverlay(marker);
}
});
geocoder.addEventListener(
GeocodingEvent.GEOCODING_FAILURE,
function(event:GeocodingEvent):void {
Alert.show("Sorry Couldn't find that place!");
trace(event);
trace(event.status);
});
geocoder.geocode(address.text);
}
]]>
</mx:Script>

<mx:Style>
Alert
{
fontFamily:"Times New Roman";
fontSize:14;
}
</mx:Style>

<mx:Panel title="Matt's Maps" width="100%" height="100%" fontSize="14" fontFamily="Times New Roman" fontWeight="bold">
<maps:Map xmlns:maps="com.google.maps.*" id="map" mapevent_mapready="onMapReady(event)" width="100%" height="100%" key="ADD YOUR GOOGLE MAP KEY HERE"/>
<mx:ControlBar>
<mx:DataGrid id="dg" dataProvider="{ro.getResultList.lastResult}" width="100%" height="100%" itemClick="mapGoto()"/>

<mx:Button label="Get Data" click="ro.getResultList()"/>

</mx:ControlBar>
<mx:Label id="address" text="{dg.selectedItem.custStreetAddress1} {dg.selectedItem.custCity} {dg.selectedItem.custState}"/>
</mx:Panel>

</mx:Application>

The Application node includes the google namespace and instructs the app to call the remote object’s getResultList method.

The next line defines the remote object and links it to the destination we declared on the server.

The onMapReady method is called when the map ready event is fired and sets the map to center in Manhattan NY, adds zoom and map type controls.

The onMapClick method is the little piece I added to show the lat,long of a point clicked in the map.

mapGoto is where all the real work is done. This adds two geocode event listeners. One for success (in which case the map is moved to the location and a marker added, together with a click event listener to pop up the address in a window if it’s clicked). One for failure (in which case an alert is shown).

After those event listeners are registered, the method calls the geocoder with an address. The geocoder is responsible for translating an address into a map location.

That concludes the embedded ActionScript code, the remainder is more presentation.

There’s a small style definition to use Times New Roman as the font at 14 point size and then the screen layout.

All of that should be pretty self-evident with the dataProvider for the data grid specified as the last result of the remote object method call and the address label being constructed from the address elements of the selected line in the data grid.

I was planning to include a screenshot of the running app but unfortunately the demo database I was hooked up to wasn’t under my control and it’s currently offline. If I can get it going, I’ll add a screenshot – until then, you’ll have to take my word for it!

Advertisements

4 Responses to “Flex Front End For Seam & JBoss”

  1. Xavier Says:

    Hello,
    thanks for your post… it is very interesting…
    I want to make something like you:

    based on a datagrid containing a zip code and country (for example 1200 Belgium), I’d like to place markers on the locations in the xml.

    Could you give me a clue?
    Thank you!

  2. Xavier Says:

    …sorry, in my previous post, the locations are the zip code + country in a xml… that’s how the datagrid will be generated.

    • mattreyuk Says:

      hey Xavier – I think I’ve got some ideas for you. I’m on vacation ’till the 18th but I’ll write more when I get back

    • mattreyuk Says:

      Xavier, you can use XML for the input to the datagrid by including a model tag (click on the model in my tag list to see my posts about it). You can add the XML directly in the model or reference a file containing the XML. Then you need to change the dataProvider of the datagrid to be the id of your new model (don’t forget to make it bindable). The names for the columns in the datagrid will be the element names of your xml so you’ll probably need to change the text of the address label to combine the fields you need. This is what’s used as input for the geocoder which converts the text address data you give it into a geocode value the map will understand (the success callback is responsible for putting the marker on the map).
      Google maps will return geocodes for less than complete addresses but you should probably check the api docs to see what the minimum data it will require to return successfully.

      Hope that helps…


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: