| By Darron J. Schall | Article Rating: |
|
| March 31, 2005 12:00 AM EST | Reads: |
23,994 |
In Part One (MXDJ, vol. 3 issue 2) we looked at one of three different ways to consume a Web service, here we look at two other ways and some of the pros and cons of each approach.
In this next example we'll explore using data binding in a different way from Pt. 1, by not relying on the Bindings tab of the Component Inspector panel. Instead, we'll create the bindings through ActionScript.
Example 2 - Creating Bindings Through ActionScript
To work through this example, we'll build the interface the exact same way as the previous example, leaving out the "add binding" steps. Either rebuild the interface following the previous instructions or take your complete Example 1 from Pt. 1 and simply remove the bindings on the components (by clicking the minus icon in the Binding tab).
Before we get to the ActionScript that needs to be written on the actions layer, first we'll examine the two classes that make data binding possible. Flash MX 2004 Professional includes the mx.data.binding.Binding class that does all of the heavy lifting. It uses a helper class mx.data.binding.EndPoint that is used to define the source and destination for the binding bridge.
The Binding constructor takes a source EndPoint that supplies the property to be bound, and a destination EndPoint that determines where that property is transferred to. Optionally, we can assign a formatter to transform the property from the source before it arrives at the destination. We can also optionally specify the binding as being two-way. Formatters and two way bindings are left as exploration pieces - discovery is a great learning mechanism.
An EndPoint is an object consisting of three main properties: component, property, and event. The "component" property of an EndPoint instance is a reference to the component the binding applies to, and the "property" property is a string defining what property is being bound or bound to. The "event" property is usually only necessary for "source" EndPoints, and is typically set to either "change" or "result." The "event" property can either be a single event as a string, or an array of events if multiple events are required.
Creating a new Binding instance and passing it a source and destination EndPoint is enough to get binding to work. Use the following two code blocks on the "actions" layer of the movie to hook up the data binding through script.
import mx.data.binding.Binding; import mx.data.binding.EndPoint; // bind the msg_ta text area to the msg parameter of the web service connector var src = new EndPoint(); src.component = msg_ta; src.property = "text"; src.event = "change"; // event is either a single event string, or an array of event strings var dest = new EndPoint(); dest.component = msg2morse_wsc; dest.property = "params"; dest.location = ["msg"]; // this binds to params.msg // creating the binding is as simple as this: new Binding(src, dest);
Alternatively, we can pass anonymous objects to the Binding constructor, bypassing the need for the EndPoint helper class. This makes for more compact code, although its readability can be argued to be either better or worse depending on your point of view.
// bind the result of the msg2morse_
wsc to the text of the morse_ta
new Binding({component:msg2morse_wsc,
property:"results", event:
["result"]},
{component:morse_ta,
property:"text"});
// bind morse_ta text to the msg
parameter of the morse2msg_wsc
new Binding({component:morse_ta,
property:"text", event:["change"]},
{component:morse2msg_
wsc, property:"params",
location:["Morse"]});
// bind the result of the morse2msg_
wsc to the text of the msg_ta
new Binding({component:morse2msg_wsc,
property:"results",
event:["result"]},
{component:msg_ta,
property:"text"});
// wire the buttons
msg2morse_btn.onRelease = function() {
msg2morse_wsc.trigger();
}
morse2msg_btn.onRelease = function() {
morse2msg_wsc.trigger();
}
In the first portion of the code, notice that we explicitly create an EndPoint for both the source and the destination. In the remaining code things are done a little different because using the EndPoint helper class is not a requirement. Rather, as long as we pass an object with the appropriate properties, the Binding class still functions correctly. With this in mind, we leverage anonymous objects to define the source and destination for the binding. Doing so makes the code more concise though it may or may not increase readability as that is a matter of personal opinion.
The only other interesting thing to note in the code is the additional use of the "location" property. If the "property" property of the component is complex (that is, not a simple value like 1 or "hello"), the "location" property points to the data field in the complex "property" object. In the example, the "param" property of the web service connector is an object and therefore complex, so we use "msg" as the "location" property in order for the Binding class to find the param.msg data field correctly.
Now, again, test the movie and see the magic. We've achieved the exact same results but instead of the "jungle code" approach of the Bindings tab, we've consolidated all of the binding code in one location. This makes the "magic" aspect a little bit more obvious, and should allow for easier updates in the future. Having a single location to look for certain information is a boon.
Like Example 1 in Pt 1, however, Example 2 is has a dark side as well. There's still a "magic" factor surrounding the web service connector supplied by Macromedia, and data binding adds a lot of unnecessary overhead behind the scenes. The former may not be that much of a concern, but if performance is paramount than the use of data binding needs to be reevaluated.
"But Darron, this article is about data binding, and now you're telling us not to use it?" Correct, sort of. Data binding has its place, but here's what you probably didn't know: every time you type a letter into the message area, a "change" event is generated because the "text" property has been changed; because of this, the glue that is data binding will update the parameter of the web service connector to be the text contained in the text field to keep them in sync.
While this doesn't sound like that big of a deal, consider the following scenario. Imagine typing the simple 4 letter word "test." In doing so, we've generated 4 change events, and set the "msg" parameter of the web service connector to be "t," "te," "tes," and finally "test." What a waste of time! In our case, we only care what the value of the text is when we invoke the web service because that is the only time the value is actually used. Instead of 4 calls, we really only need to make one.
Imagine, now, typing the above paragraph into the message area. Around 400 change events would have been generated, results in over 400 separate assignments, when, as previously stated, only one is required. Not just assignments, either. Don't forget about the overhead behind the scenes in dispatching and handling those change events. This wasteful aspect of data binding can be a major thorn in the side, especially when performance is on the line on slower client machines.
In reality, the wastefulness may not have a profound impact on your application. You may find that the benefits of binding outweigh the cost of using it. However, for those that want a more streamlined approach (sans data binding and web service connector "magic"), one final example needs to be gone through.
Example 3 - Not Using the Web Service Connector or Data Binding
In this last example we'll explore building the same application but without any relying on the web service connector and without the aid of data binding. This is somewhat of a code purist approach and is for those who like being closer to the underlying code.
For this example, start with a blank document and construct the interface almost exactly the same as before. Create two text areas and two buttons on an "interface" layer, give the components the appropriate instance names (msg_ta, morse_ta, msg2morse_btn, morse2msg_btn), and position and size them on the stage accordingly. Leave out the web service connectors since this example doesn't use them.
This next step is very important. By default, the classes needed to access web services are not included in all .swf files. In order to include these classes and leverage their functionality, we need to add them in the following manner.
From the menu bar, select Window -> Other Panels -> Common Libraries -> Classes. Drag the "WebServiceClasses" from the library that opens up onto the stage of your Flash document. Finally, delete the instance on the Stage that you just created. What just happened was that we added the web service classes to the library of our new movie, and by default they will now be included in our published .swf. At this point we can leverage the web service functionality through code. All that's left to do is put the following code on the "action" layer:
import mx.services.WebService;
import mx.services.PendingCall;
var morse_ws:WebService = new
WebService("http://web221.
area-18.server-home.net/Morse.
asmx?WSDL");
msg2morse_btn.onRelease = function() {
// calling a web service method
returns a PendingCall
var pc:PendingCall = morse_
ws.MsgtoMorse(msg_ta.text);
pc.onResult = function(result) {
morse_ta.text = result;
}
pc.onFault = function(fault) {
trace("msg2morse fault: " + fault.
faultString);
}
}
morse2msg_btn.onRelease = function() {
var pc:PendingCall = morse_
ws.MorsetoMsg(morse_ta.text);
pc.onResult = function(result) {
msg_ta.text = result;
}
pc.onFault = function(fault) {
trace("morse2msg fault: " + fault.
faultString);
}
}
In the code above we create a reference to the web service by passing in the WSDL location to the WebService constructor. Then, whenever a button is pressed we call the appropriate method and save a reference to the PendingCall instance it creates. Finally, the "pc" has two special methods that get invoked when either the results come back successfully (calling "onResult") or when an error occurs (calling "onFault").
Summary and Final Thoughts
As you can see, there is more than one way to accomplish a task. We've built the same application in three distinct ways, each with their pros and cons.
The first example requires the least amount of code. Data binding is leveraged through the Bindings tab in the Component Inspector panel, and two WebServiceConnectors control access to the remote web service.
The second example improves upon the first by placing all of the Data Binding code in a single location, but has the negative side effect of requiring more "hand coding."
The last example is the "down and dirty" approach that uses the WebService and PendingCall classes directly without the need for the WebServiceConnector, and rids us of the wasteful aspect of using data binding.
Each example can be the "right" way to code something, depending on the application requirements and the person doing the coding. I'm a fan of the last example, but you're welcome to disagree.
From here, I encourage you to explore the further reading links. Find a web service that interests you and try building a small application that uses it. Who knows, you might even surprise yourself!
Further Reading
Published March 31, 2005 Reads 23,994
Copyright © 2005 SYS-CON Media, Inc. — All Rights Reserved.
Syndicated stories and blog feeds, all rights reserved by the author.
More Stories By Darron J. Schall
Darron J. Schall, an Editorial Board member of Web Developer's & Designer's Journal, has been programming long before he could drive. In school he studied programming languages, ranging from Basic to Pascal to C++ and eventually moving into Java and C# throughout college. Somewhere in the middle he got hooked on Flash 5 and it's been a crazy love affair ever since. Darron is an independent consultant specializing in RIA development. He maintains a Flash Platform related weblog (www.darronschall.com) and is an active voice in the Flash and Flex communities.
- Ulitzer.com Named Exclusive "New Media" Sponsor of Cloud Computing Conference & Expo
- Adobe’s Aiming ColdFusion at Multiple Clouds
- Cloud Executives Feature on Cloud Computing Expo Power Panel
- Cloud Computing Journal: Adobe to Deliver ColdFusion in the Cloud
- Adobe Reader Sued
- Adobe Unveils LiveCycle Enterprise Suite 2 for Deployment in the Cloud
- Adobe May Cooperate with Apple to Transplant Flash Player to iPhone
- Ph.D. in Twitter Anyone?
- Adobe Flex Developer Earns $100K in New York City
- Eolas Sues the Internet
- Adobe LiveCycle Enterprise Suite 2 for Cloud Computing
- Special Report on the Emerging Cloud Computing Trend
- My Thoughts on Ulitzer
- Ulitzer.com Named Exclusive "New Media" Sponsor of Cloud Computing Conference & Expo
- Ulitzer Live! New Media Conference & Expo
- Adobe’s Aiming ColdFusion at Multiple Clouds
- Eval JavaScript in a Global Context
- Fig Leaf Software to Exhibit at Government IT Conference & Expo
- Cloud Executives Feature on Cloud Computing Expo Power Panel
- Software Flexibility in the Cloud - Part 4 of 5
- Is Microsoft as Free as Open Source?
- Cloud Computing Journal: Adobe to Deliver ColdFusion in the Cloud
- Adobe Reader Sued
- Adobe Unveils LiveCycle Enterprise Suite 2 for Deployment in the Cloud
- Where Are RIA Technologies Headed in 2008?
- Cover Story: How to Increase the Frame Rates of Your Flash Movies
- AJAX World RIA Conference & Expo Kicks Off in New York City
- Your First Adobe Flex Application with a ColdFusion Backend
- Adobe Flex 2: Advanced DataGrid
- i-Technology Blog: Death-Knell For "Rich Media? Hardly!
- Adobe/Macromedia - Microsoft, Look Out!
- How To Create a Photo Slide Show ...
- Adobe Flex Interface Customization - Themes, Styles, Skins
- Personal Branding Checklist
- Has the Technology Bounceback Begun?
- "Real-World Flex" by Adobe's Christophe Coenraets

































