Saturday, March 28, 2009

ArcGIS Server Sample Flex Viewer: Capturing and Using Configuration Data


The Sample Flex Viewer (SFV) uses a simple xml file (config.xml) for application initialization and configuration. Application properties managed by this configuration file include, among others, UI attributes such as banner, title and logo, primary menu configuration, widget management, and layer management.



It is almost a certainty that any customization will require custom configuration settings, either populated by passing in URL parameters (in a future post) or by setting custom properties in the config.xml file. These data can be captured and used by making a few changes to core classes in the SFV. This example focuses on capturing a custom attribute added to one of the existing elements, in this case, the <mapservice> element.


The ultimate goal of this example is to provide some means of categorizing map services identified in the configuration file for display in multiple instances of the livemaps widget, each containing subsets of specific map services. We will do this by adding a custom attribute to the <mapservice> element called group.



<mapservice label="map label" type="dynamic, tiled, arcims, etc" visible="true/false" alpha="0..1" group="wlci">url</mapservice>



Now, getting the data. But first, we need some background. While we won’t be using it directly in this example, it is important to mention the configData class. The configData class does nothing more than provide a place to store the configuration data. It is a collection of arrays which correspond to application functional groups such as UI, menus, maps services, widgets etc. If your intent is to create an entirely new class of configuration data, let’s say for url parameters (more on that in a later post), you would provide the framework for that data in this class. Our example is a bit simpler, we are simply adding a new attribute to an existing class.


The class that does most of the legwork is the configManager. It begins by establishing and HTTPService connection (configService) to the config.xml file and then listens for a result (ResultEvent.RESULT). The important stuff occurs in the handler for this event. Within this handler, an instance of configData is created along with an xml dataset containing the contents of config.xml:



var configData:ConfigData = new ConfigData();

var configXML:XML = event.result as XML;



It then proceeds to parse out the functional collections of data as needed. The following illustrates how it parses out <mapservice> configuration data. This pattern can be used to obtain any attributes added to the mapservice element in the config file.


//================================================

//map

var configMap:Array = [];

var mapserviceList:XMLList = configXML..mapservice;

for (i = 0; i < mapserviceList.length(); i++) {


var msLabel:String = mapserviceList[i].@label;

var msType:String = mapserviceList[i].@type;

var msVisible:Boolean = true;

if (mapserviceList[i].@visible == "false")

msVisible = false;

var msAlpha:Number = 1;

if (!isNaN(mapserviceList[i].@alpha))

msAlpha = Number(mapserviceList[i].@alpha);

var msURL:String = mapserviceList[i];

var mapservice:Object =

{



label: msLabel,

type: msType,

visible: msVisible,

alpha: msAlpha,

url: msURL,



}

configMap.push(mapservice);



}

configData.configMap = configMap;



The previous block of code begins by creating an empty array for populating local data.



var mapserviceList:XMLList = configXML..mapservice;



creates an XMLList of all nodes in the DOM hierarchy called mapservice. The XMLList can then be examined just like an array, stepping through it by using a for statement. Attributes of the elements within the XMLList are then accessed explicitly via the attribute name. For example:



var msLabel:String = mapserviceList[i].@label;



retrieves the value assigned to the label attribute for that particular mapservice node. The value of the node itself is retrieved using the following syntax:



var msURL:String = mapserviceList[i];



For each node instance, a generic object of name/values pairs is then created containing each attribute value along with the value of the node itself. That object is then added to a local array for each node instance and then is assigned to the configData instance upon parsing completion.


For this example, recall that we have added a new attribute called group to each <mapservice> element. To retrieve that value, we simply need to create and assign a new local variable with the attribute value, add it to the generic name/value pairs object and we are golden.



//================================================

//map

...


for (i = 0; i < mapserviceList.length(); i++)

{



...

//retrieve newly added group attribute from mapservice entry

var msGroup:String = mapserviceList[i].@group;

...

var mapservice:Object =

{



...

//add newly added group attribute to mapservice object

group: msGroup,



}



configMap.push(mapservice);

}

configData.configMap = configMap;



Our configData instance now contains the newly added "group" attribute. Once it is completely populated, the CONFIG_LOADED event is dispatched which essentially notifies the application that the configData instance is now available for use. Using the data is even easier. All that is needed is to listen for the CONFIG_LOADED event:



SiteContainer.addEventListener(AppEvent.CONFIG_LOADED, config);



where config is a function whos argument is an event containing the data itself. It is then accessed via the following:



private function config(event:AppEvent):void

{



configData = event.data as ConfigData;



}

This is done by default in the MapManager.mxml component. Have a look at the function called config is this component and you will see that pattern for obtaining data from configData.

private function config (event:AppEvent):void

{

configData = event.data as ConfigData;

....

for (i = 0; i <donfigData.configMap.length; i++)

{

...

var url:String = confData.configMap[i].url;

...

}

}

A nice feature in the Sample Flex Viewer is that the BaseWidget class (that which we extend for all new widgets) exposes the configData object by default. This means we can then obtain data parsed from the config.xml file by the ConfigManager from any widget that extends the BaseWidget. To do this, we do something similar to what the MapManager component does.

for (var i:Number = 0; i <configData.configMap.length; i++)

{

...

var group:string = configData.configMap[i].group.toString();

...

}

Friday, February 27, 2009

What’s New in ArcGIS Server 9.3.1

I just returned from the ESRI Petroleum User’s Group (PUG) conference in Texas. The buzz this year was a little lower than those of an anticipated major release. The featured release during this gathering was 9.3.1. As I mentioned in a previous post, nary a word was mentioned regarding Desktop, it was all about “Web GIS.” Given my professional interest in this platform, this was ok with me. While many of the demos highlighted the various development platforms including the JS and FLEX API’s, a few included new features in 9.3.1. Probably the most anticipated, at least for AGS users, is increased performance for dynamic map serving. As far as I could tell, implementation of this new feature is actually done via a tool designed to help optimize the map document. The demo illustrating this improvement included a side-by-side comparison of the same dynamically generated map service, one that had been “optimized” using the new optimization tool and one that hadn’t. Each map display included a timer depicting load times. Anecdotally, map services which had been “optimized” using the new tool loaded about 3 times as fast. The optimization tool, utilized in ArcMap during the demo, looked at characteristics of the map document including whether the projection of the data frame matched that of the data, whether any data links were missing, scale dependent rendering, symbol level drawing and a couple of others that I missed. The workflow for tool use included an iterative process of optimization and map service preview. The demo was good and even generated a fair amount of applause. However, if faster dynamic map generation centers on checking the characteristics I listed above, don’t hold your breath. It seems to me that most folks are already looking at these sorts of things.


Other features mentioned but not demoed in the 9.3.1 release included the ability to publish to AGS directly from ArcMap and integration of Virtual Earth base data (not Google) directly into the ESRI platform including ArcMap. There was also some discussion about the new sharing framework via ArcGIS Online. While some may say “not another one” this one features content sharing and discovery definitely designed for a GIS pro and not so much for general consumers. Other notable discussions included AGX build 900 and the notion of what ESRI is calling a layer package (not sure if this is 9.3.1 or 9.4). The layer package is simply of was of packages data and cartography for sharing purposes.

Tuesday, February 24, 2009

2009 ESRI Petroleum User Group (PUG) Conference

Today is day two of the 2009 Petroleum User's Group conference. Yesterday featured the standard PUG fair including the usual ESRI plenary "dog and pony" show followed by some really good user presentations. Lead by Clint Brown, the tone of the plenary talks centered on "Web GIS." Highlights included ArcGIS 9.3.1 discussion, demos of the JS and FLEX APIs as well as some discussion about yet another sharing framework being designed via ArcGIS Online. To the dismay of a typically traditional GIS audience, it is clear that the focus of ESRI's R & D/future direction is "Web GIS." I'm not even sure if Desktop was even mentioned. The term "consumable" in the context of data and services was mentioned at least a dozen times with emphasis is user experience oriented towards the Google and VE patterns.

Thursday, February 12, 2009

JS vs Flex ArcGIS Server Sample Viewers

In recent weeks, ESRI has released 2 versions of a sample viewer application based on both their latest development platforms, the JS platform (released January 2009) and the Flex platform (released November 2008, updated February 2009). They both look and function similarly out of the box. Each features a icon oriented navigation bar based on various functional classes including maps, navigation, tools and resources. They both use REST based ArcGIS Server services both dynamically generated and cached very easily (although I was able to add ArcIMS Service Support to the Flex version without much hassle). Each features some pretty nice design patterns which allow developers to worry less about core functionality. Custom functions are implemented as "widgets" which function independently of the software core.

After tinkering with the Flex application for a few weeks and having a look at the JS version, I have a few impressions to share. First, they both use design patterns (Container Event Bus and Dependence Injection) that help decouple core functionality from custom functionality and really make it easy to extend. The flex viewer, based on Adobe's Opensource Flex 3.2 platform is very sexy and alleviates many cross-browser compatibility issues because of its required Flash plugin. Recently released as an opensource project, Flex offers a rich user experience with flashy graphical displays and fluid GUI performance. However, it requires an specific IDE based on the Eclipse IDE called Flex Builder which is rather pricey (ranging from $200.00 - $700.00). I have had the fortune of getting the IDE and have begun some "widget building" myself and have found it to be quite easy. I was able to construct a simple Map Navigation Widget in just a few days without any prior Flex development experience.While I haven't tinkered as much with the JS version, my initial impression is that it is also very slick and does not require a plugin. However, it's sex appeal is lacking a bit compared to the Flex version and it sounds as if (based on comments from the sample download blog) that it has some issues in IE 7.

Saturday, September 13, 2008

Basic Networking

The following slides are part 2/unit 1 of the Introduction To Geospatial Web Technologies course I teach @ University of Colorado @ Denver, Master's of Engineering in GIS Program.


History of Internet Mapping

The following slides are part one of unit 1 of the Introduction To Geospatial Web Technologies course I teach @ University of Colorado @ Denver, Master's of Engineering in GIS Program.



Masters Degree in GIS -- MEng-GIS

As adjunct faculty at the University of Colorado @ Denver, I would like to give a plug for our Master's of Engineering in GIS program. This program is one of a kind and provides extensive flexibility for working professionals and those seeking distance learning. All courses are offered inclass and online! I have been a part-time instructor for several years now and have taught Introduction to GIS as well Introduction to Geospatial Web Technologies. My current focus is the later. Have a look at the course overview/syllabus. In the coming weeks, I will be sharing selected portions of the course curriculum and would entertain any feedback. You can use anything that you wish as long as you cite these materials appropriately.