Login | Register   
LinkedIn
Google+
Twitter
RSS Feed
Download our iPhone app
TODAY'S HEADLINES  |   ARTICLE ARCHIVE  |   FORUMS  |   TIP BANK
Browse DevX
Sign up for e-mail newsletters from DevX


advertisement
 

Create a Map Client with Web Services, Part II

This project demonstrates how binding to web services with Flash Builder's data service tools can be a tremendous time saver.


advertisement
Part 1 of this series started a simple project to show how you can use Adobe Flash Builder 4 to rapidly develop a SOAP-powered map application called TerraClient. Using the new data service capabilities available in Flash Builder, you bound to MSR Map's web service and generated a rudimentary search form to utilize it. Now, you're going to dig deeper and use multiple asynchronous SOAP requests to display the tiled map imagery.

By the end of this article, you'll have a rudimentary map client and-more importantly-a solid understanding of how you can use web services with Flash Builder. Figure 1 shows what the finished product looks like.



Figure 1. Palo Alto, California, as viewed in TerraClient.

As with part 1, you will need Flash Builder version 4 build 2 or later to follow along with the coding steps in this article. You will also need the project source code from where we left off at the conclusion of part 1. If you don't have it, download terraclient_part1.fxp and perform the following steps to import the project into Flash Builder:
    1. Launch Flash Builder, and then click File > Import.
    2. Select Flash Builder Project as the Import Source, and then click Next.
    3. Select Import Project, and then browse to the location of terraclient_part1.fxp.
    4. Edit the Extract new project(s) to path, and remove the trailing _part1 from the project folder name. When you're done, the project path should end with \terraclient instead of \terraclient_part1.
    5. Click Finish.
Before you start coding again, let's take a look at a new tool in Flash Builder that is extremely useful when using SOAP services.

Step 1: Use the Network Monitor

It is practically a law of nature that when troubleshooting web services you'll need to see the raw Hypertext Transfer Protocol (HTTP) request and response messages at some point. Adobe has introduced the new Network Monitor tool inside Flash Builder so you can see exactly what's going back and forth between your project and the server.

If it isn't already visible, click Window > Network Monitor. At the top right of the window is the toolbar shown in Figure 2. Use these buttons to enable or disable the monitor, pause monitoring, clear the window, and save the monitoring results to an Extensible Markup Language (XML) file.

Figure 2. The Network Monitor window.

To see the monitor in action, perform the following steps:
    1. Click Enable Monitor.
    2. Run the TerraClient application in Debug mode by clicking Run > Debug TerraClient.
    3. When the TerraClient page loads in your browser, enter a search term in the form, and then click Get Placelist.
As the requests and responses go between TerraClient and the MSR Maps web service, you'll be able to view them in Network Monitor. You can switch between a raw view, a tree view (shown in Figure 2), and a hexadecimal notation view of the messages.

You won't be specifically using the Network Monitor from here on out. However, if you get stuck and need to see exactly what's going back and forth from the web service, the tool will certainly come in handy. The MSR Maps web services can be slow at times, so you can also use the monitor to see how long each response takes.

Step 2: Finish the Infrastructure

Before jumping into the code, you must identify all of the web service calls needed to retrieve map data for one of the search results. Figure 3 is a Unified Modeling Language (UML) sequence diagram that visualizes what will happen.

Figure 3. UML sequence of the web service calls made to MSR Maps TerraService

As shown in Figure 3, you've already handled the initial GetPlaceList call and the response of PlaceFacts. When you select one of those PlaceFacts, you have several more calls to make to assemble the map tiles related to the selection.

First, use the LonLatPt coordinates of the PlaceFacts to make a GetTileMetaFromLonLatPt request. The TileMeta response gives you the necessary data to then make a series of GetTile calls. The map display will be composed of nine tiles, so make nine GetTile requests. The response from the TerraService to each call will be an image transmitted as a byte array. The final GetTheme call will provide information on the type and source of the imagery.

Add new web service operations

In part 1, step 2, you connected to the TerraService Web Services Description Language (WSDL) file and bound to one of the web service operations called GetPlaceList. Now, add the operations shown in Figure 3 by performing the following steps:

1. On the Data/Services tab, right-click the TerraService2 node, then click Properties.
2. In the Web Service Properties window, select the GetTileMetaFromLonLatPt, GetTile, and GetTheme web service operations.
3. Click Finish.

Flash Builder creates objects to represent the new operations and request/response object data types. You can take a look at the results in the Project Explorer (look in /src/server) or on the Data/Services tab. Now that the new service objects are available, it is time to start using them to assemble the actual map in TerraClient.

Complete the SearchForm class

The SearchForm class in src/client/SearchForm.mxml displays the search result place names, but (so far) selecting one of the results doesn't do anything yet. You'll make it so that selecting a result invokes a handler function set by another class. Declare a new property inside SearchForm's script block to hold the handler, and add a placeList_clickHandler function used to invoke it:

/** Handler for when a PlaceFacts object is selected. */ [Bindable] public var select:Function; /** * Invoke select handler when a PlaceFacts object is selected. * * @param event  Click event from placeList. */ protected function placeList_clickHandler(event:MouseEvent):void { if(select!=null) { select.call(null, placeList.selectedItem); } }

To wire the handler to search result selection, add click="placeList_clickHandler(event)" to the search results List object. When you're done, it should look like this:

<!-- Search Results --> <s:List id="placeList" dataProvider="{GetPlaceListResult.lastResult}" labelFunction="placeLabel" width="590" height="70" color="#0000FF" textDecoration="underline" textAlign="center" borderVisible="false" click="placeList_clickHandler(event)" > <s:layout> <s:TileLayout horizontalAlign="center"  verticalAlign="middle"  columnAlign="justifyUsingWidth" /> </s:layout> </s:List>

This wraps up the SearchForm. Now comes the heart of TerraClient, where the map images are retrieved and displayed.

Step 3: Get the Big Picture

Thus far, the PlaceMap class in src/client/PlaceMap.mxml has been untouched. It is a subclass of the Group class and will hold nine map tile Image objects loaded from the web service. Note the 3×3 grid specified in the TileLayout definition:

<?xml version="1.0" encoding="utf-8"?> <s:Group xmlns:fx="http://ns.adobe.com/mxml/2009"         xmlns:s="library://ns.adobe.com/flex/spark"         xmlns:mx="library://ns.adobe.com/flex/halo"         xmlns:terraservice2="server.services.terraservice2.*" >      <s:layout>      <s:TileLayout horizontalGap="0" verticalGap="0"                    requestedColumnCount="3" requestedRowCount="3"/>   </s:layout>      <s:filters>      <s:DropShadowFilter />   </s:filters>      <fx:Script>      <![CDATA[      ]]>   </fx:Script>      <fx:Declarations>   </fx:Declarations>    </s:Group>

Note: A caveat before we continue: Putting service call code directly in SearchForm and PlaceMap has been done for the sake of keeping the TerraClient project simple. In a real project, I highly recommend that you follow good Model-View-Controller (MVC) practices, which would likely involve moving all of the service-related code to non-visual controller classes and keeping the view classes as "dumb" as possible.

Take what you learned from the generated code in Part 1 and create some of your own variations in PlaceMap.mxml to get the work done. For starters, add a declaration for the TerraService2 proxy in the Declarations section:

<fx:Declarations> <terraservice2:TerraService2 id="terraService2" showBusyCursor="true"/> </fx:Declarations>

You may recall that when you put SearchForm.mxml together, the generated search form also put a CallResponder instance in the declarations. You'll be using CallResponder instances in PlaceMap as well, but you'll create them programmatically as needed within Script block functions, instead. There are a number of bound properties to add to PlaceMap. These properties will be referenced in various places, so the simplest way forward is just to add them all now. Put these imports and properties in your Script block:

<fx:Script> <![CDATA[ import mx.controls.Image; import mx.rpc.CallResponder; import mx.rpc.events.*; import server.valueObjects.*;   /** The imagery theme to use.  Default to Aerial. **/ [Bindable] public var theme:int = 1;   /** The scale to use.  Default to 16 meters. **/ [Bindable] public var scale:String = "Scale16m";   /** The current status message as the map tiles load. */ [Bindable] public var status:String = "";   /** The current TileMeta object retrieved. */ [Bindable] public var currentTile:TileMeta;   /** The current ThemeInfo retrieved. */ [Bindable] public var currentTheme:ThemeInfo;   /** Internal counter for tiles remaining to be loaded. */ protected var remaining:int; ]]> </fx:Script>



Comment and Contribute

 

 

 

 

 


(Maximum characters: 1200). You have 1200 characters left.

 

 

Sitemap