Build a Simple Map Client with SOAP in Flash Builder 4, Part I

Adobe Flash Builder (formerly Adobe Flex Builder) introduces a powerful new set of tools for using remote data services. Of particular interest is Flash Builder’s support for SOAP (Simple Object Access Protocol) web services, as SOAP is both a mainstay and a frequent source of headaches in the software industry. The new data service tools in Flash Builder natively automate enough of the grunt work that using a SOAP web service is almost trivial.

This two-part series (see Part 2) shows how to use Flash Builder to rapidly build a SOAP-driven map search application called TerraClient. Part 1-this article-shows how to automatically bind to SOAP services, generate a search form, and handle the initial search results. Part 2 will show you how to handle the multiple asynchronous SOAP requests and responses needed to display the map imagery. Figure 1 shows the finished product.

Figure 1. TerraClient: A map client of SOAP web services built with Flash Builder.

To get map data and imagery for TerraClient, you’ll use the public TerraService web service hosted on MSR Maps. The data center behind MSR Maps is owned and operated by Microsoft, but the map data and imagery are provided by the U.S. Geological Survey. The website — formerly TerraServer USA — provides a well-documented set of public SOAP web services that you can call directly from Flash Builder.

To run the code used in this article, you need Flash Builder version 4 build 2 or later. If you haven’t installed it yet, I recommend getting the Flash Builder 4 Standalone Installer instead of the Flash Builder 4 Plug-in for Eclipse. When Flash Builder is installed and ready to go, you’re only a few minutes away from using a SOAP web service.

Step 1: Initial Project Setup

Skipping the initial project setup and getting right to the good stuff, begin by downloading terraclient_initial.fxp. Then, import the file 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_initial.fxp.

    4. Edit the Extract new project(s) to path, and remove the trailing _final from the project folder name. When you’re done, the project path should look like

    …/terraclient instead of …/terraclient_initial.5. Click Finish.

You should now have a basic Flex project-four basic components with some minimal user interface (UI) scaffolding-loaded and ready to use. Here are the components:

    * src/TerraClient.mxml. This is the application entry point. For this project, its role is simply to assemble the other components.

    * src/client/SearchForm.mxml. This file contains a search form used to query the TerraService for a list of location names. It also holds the list of locations that the query returns.

    * src/client/ImageOptions.mxml. This utility class simply provides two drop-down menus to specify the kind of map imagery desired.

    * src/client/PlaceMap.mxml. This component is the workhorse that assembles the map tile images. You’ll use what you learned from the Flash Builder-generated code in Search Form to create programmatic variations in the PlaceMap component.

Step 2: Connecting to the SOAP Service

In this step, you use Flash Builder’s Data Service tools to connect to the web service, then generate a service proxy with its related value objects.

From the Flash perspective, click Window > Open Perspective > Flash. Your window configuration should look similar to Figure 2.

Figure 2. The initial SearchForm.mxml file as viewed in the Flash perspective.

Take a look at the Data/Services tab at the bottom of your window. You’ll use this tool to connect to the TerraService Web Services Description Language (WSDL) file and create a local proxy for the GetPlaceList operation.

Click the Connect to Data/Service link to open the wizard. Then, perform the following steps:

1. Select the Service Type: “Web Service” option, and then click Next.

2. Specify WSDL to Introspect:

    * Keep the default option to access the web service directly from the client.
    * In the WSDL URI field, enter the WSDL location for TerraService (http://msrmaps.com/TerraService2.asmx?WSDL).
    * Service name: Keep the default value of TerraService2.
    * Service package: Type server.services.terraservice2 to put the Service proxy classes into a top-level server package.
    * Data type package: Type server.valueObjects to place the value objects package within the top-level server package.

3. Click Next.

4. The Configure Code Generation wizard step shows all of the operations available in the TerraService WSDL file. For now, keep things simple:

    * Clear all of the web service operations with the Deselect All button
    * Select the GetPlaceList operation, and then click Finish.

As the wizard closes, Flash Builder generates code for the TerraService2 proxy, the GetPlaceList operation, and the value objects used in both the request and the response. The items on the Data/Service tab, shown in Figure 3, provide a logical view of the data types and operations related to the newly generated TerraService2 proxy. There is also a new /src/server package in the Package Explorer with all of the generated source code.

Figure 3. The new service object and value objects generated using WSDL.

Step 3: Generate the Search Form

With the service and value objects generated, you are going to generate a search form for the GetPlaceList operation. This form lets users type a place name, submit it to the web service, and get back a list of matching places. You will then add a List component to display the search results.

To get started, open /src/client/SearchForm.mxml. There’s basically nothing in the file yet, but that’s about to change. Return to the Data/Service panel, and then open the logical tree under TerraService2. Right-click the GetPlaceList operation, and then click Generate Form (see Figure 3). The form generated will be inserted into the SearchForm.mxml component.

In the Generate Form wizard, perform the following steps:

1. Configure the wizard options:

    * Generate form for: Keep the Service call default.
    * New Service Call: This option should be selected.
    * Service: Keep the TerraService2 default.
    * Operation: Keep the GetPlaceList default.
    * Create: Select Form for input parameters, but clear the Form for return type option. Because GetPlaceList returns an array of PlaceFacts, generating a form for the return type isn’t useful. You’ll handle displaying the search results using a List.

2. Click Next.

3. On the Property Control Mapping wizard page, keep the defaults, and then click Finish.

Examine the Generated Form

When the wizard finishes, SearchForm.mxml will be augmented with the generated form, a function in the Script block to handle the Submit button, and two object instances in the Declarations block. Let’s start with a quick look at the form:

         
             
 
   

Each input parameter for TerraService's GetPlaceList operation has a corresponding form item:

    * In the placeNameTextInput field, users type a location/land name like "Denver, CO" or "Statue of Liberty, New York."
    * The maxItemsTextInput field is used to specify an upper limit of places returned in the search results.
    * The imagePresenceCheckBox indicates whether to limit the search results to places with available imagery.

For the sake of your own testing convenience, I recommend that you set a default value on the latter two form items. Add text="5" to the maxItemsTextInput and selected="true" to the imagePresenceCheckBox. Eventually -- when you're done experimenting -- you may want to hide these two form inputs altogether. Add visible="false" and includeInLayout="false" to both components' to hide them away with minimal refactoring. The project available for download at the end of this article has a more aesthetic version of this form, as well.

Examine the Generated Declarations

The declarations block in SearchForm.mxml has two new instances inserted by the form generator:

         
     
  

The instance of the TerraService2 service is a local proxy object that the Connect to Data/Service Wizard generates. When GetPlaceList is called, a non-blocking SOAP request is sent to the remote TerraService. The method itself immediately returns a callback token that is populated when the asynchronous response occurs. (If you're familiar with Asynchronous JavaScript and XML [Ajax] concepts, this is old hat.)

The fault attribute on the TerraService2 instance is set to handle any error responses with a generic alert. The showBusyCursor attribute is a convenient mechanism for reminding users that a response is still pending.

Right-click the TerraService2 class, and then click Go to Definition. Note that Flash Builder leaves this empty subclass as a place for customized behavior. Go to the definition of the super class reference _Super_TerraService2 to see where the real service-specific code has been generated.

Scroll down to the definition for the GetPlaceList method. The comment block is extremely informative, describing how the method should be used:

/** This method is a generated wrapper used to call the 
'GetPlaceList' operation.
It returns an AsyncToken whose result property will be populated with the result of
the operation when the server response is received. To use this result from MXML code, define a CallResponder component and assign its token
property to this method's return value. You can then bind to CallResponder.lastResult or listen for the CallResponder.result or fault [email protected] [email protected] mx.rpc.CallResponder @return an AsyncToken whose result property will be populated with the result of the operation when the
server response is received. */          public function GetPlaceList(placeName:String, MaxItems:int,                       imagePresence:Boolean) : AsyncToken { ? }

Returning to the generated declarations in SearchForm.mxml, below the TerraService2 declaration is a CallResponder instance. This instance will be populated when TerraService responds to the request. This operation is done in the generated Script block, so that's where we should look next.

Examine the Generated Script

The Script block in SearchForm.mxml now contains a simple function that is called when users click Search:

protected function button_clickHandler(event:MouseEvent):void{  GetPlaceListResult.token = terraService2.GetPlaceList(                placeNameTextInput.text,               parseInt(maxItemsTextInput.text),               imagePresenceCheckBox.selected);}

When the button_clickHandler is invoked, the TerraService2 instance's GetPlaceList method is called with input values from the form. The return AsyncToken value is set on the GetPlaceListResult call responder. To display the search results, simply use the lastResults property on GetPlaceListResult as the data provider for a List.

To display the search results, use a simple list and assign the data provider to the lastResults property on GetPlaceListResult. Add the component shown here below the
in SearchResults.mxml:

        

The heart of this component is really just a List with a dataProvider and a labelFunction. The rest of the attributes and the layout are there for aesthetic reasons.

A custom labelFunction is needed, because the search results are an array of PlaceFacts value objects. (These were generated when you used the Connect to Data/Service Wizard.) They don't have a useful toString() method, so provide a simple placeLabel function. Add the following function to the Script block in SearchForm.mxml:

protected function placeLabel(value:Object):String {  return value._Place.City + ", " + value._Place.State;}

The TerraService uses the City attribute on a Place object to hold either an actual city name or a landmark name. So, the computed label will work for equally well for "Denver, Colorado" and "Statue of Liberty, New York."

Try it out

So far, you've connected to the web service, generated a search form, and added a List component to display the results. It is time to try it out for yourself:
    1. Click Run > Run to build and run the TerraClient project.
    2. If the Run As window appears, select the Web Application option. Click OK.
When the TerraClient loads in your web browser, you'll see the search form. Enter a city and state in the PlaceName field. If you didn't specify a default value in the form for MaxItems, you'll need to enter a number between 1 and 100, inclusive. Figure 4 shows what the form and search results look like when searching for "San Jose, CA" with the initial TerraClient.

Figure 4. The search form in action

Wrapping Up

The new tools available in Flash Builder handle a lot of the grunt work needed to use remote SOAP web services. Once you get familiar with the wizards introduced in this article, you can probably get through every step thus far in less than 5 minutes. More importantly, you've started to see what's behind the "magic" and how to use it for your own projects.

For your convenience, you can download and import a version of the project so far: terraclient_part1.fxp. You can use it to check against your own work to make sure everything is correct thus far.

TerraClient isn't finished just yet, however. In part 2, you'll need to use one of the search results to build a tiled map display. You'll use what you've learned in here to make multiple asynchronous SOAP requests and handle the results.

Share the Post:
Share on facebook
Share on twitter
Share on linkedin

Overview

Recent Articles: