|
SYS-CON.TV Webcasts
Comments
Did you read today's front page stories & breaking news?
SYS-CON.TV
|
Top Links You Must Click On
ColdFusion Integrating Flash MX 2004 and ColdFusion MX 6.1 with Web Services
Integrating Flash MX 2004 and ColdFusion MX 6.1 with Web Services
By: Curtis Hermann
Apr. 7, 2004 12:00 AM
This is a very good time to be a Web application developer. Over the years we have moved from complex and proprietary methods of sharing data, to a more standardized and easy-to-implement method of exchanging simple or complex objects over the Web.
Though nothing is perfect, data transfer via Web services is much more standardized and hasbeen made more simple than anything we have had in the past. Web services allow us to not only share data but to share complex data. With Web Services you can send and receive objects that range from simple numbers to record sets. This is accomplished by defining interfaces and by passing data back and forth in XML format. Both ends of the communication pipe know how to translate the XML to native objects, like a String or Array. Since the data is defined with XML, it is platform independent. As long as this data adheres to the shared standard, multiple applications can communicate and know nothing about the other's technology. This is a very powerful distributed computing world that has existed since the inception of the World Wide Web. You cannot only share data between different components of one application, but can make it available for others to grab, like the latest-breaking news from your Web site or stock quotes. The standard used in the technologies discussed within this article is a protocol called Simple Object Access Protocol (SOAP). SOAP has taken the lead in messaging standards. Furthermore, Macromedia, along with other technology giants like IBM, Microsoft .NET, and others, has decided to adopt SOAP with the new set of data components and Web services classes.
What About Flash Remoting? For those of you who don't know much about Flash Remoting, it is a technology that is used in the same way as SOAP Web services, but is proprietary to Flash MX+ applications. Flash Remoting is a Macromedia technology, whereas SOAP is an open standard. One advantage that Flash Remoting has over SOAP, is that it is sent in binary format so that it is much more efficient and "lighter weight." SOAP, on the other hand, is very verbose in its object descriptions and can be much slower than Flash Remoting when returning large results; this is because SOAP is based on passing XML strings between machines. A disadvantage of Flash Remoting is that it is not free - kind of. You either need to purchase it for your server (for "pure" Java or .NET), or be running on a ColdFusion MX+ or JRun 4+ platform. Also, at the time of this writing, Flash Remoting is still written in ActionScript 1.0 while the Web service classes and data components in Flash MX 2004 are written in ActionScript 2.0. So, if you are into developing strictly ActionScript 2.0 applications, and you use Flash Remoting, you will need to still use ActionScript 1.0 syntax to include the libraries into your application. However, Macromedia promises that a new version written in ActionScript 2.0 is coming soon. I look forward to this release. I myself have written many applications using Flash Remoting and enjoy the technology very much and encourage others to explore and work with it as well.
Web Services, Flash MX 2004 and ColdFusion MX 6.1 The same happens in reverse. Flash knows nothing about ColdFusion CFML and ColdFusion knows nothing about Flash ActionScript, but they do share a common language - SOAP - and it's a beautiful thing. The same holds true for Java, PHP, Visual Basic, and other programming languages.
What We Are Going to Do In our sample application ColdFusion is going to be the technology used to publish the Web service that supplies Flash with data from the server. Flash is going to make calls to the ColdFusion server to get that data, and will pass any data that the server requires for its methods. SOAP is going to be the vehicle for the data to ride on, between the two. In a nutshell, the user will type in a username and password, then click the login button. At this point Flash will pass the two arguments to ColdFusion in the form of a SOAP request. ColdFusion will take that SOAP XML and translate the two arguments to a string type that ColdFusion can understand. ColdFusion will then evaluate the username and password and return a valid or invalid string value back to Flash in a SOAP Response. Flash then receives that XML data structure, converts it to a String object it can understand, and displays the result to the user. That's it! The last thing to discuss before we go into the project, is that Flash MX 2004 interacts with Web services in two ways. First, it uses design time graphical components to set the properties in the IDE rather than in code. You can actually develop applications without typing a line of code. Second, it uses the Web service classes and does not rely on the graphical components. We will examine both in this article.
The Web Service
<CFCOMPONENT>
<CFFUNCTION>
<CFARGUMENT> For more information on publishing CFCs as Web services check out: http://livedocs.macromedia.com/coldfusion/6/ Developing_ColdFusion_MX_Applications_with_CFML/webservices5.htm
LoginManager.cfc
Setting Up the Application Under ColdFusion MX Then I saved a file named LoginManager.cfc in the ws directory: [coldfusion web root]/mxdj/ws/LoginManager.cfc Open this file in your favorite editor (I use Dreamweaver MX 2004) and place the following code. First start with the component definition:
<cfcomponent> Second, define the method to login:
<cfcomponent> Note: The access attribute is set to remote; if you do not set this attribute correctly the component will not be accessible to Flash. Third, define the arguments needed to log in:
<cfcomponent> Finally, write the code to verify the username and password, as well as return the result of that evaluation.
<cfcomponent> Obviously, this is just a quick example of a login method that is not very realistic. A real login method would be connecting to a database and not using hard-coded values as this one does. That's about all it takes to create a component. Go ahead and test it out by accessing the component in your Web browser with the following URL (replace the localhost:8500 with the URL and port to your ColdFusion MX server): http://localhost:8500/mxdj/ws/LoginManager.cfc?method=login&username=cur tis&password=letmein You should see a result like the one in Image 1. Now, produce a bad login by changing the arguments to an invalid username and password: http://localhost:8500/mxdj/ws/LoginManager.cfc?method=login&username=bla... You should see a result like the one in Image 2. Now that we have our component working, let's turn it into a SOAP Web service that can be used by the new data components in Flash MX 2004. Well, there is not really anything to do, except change the way we access it. By adding ?wsdl to the end of the URL to access a component tells ColdFusion MX that we want our communication with that component to be SOAP based. To look at what our CFC looks like using SOAP type, see the following URL: http://local host:8500/mxdj/ws/LoginManager.cfc?wsdl. WSDL (Web Services Description Language) is an XML format for describing Web services. It defines what methods (or operations) are available, what parameters the method will take, and what the method returns. The result should look like Image 3. Note: If your browser appears to be blank, view the document source. Some browsers do not display WSDL. This is how WSDL describes the LoginManager CFC, so that when other SOAP-aware applications attempt to use this service, they know how the objects are defined.
The Flash Front End The Interface
Web Services Panel To add a Web service, click the globe icon in the upper left hand corner of the panel. A Define Web Services dialog will open. We want to view the LoginManager service so click the plus icon to add a service, then enter the URL to the service and tack ?wsdl to the end (http://localhost:8500/mxdj/ws/LoginManager.cfc?wsdl; see Image 6). Press the "OK" button. Now your Web services panel will display the newly added service. In this panel, services are displayed in a tree so that you can drill down to its method and that method's arguments and results. Expand each level of the LoginManager service so that you can see the Login method, its arguments, and results (see Image 7).
The WebServiceComponent Once the component is on the stage go ahead and move it off the viewable area. It is not seen at runtime, so wherever you place it on the screen is just a matter of organizational preference (see Image 9). Select the WebServiceConnector component and name it to login_wsc. Also, verify that the WSDLURL and operation property is correct (see Image 10).
Binding To bind the arguments to the TextInput components, select login_wsc then click on the bindings tab in the Component Inspector tab. Click the plus icon to add a parameter binding (see Image 11). An Add Bindings dialog will open displaying the possible arguments and results that can be bound (see Image 12). Select the username argument and press the OK button. Back in the Component Inspector panel, under the Bindings tab, you will now see the username argument in the Bindings list. With the username binding selected, click in the bound to property field to bind the username argument to the username_inpt TextInput component. Within the Component Path tree lays the login_frm and all of its components. Select the <TextInput> username_inpt node then click OK (see Image 13). The component is now bound to the username argument. Notice that the direction property is equal to "in". When a user types in a username, that value will be bound to the username argument and passed to the login method. Repeat the same process to bind the password argument to the password_inpt TextInput component. When passing values to the WebServiceConnector, the direction value will be "in", but when receiving values from a WebServiceConnector the will be "out". You will now see how the "out" direction works with the next step. At this point you are able to pass arguments to the WebServiceConnector, but are not able to receive the result. To do this, click the plus icon on the Bindings tab the same way you added the arguments. This time select the results node and click OK. In the Component Inspector, under the Bindings tab, you should now have three items that are bound: username, password, and results. To complete the binding of the results, click in the bound to property field, then drill down to the Label <results_lbl> node in the Bound To dialog, finally clicking OK. Your Component Inspector panel should now look like Image 14. Okay, now our interface is bound to data! All we have to do now is trigger the data source. To continue down the path of NO CODING, we will trigger the data source using the new Flash MX 2004 behaviors. To do this, select the login_btn on the stage, then open the Behaviors panel, accessed via the main menu-Window-Development Panels-Behaviors (see Image 15). To add a behavior, click the plus icon, then navigate the menu Data-Trigger Data Source (see Image 16). The Trigger Data Source dialog will open. Drill down the tree and select login_wsc, then click OK (see Image 17). To see what has happened, select the login_btn Button component and open the actions panel. As you can see in Image 18, code has been generated for you to trigger the login_wsc WebServiceComponent. So, now we are bound and triggered and ready to log in. Test your application and enter in a username and password. If you want to have a successful login enter "curtis" for the username and "letmein" for the password. If the username and password are correct, then the results_lbl will display "good login!" (see Image 19). Otherwise, a bad login will result in "bad login". This has been a simple example of how the WebServiceConnector component and a ColdFusion CFC can work together. Through the use of the Component Inspector, you can bind data to other components without one line of code. It's fun to throw together a quick application or prototype using these tools. However, you can soon find yourself limited by this way of application development and find yourself deep in code to solve the problem.
Coding the Web Services Classes So let's get started on creating a coded version of the Login application. The easiest and quickest way to get things going is to save a copy of the Login.fla as Login2.fla. Next, delete the login_wsc WebServiceConector component from the stage and delete the WebServiceConector component from your library. Finally, select the login_btn Button component on the stage and delete the click behavior from the Behaviors panel. Now we are ready to set up our application with code. We are going to need a class for the login_frm Form. Classes in ActionScript 2.0 are defined in their own file with the .as extension. Let's begin by creating a new class from within the Flash MX 2004 development environment. From the main menu select File-New. A New Document dialog will open. Make sure the General tab is selected, then choose the ActionScript File option from the list and click OK (see Image 20). Save the new file as LoginForm.as in the same directory as the Login2.fla. Make sure to pay attention to how you name and reference files, ActionScript 2.0 is case sensitive no matter what platform you are developing on. Many articles and online tutorials are written on ActionScript 2.0, so I will not go into it here. But, if you want to read a good one, check out the Ramping up on ActionScript 2.0 and Flash MX 2004 in the January 2004 edition of ColdFusion Developer's Journal (www.sys-con.com/coldfusion/). Let's write our class. First the class definition. Since we will be associating this class with login_frm Form, we will need to extend the Form class:
class LoginForm extends mx.screens.Form {
function LoginForm() {
}
}
Save the LogForm.as file then go back to the design environment to associate the LoginForm class with login_frm. To do this, select login_frm in the form hierarchy pane and select the properties tab in the Properties panel. In the class name field, replace mx.screens.Form with LoginForm (see Image 21). Now when an instance of login_frm is created, so will an instance of LoginForm class. Before we go back to coding we need to get the Web services classes into our application. You can access these classes from the main menu by navigation Window-Other Panels-Common Libraries-Classes (see Image 22). In the libraries panel you will see a library with the heading Classes.fla. Within Classes.fla there are DataBindingClasses, UtilsClasses, and WebServicesClasses. Now, we will deal with WebServicesClasses. Drag the WebServicesClasses icon to the stage so that it is in the Login2 library. Then delete the object from the stage. Back in our LoginForm.as file, we need to import the services that we just added to our file.
import mx.services.*;
class LoginForm extends mx.screens.Form {
function LoginForm() {
}
}
Then we need to define a variable to hold a reference to our login_btn Button component and add a listener for the click event. Also, define references to the TextInput and Label components:
import mx.services.*;
import mx.controls.Button;
import mx.controls.Label;
import mx.controls.TextInput;
class LoginForm extends mx.screens.Form {
private var login_btn:Button;
private var results_lbl:Label;
private var username_inpt:TextInput;
private var password_inpt:TextInput;
function LoginForm() {
}
function onLoad() {
var obj = this;
var loginBtnListener = new Object();
loginBtnListener.click = function(evnt) {
}
login_btn.addEventListener("click", loginBtnListener);
}
}
When the login_btn Button is clicked then we should make a call to our Web service. So, within the click event for login_btn we will set up a service and make a call.
loginBtnListener.click = function(evnt) {
var loginService:WebService = new WebService
("http://water.local:8101/cfusion/mxdj/ws/LoginManager.cfc?wsdl");
}
Next, make the call. Also, assign an object to that call to listen for the result and fault events.
var loginCall:PendingCall = loginService.login(obj.username_inpt.text,
obj.password_inpt.text);
loginCall.onResult = function(result) {
obj.results_lbl.text = result;
}
loginCall.onFault = function(fault) {
obj.results_lbl.text = "An Error Occurred"
trace(fault.faultCode + " : " + fault.faultString);
}
Finally, your completed LoginForm class should look like this:
import mx.services.*;
import mx.controls.Button;
import mx.controls.Label;
import mx.controls.TextInput;
class LoginForm extends mx.screens.Form {
private var login_btn:Button;
private var results_lbl:Label;
private var username_inpt:TextInput;
private var password_inpt:TextInput;
function LoginForm() {
}
function onLoad() {
var obj = this;
var loginBtnListener = new Object();
loginBtnListener.click = function(evnt) {
var loginService:WebService = new WebService
("http://water.local:8101/cfusion/mxdj/ws/LoginManager.cfc?wsdl");
var loginCall:PendingCall = loginService.login(obj.username_inpt.text,
obj.password_inpt.text);
// onResult is called when all goes well
loginCall.onResult = function(result) {
// display whether the user is valid or not
obj.results_lbl.text = result;
}
// an error occurred while trying to make the Web Service call
loginCall.onFault = function(fault) {
trace(fault.faultCode + " : " + fault.faultString);
}
}
login_btn.addEventListener("click", loginBtnListener);
}
}
Debugging
PendingCall Class For example, in the loginCall.onResult event I trace the loginCall.response property. The following is what is in the output:
<?xml version="1.0" encoding="UTF-8"?>
SoapCall Class Change the loginCall.onResult event handler to this:
loginCall.onResult = function(result) {
var sCall:SOAPCall = loginCall.myCall;
for(var i in sCall) {
trace("loginCall.myCall." + i + " = " + sCall[i]);
}
obj.results_lbl.text = result;
}
Log Class
By adding the following code we can track what is going on during our Web service method invocation: Insert this code right above the loginService declaration:
var loginLog:Log = new Log(Log.VERBOSE);
loginLog.onLog = function(log_str) {
trace(log_str);
}
Change the loginService declaration by adding an additional parameter containing the loginLog: var loginService:WebService = new WebService("http://water.local:8101/cfusion/mxdj/ws/LoginManager.cfc?wsdl", loginLog); Now run the application and log in again. You will see output from the log object in the Output panel (see Image 23). As you can see there are many ways to debug your application, so you won't be left out in the cold.
Wrapping Up Would you prefer to use the LoadVars technology of yesteryear? I think not. Coming from years of transferring data through URL rewriting, HTML form elements, and manually parsing XML documents, I am pretty set on not going back to that - and recent trends show that the industry agrees. Having the ability to work with objects, and not caring how they got to the server and came back to me, is a good thing. With integrating technologies such as ColdFusion MX and Flash MX 2004, data should be smooth and trouble free. Reader Feedback: Page 1 of 1
Enterprise Open Source Magazine Latest Stories . . .
Subscribe to the World's Most Powerful Newsletters
Subscribe to Our Rss Feeds & Get Your SYS-CON News Live!
|
SYS-CON Featured Whitepapers
Most Read This Week |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||