Centralizing Web Service Access


In these next tasks you will create an ActionScript class that will act as a central point in which you can mange all your Web Service calls in the DataEntry application. You will go back to the DataEntry.mxml and use a new Management class to enable you to update and delete a product.

The DataManager simplifies the interaction with the <mx:WebService> tag by giving you one class that you can get a WebService object to call your methods against. By having your code in one place that creates the Web Services, you can guarantee that every object is created the same. Be aware that this section is a brief review of some advanced functionality of Flex. Because many topics will be new, do not worry if you need some real life project to work with in order to fully understand how this works. That being said you may want to use the DataManager in the real life applications you build.

1.

If you have not done so already, start your local ColdFusion server.

2.

Copy DataManager.as into the managers directory.

The file to copy is located in the Lesson17/assets directory.

3.

Open DataManager.as and review.

4.

Review the DataManager() constructor.

public function DataManager(pri:PrivateClass, wsdl:String){    this.ws = new WebService();    ws.wsdl = wsdl;    ws.loadWSDL(); } 


This function is responsible for creating the WebService object that the DataManager uses. It has a public attribute called ws that holds the reference to the WebService object it created. The constructor expects a WSDL file to be passed in along with a PrivateClass object. This PrivateClass definition is located at the bottom of the file with the following definition:

/* PrivateClass is used to make DataManager constructor private */ class PrivateClass{    public function PrivateClass(){} } 


Tip

This PrivateClass class is defined at the bottom of the DataManager file and is marked as private. This is a quick technique to make sure that each DataManager created must be done via a static method on the DataManager. That is the only area of the application that can access the private class due to Flex's scoping rules. This is the key way to force a Singleton pattern in Flex.

5.

Review the static function getdataManager().

public static function getDataManager(wsdl:String):DataManager{    if(DataManager.instanceMap[wsdl]== null){       DataManager.instanceMap[wsdl] = new DataManager(new PrivateClass(),wsdl);    }    var dm:DataManager = DataManager.instanceMap[wsdl];    if(dm.ws.canLoadWSDL())       {return dm;}    else       {throw new Error("BAD WSDL:"+wsdl);} } 


This function acts as the only way that you can create new DataManager objects. You will create one DataManager object per unique Web Service by using the WSDL filename as the unique key into the static instanceMap object. Because instanceMap is a static variable on the class itself, there will be only one variable for the whole application. This means that every time this getdataManager() is called, it will check to see whether there was ever a WebService with that WSDL file called before. If so, it will use that instance.

6.

Review the makeRemoteCall() function.

public function makeRemoteCall(methodName:String,eventName:String, args:Object):void{    trace("DataManager.makeRemoteCall("+methodName+","+eventName+","+args+")");    var op:mx.rpc.AbstractOperation = ws[methodName];    ws.addEventListener("result",doResults);    ws.addEventListener("fault",doFault);    if (args){       op.arguments = args;    }    var token:AsyncToken = op.send();    token.eventName = eventName; } 


This method uses the argument property of the AbstractOperation to generically pass arguments to a operation on the Web Service. These generic arguments are in an object structure with the key names equal to the parameter names specified by the Web Service. The function is called on the DataManager object to initiate a call to the method, specified by methodName, on the Web Service and raises an event on the DataManager, specified by eventName, upon the successful call to the Web Service. The raised event is of type DataManagerResultEvent event. Effectively, it will call whatever method you specify, passing it the parameters in the accompanying object and raising the specified event when successful.

7.

Copy DataManagerResultEvent.as into the events directory.

The file is copy is located in the Lesson17/assets directory.

8.

Open DataManagerResultEvent.as and review.

9.

Review the DataManagerResultEvent() constructor.

public function DataManagerResultEvent(type:String,result:Object){    super(type);    this.result = result; } 


This event class has only one attribute on it: result. This is used as a pass through of what the result was from the original Web Service call. The constructor first specifies the event name to raise via the type argument and then the result that came back from the Web Service.

10.

Open the views/dataEntry/UpdateDeleteProd.mxml file.

The file is located in the flexGrocer/views/dataEntry directory.

11.

Below the import, declare a public variable named prodID that will hold the reference of the identity of the product used by the component. Make it of type int and make it Bindable.

[Bindable] public var prodID:int; 


Earlier, you added a prodID attribute to the Product value object. You need to update the UpdateDeleteProd component to be aware of the prodID of the Product value object it is working with.

12.

In the populateForm() function, set the prodID attribute from the node using selectedNode.@prodID. Do this right after you check to make sure that the selectedNode.@prodName is not undefined.

if(selectedNode.@prodName != undefined){    prodID = int(selectedNode.@prodID); 


13.

Add a new tag to the prodModel model called prodID. Bind the value equal to public variable prodID.

<mx:Model >    <prodID>{this.prodID}</prodID> 


The model is built into a Product value object before it is passed out of the component through a ProductEvent. By adding this tag, you will set the prodID of the value object.

14.

Save the UpdateDeleteProd.mxml file.

15.

Open the DataEntry.mxml file.

The file is located in flexGrocer directory.

16.

Inside the script block, add an import for the managers.DataManager and events.DataManagerResultEvent classes.

import managers.DataManager; import events.DataManagerResultEvent; 


17.

Create a private function called updateProduct(). Have it accept one argument called product of type Product.

private function updateProduct(product:Product):void{ } 


18.

Create a local variable called dm of type DataManager. Set it equal to a new DataManager that is created through the static method DataManager.getDataManager(). Use http://localhost:8300/flexGrocer/cfcs/ProductManager.cfc?wsdl as the wsdl to get the Web Service.

[View full width]

private function updateProduct(product:Product):void{ var dm:DataManager = DataManager.getDataManager ("http://localhost:8300/flexGrocer/cfcs /ProductManager.cfc?wsdl"); }


This will be the instance of the DataManager that you call the method on which to update the product.

19.

Assign an event listener on dm object that listens for the updateProductResult event. Have it call the updateProductResult() function.

[View full width]

private function updateProduct(product:Product):void{ var dm:DataManager = DataManager.getDataManager("http://localhost:8300/flexGrocer/cfcs /ProductManager.cfc?wsdl"); dm.addEventListener("updateProductResult", updateProductResult); }


20.

On dm, call the makeRemoteCall() method. For the first argument pass in a string of updateProduct, which specifies the appropriate method to call on the Web Service. Next, pass in a string of updateProductResult, which will cause the DataManager to raise an event of the same name upon success. Lastly pass in a new object, created inline, which contains the product argument passed into the updateProduct method as a property called aProduct.

[View full width]

private function updateProduct(product:Product):void{ var dm:DataManager = DataManager.getDataManager("http://localhost:8300/flexGrocer/cfcs/ ProductManager.cfc?wsdl"); dm.addEventListener("updateProductResult", updateProductResult); dm.makeRemoteCall("updateProduct", "updateProductResult", {aProduct:product}); }


21.

Create a private function called updateProductResult() that accepts one argument called event, of type DataManagerResultEvent.

private function updateProductResult(event:DataManagerResultEvent):void{ } 


22.

Show the pop-up window with results using the showPopUp() function. You will need to use the Product.buildProduct() method to take the result of the call to the server and create a new Product from the event.result.

private function updateProductResult(event:DataManagerResultEvent):void{    showPopUp(Product.buildProduct(event.result),'Product Updated'); } 


The result from the Web Service is an Object that you pass to the buildProduct() function. It will create a new product with the data returned.

23.

Call the refetchData() function on prodMgr to have it go to the server to get the updated XML file.

private function updateProductResult(event:DataManagerResultEvent):void{    showPopup(Product.buildProduct(event.result),'Product Updated');    prodMgr.refetchData(); } 


Once again, you will just refresh the Tree component by going back to the server to get the latest XML of the products.

24.

On the UpdateDeleteProd component, change the productUpdate event to call the updateProduct() function. Have it pass the event.product it receives along to this function as the argument.

productUpdate="updateProduct(event.product)" 


25.

Create a private function called deleteProduct(). Have it accept one argument called product of type Product.

private function deleteProduct(product:Product):void{ } 


26.

Create a local variable called dm of type DataManager. Set it equal to a new DataManager that is was created through the static method of DataManager.getDataManager(). Use http://localhost:8300/flexGrocer/cfcs/ProductManager.cfc?wsdl as the wsdl to get the WebService.

[View full width]

private function deleteProduct(product:Product):void{ var dm:DataManager = DataManager.getDataManager("http://localhost:8300/flexGrocer/cfcs /ProductManager.cfc?wsdl"); }


This will be the instance of the DataManager class that you will use to update the product.

27.

Assign an event listener to dm that listens for the deleteProductResult event. Have it call the deleteProductResult() function.

[View full width]

private function deleteProduct(product:Product):void{ var dm:DataManager = DataManager.getDataManager("http://localhost:8300/flexGrocer/cfcs /ProductManager.cfc?wsdl"); dm.addEventListener("deleteProductResult", deleteProductResult); }


28.

On dm, call the makeRemoteCall() method. For the first argument pass in a string of deleteProduct, which specifies the appropriate method to call on the Web Service. Next, pass in a string of deleteProductResult, which will cause the DataManager to raise an event of the same name upon success. Lastly, pass in a new object, created inline, which contains the product argument passed into the updateProduct method as a property called aProduct.

[View full width]

private function deleteProduct(product:Product):void{ var dm:DataManager = DataManager.getDataManager("http://localhost:8300/flexGrocer/cfcs /ProductManager.cfc?wsdl"); dm.addEventListener("deleteProductResult", deleteProductResult); dm.makeRemoteCall("deleteProduct", "deleteProductResult", {aProduct:product}); }


29.

Create a private function called deleteProductResult() that accepts one argument, called event, of type DataManagerResultEvent.

private function deleteProductResult(event:DataManagerResultEvent):void{ } 


30.

Show a popup window with the results using the showPopUp() function. You will need to use the Product.buildProduct() method to take the result of the call to the server and create a new Product from the event.result.

private function deleteProductResult(event:DataManagerResultEvent):void{    showPopUp(Product.buildProduct(event.result),'Product Deleted'); } 


The result from the Web Service is an Object that you pass to the buildProduct() function that will create a new product with the data returned.

31.

Call the refetchData() function on prodMgr to have it go to the server to get the updated XML file.

private function deleteProductResult(event:DataManagerResultEvent):void{    showPopup(Product.buildProduct(event.result),'Product Deleted');    prodMgr.refetchData(); } 


Once again you will just refresh the Tree component by going back to the server to get the latest XML of the products.

32.

On the UpdateDeleteProd component, change the productDelete event to call the updateProduct() function. Have it pass the event.product it receives along to this function as the argument.

productDelete="deleteProduct(event.product)" 


33.

Save DataEntry.mxml and run the application. Click a product from the Tree component. Change the name of the product and press Update. You will see the new product name in the Tree component.

When you run the DataEntry and update a product's name, you should see the following figure after you expand the Tree component.




Adobe Flex 2.Training from the Source
Adobe Flex 2: Training from the Source
ISBN: 032142316X
EAN: 2147483647
Year: 2006
Pages: 225

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net