Wednesday, January 28, 2009

Not All Files Appear in AIR Export Release Build

As shown in Adobe bug database (i.e., FB-16266), not all files you need will appear in AIR Export Release Build.

I've found that there are two cases that files were not copied over:
  1. Image file included using the following MXML statement:
    <mx :Image source="assets/search/oracle_logo.png">

  2. Dynamically loaded resource bundle files:

    _resourceModuleURL = "assets/search/search_" + _locale + ".swf";
    _step = new ResourceBundleLoader(_resourceModuleURL);


FlexBuilder should have provided options for developers to pick and choose what files to be packaged into the final AIR application. It does. However, in my case, the above two files are simply not listed in "AIR File Contents" dialog and there is no way to choose them from.

The workaround for this issue is:
  1. At the last step of "Export Release Build" (i.e., AIR File Contents), click on Cancel instead of Finish. FlexBuilder will copy all files needed (except the ones that are known missing) to the bin-release folder.
  2. Copy missing files to their corresponding locations.
  3. Run adt manually to generate the final AIR application:

    REM
    set flexSdkDir="D:\Program Files\Adobe\Flex Builder 3\sdks\3.1.0"
    set JAVA_HOME="C:\Program Files\Java\jre1.6.0_07\bin"

    REM
    set Path=%Path%;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem
    set Path=%Path%;c:\Program Files\Winzip;D:\MKSNT;%flexSdkDir%\bin
    set Path=%Path%;%JAVA_HOME%\bin
    echo %Path%

    set flexWorkDir="D:\myDocuments\Flex Builder 3"

    adt -package -storetype pkcs12
    -keystore %flexWorkDir%/myDigitalCertificate.p12
    -storepass welcome -tsa none Search.air bin-release\Search-app.xml
    -C bin-release Search.swf -C src assets


Saturday, January 24, 2009

A Photo Safari to Botswana


Lilacbreasted Roller


Legadima


Do you like these animal pictures? These are the photos taken by my respected College Professor who has joined his wife on a trip to Africa (i.e., A Photo Safari to Botswana). As you can see, these photos have captured many wild animals in Botswana with high details and beautiful colors. My professor has also done a good job of labeling each animal with its name. I would say these set of photos are treasures to our future generations by documenting and recording animals that are disappearing or endangered. You can click here to see all of them.

Friday, January 23, 2009

Setting Web Services to A Different URL in ActionScript

Some Web Services don't provide a correct port address in its WSDL. To get around this issue, it requires developers to set new endpointURI in MXML/ActionScript files.

There are two ways of calling web service operations in Adobe Flex:
  1. Use Flex built-in WebService class

  2. Use web service proxy classes (automatically generated by WSDL Instrospection Wizard)

Using Flex Built-In WebService Class


Using the first approach, you can set endpointURI on the WebService instance. The creationComplete event is thrown when the application is initialized. In this case, you can attach a listener (i.e., initApp()) to intercept the event and set the correct endpointURI on the WebService instance. Note that the new endpointURI set on the WebService instance applies to all operations defined in it.

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication
xmlns:mx=http://www.adobe.com/2006/mxml
layout="vertical"creationComplete="initApp()"
xmlns:search="search.*">

<mx:WebService
id="myWebService"
wsdl="http://www.example.com:7753/search/query/Search?WSDL"
showBusyCursor="true">

<mx:operation name="doSimpleSearch" resultFormat="XML"
fault="onFault(event)"
result="showResult(event)"/>

<mx:operation name="login" resultFormat="XML"
fault="onFault(event)"
result="showResult(event)"/>

</mx:WebService>

<mx:Script>


private function initApp():void
{
myWebService.endpointURI =
"http://www.example.com:7753/search/query/Search";
myWebService.login("yyy", "yyy");
}
]]>

</mx:WindowedApplication>

Using Web Service Proxy Classes

You can also use the Flex Builder Import Web Service feature to automatically generate connection code for invoking SOAP-based web service operations. The generated code includes client-side (ActionScript) web service proxy classes that return strongly typed objects. You can use the generated code to call web service operations directly and to pass strongly typed objects as operation parameters.

Generated web service proxy files
The Import Web Service feature introspects a provided WSDL file and generates the following ActionScript class files:
  • BaseServiceName.as

  • IServicename.as

  • etc.

To see the full list of generated files and their descriptions, see Adobe Help.

For example, our service is named SearchService which is retrieved from the WSDL file. Using Import Web Service feature in FlexBuilder, it generates the following files:
  • BaseSearchService.as

  • ISearchService.as

  • etc.

To fix the URL issue, you locate endpointURI in the BaseServiceName.as file. Then set it to be the correct URL as shown below:
BaseSearchServicePort.endpointURI = "http://myserver:7777/search/query/Search"

This should work when you use the generated code to call web service operations directly. Without this fix, you will get the notorious stream error #2032.

I also noticed that there is a generated WSDL file in the project under .wsdl folder. It may be a good idea to change the URL in that WSDL file to be correct.

Thursday, January 22, 2009

Two Ways of Calling Web Service in Flex

There are two ways of calling web service operations in Flex:
  1. Use Flex built-in WebService class
  2. Use web service proxy classes (automatically generated by WSDL Instrospection Wizard)

Flex Built-in WebService Class


The <mx:WebService> tag gives you access to the operations of SOAP-compliant web services deployed on a web server.

See a working example here.

Web Service Proxy Classes


You can use the Flex Builder "Import Web Service" feature to automatically generate connection code for invoking SOAP-based web service operations. The generated code includes client-side (ActionScript) web service proxy classes that return strongly typed objects. You can use the generated code to call web service operations directly and to pass strongly typed objects as operation parameters. See the details on Adobe Flex 3 Help.

The following two tables compare these two approaches:


































Flex WebService Class
Example

<mx:WebService


 id="myWebService"


 wsdl="http://.../OracleSearch?WSDL"


 showBusyCursor="true">



<mx:operation name="login" resultFormat="XML"


 fault="onFault(event)"


 result="onLoginComplete(event)"/>


</mx:WebService>


Request
  1. myWebService.login(userName, password);
  2. myWebService.login(preEncodedXml);
Response myWebService.login.lastResult
Parameters

  1. Marshaled and validated by SchemaManager (i.e., provide multiple parameters mapped to message parts in the WSDL definition) [see Note #1]

  2. Bypassing the marshaling and validation of SchemaManager (i.e., use a pre-encoded node such as a single XML object, XMLList object, etc.)


Advantage(s)

  1. Even "Import from WSDL" Introspection Wizard fails, you can still call web service operations.


Disadvantage(s)

  1. Need to know the mappings between the WSDL definition and the MXML Web services declaration [see Note #2].

  2. If the marshaling and validation is done at runtime, it incurs overhead.

  3. If the marshaling and validation is bypassed, the SOAP payload may be invalid.






































Generated Web Service Proxy Class
Example

<search:OracleSearchService id="myWebService">


 <search:login_request_var>


  <search:Login_request>


   <search:username>{tiNameInput.text}</search:username>


   <search:password>{tiPassInput.text}</search:password>


  </search:Login_request>


 </search:login_request_var>


</search:OracleSearchService>


Request myWebService.login_send()
Response myWebService.login_lastResult
Parameters Strongly typed objects (i.e., Login_request class instance).
Advantage(s)

  1. Parameters are strongly typed.

  2. No need to know the mappings between the WSDL definition and the MXML Web services declaration [see Note #1] because the Web Service Introspection Wizard generates proxy classes that take care of web service data mapping and event plumbing.


Disadvantage(s)

  1. Sometimes "Import from WSDL" Introspection Wizard fails to convert.

  2. Sometimes generated SOAP message based on wizard's interpretation of schema is invalid (i.e., invalid to a specific implementation of web server).

  3. Whenever WSDL is updated, you need to regenerate proxy classes.







Notes

  1. Based on WSDL's schema definition, WSDL introspection wizard generates a set of web service proxy classes in advance. At runtime, operation's parameters are provided as strongly-typed objects (i.e., content objects) and marshaled/validated to SOAP message body.
  2. The mappings between the WSDL definition and the MXML Web services declaration depend on the operation style (Document or RPC), encoding mechanism used (literal or encoded), type (simple or complex) of parameter, and number of parameters. (You can read "Develop Web services clients with Macromedia Flex" article to understand the mapping issues although it is a little bit out-of-date).

How to Make External Components Available to Your Flex Code

MXML tags correspond to ActionScript classes or properties of classes. Flex parses MXML tags and compiles a SWF file that contains the corresponding ActionScript objects. For example, Flex provides the ActionScript HBox class that defines the Flex HBox control. In MXML, you create a HBox control by using the following MXML statement:
<mx:HBox id="mainWindow"  width="100%" height="30" 
borderSkin="{components.TopBorder}" backgroundColor="#A5A7Ad"
backgroundAlpha="0.75" cornerRadius="15" paddingLeft="0"
paddingTop="0" paddingRight="0" paddingBottom="0"
verticalGap="0" verticalAlign="middle">

When you declare a control using an MXML tag, you create an instance object of that class. This MXML statement creates a HBox object, and initializes the borderSkin property of the HBox object to the components.TopBorder Class. To avoid compilation error, you need to make externally defined classes and packages available to your code by using import statement. For components.TopBorder, you need to import it like this:
<mx:script>
<![CDATA[import components.TopBorder;]]>
</mx:Script>
It is possible for you to omit this import statement if you have other components from the same package being referenced in the same MXML file. Say, in the same MXML file that references components.TopBorder, we also have the following MXML tag which references VStack from the same package (i.e., components):

<components:VStack id="worklistComp"  width="100%" height="100%" 
headerStyleName="StackLabel" backgroundColor="#e8eaed" boderThickness="0">

To avoid compilation error, you need to add an namespace declaration as this:

<mx:windowedapplication xmlns:components="components.*" 
width="452" height="364" layout="vertical" ...>

Because the reference of components.VStack has made components package available to your code by MXML compiler, you don't need to import it again.

In summary, you always need to make externally defined classes and packages available to your Flex code by:
  • If you reference it in MXML tag, you use xmlns attribute to declare a prefix and its path (i.e., xmlns:components="components.*") and use that prefix in the tag name (i.e., <components:VStack>).

  • If you reference it in MXML attribute or node value, you use ActionScript import statement to make it available.

Friday, January 16, 2009

Installing Eclipse and Its Plug-ins (FB, Jupiter, Subclipse)

This article documents the procedure of setting up Eclipse to use the following plug-ins:
  • Flex Builder plug-in 3.0.2 (i.e., FB3_WWEJ_Plugin.exe)
  • Jupiter plug-in 3.4.1.1 (i.e., edu.hawaii.ics.csdl.jupiter_3.4.1.1.jar)
  • Subclipse plug-in
To read more about these plug-ins, refer to the following documents:

The Eclipse platform we use is "Eclipse IDE for Java EE Developers" and you can download it from here. Our version is 3.4.1.

Follow these steps to install Eclipse and its plug-ins:
  1. Install Eclipse by unzipping the archive to a folder, say E:\MyApplications.
  2. Click on E:\MyApplications\eclipse\eclipse.exe to start Eclipse.
  3. Install Flex Builder plug-in by clicking on FB3_WWEJ_Plugin.exe
    • Adobe Flex Builder 3 Installer will be launched.
    • Choose an install folder for Flex Builder (e.g., E:\Program Files\Adobe\Flex Builder 3 Plug-in)
    • Choose an Existing Eclipse Folder (e.g., E:\MyApplications\eclipse)
    • If you already have Flash Player installed, you can skip additional installations
    • Close all instances of Eclipse or Flex Builder before proceed with the installation
    • If you install the plug-in on a machine that already has a registered Flex Builder installation, it will be automatically registered. Otherwise, you need to register.
  4. Install Jupiter plug-in by copying its jar file into the plugins directory of Eclipse (e.g., E:\MyApplications\eclipse\plugins).
  5. Install the Subclipse plug-in
    • In Eclipse, open Help -> Software Updates
    • Software Updates and Add-ons wizard will be launched
      • If you try to install the Subclipse plug-in (or any Eclipse plug-in) from the intranet, you'll need to set the Proxy in Eclipse first. You do that in Window->Preferences->General->Network Connectivity.
    • Click on Available Software tab
    • Click on Add Site button
    • Add the following location: http://subclipse.tigris.org/update_1.4.x
    • Expand http://subclipse.tigris.org/update_1.4.x site
    • Select "Subclipse" and "JavaHL Adapter"and then click on "Install" button
As you might have noticed, there are 3 different ways of installing Eclipse plug-ins:
  1. Use InstallAnywhere installer
  2. Copy jar file into plugins directory
  3. Use Eclipse's Software Update

Final Words

When features and plug-ins are manually installed on top of an Eclipse-based product install located on a FAT file system that has already been run at least once, the product must be explicitly restarted with -clean. That is,

eclipse.exe -clean


Learn More
  1. Eclipse IDE Tutorial

Thursday, January 15, 2009

Importing Foreign Projects from SVN in Flex Builder

How does one go about opening someone else's project in Flex Builder using Subversion? You can directly import a project without creating a dummy one first and there are two ways of achieving this:

(1) From File menu...

  1. File > Import > Other
  2. Select Checkout Projects from SVN
  3. Check Use existing repository location: and select svn://rws...
  4. Select a project folder
  5. Use the default setting in Checkout from SVN dialog.

(2) From SVN Respository Exploring perspective...

  1. Browse in the SVN navigator to the project folder that you want to include into your existing workspace.
  2. Right click and bring up context menu.
  3. Choose Checkout...
  4. Checkout from SVN dialog will pop up and offer to check out the project in the current workspace.



To install Subversion in Flex Builder, you can get the the Subclipse plugin and follow the instructions as shown here.

Wednesday, January 14, 2009

Flash Debug Player and its Configuration

To work with Flex Builder Debugger, you need the Flash debug player. This is installed when you install Flex Builder. But, this may fail or you may upgrade Flash player independently. To determine if you have the debug player installed, you can navigate to: Version test for Adobe Flash Players. In ActionScript, you can use Capabilities.isDebugger property to test if you have the debug player installed.

Flash debug player is different from the standard Flash Player. It includes additional functionality that the standard player does not have such as:
  • Logs trace() statements (logging in the Flash debug player is turned off by default)
  • Works with Flex Builder Debugging Perspective
  • Works with the Flex Builder 3 Profiler
Using Flash debug player's run time log file (i.e., flashlog.txt) alone, you can gain lots of valuable information for your debugging. Output strings from trace() method are appended to this log file. Furthermore, the debug player exposes quite a bit Run Time Errors (RTEs). The production player will actually ignore most RTEs and carry on. This can let the user continue on without a fatal crash. But, sometimes the error can stop the Flash application in its tracks.

The debug version of Flash Player can be configured by the mm.cfg text file in the system. You can use any text editor to create it. The following table lists the properties that you can set in the mm.cfg file:


























Property
Description
ErrorReportingEnable

Enables the logging of error messages.


Set the ErrorReportingEnable property to 1 to enable the debugger version of Flash Player to write error messages to the log file. To disable logging of error messages, set the ErrorReportingEnable property to 0.


The default value is 0.


MaxWarnings

Sets the number of warnings to log before stopping.


The default value of the MaxWarnings property is 100. After 100 messages, the debugger version of Flash Player writes a message to the file stating that further error messages will be suppressed.


Set the MaxWarnings property to override the default message limit. For example, you can set it to 500 to capture 500 error messages.


Set the MaxWarnings property to 0 to remove the limit so that all error messages are recorded.


TraceOutputFileEnable

Enables trace logging.


Set TraceOutputFileEnable to 1 to enable the debugger version of Flash Player to write trace messages to the log file. Disable trace logging by setting the TraceOutputFileEnable property to 0.


The default value is 0.


TraceOutputFileName

Note: Beginning with the Flash Player 9 Update, Flash Player ignores the TraceOutputFileName property.


Sets the location of the log file. By default, the debugger version of Flash Player writes error messages to a file named flashlog.txt, located in the same directory in which the mm.cfg file is located.


Set TraceOutputFileName to override the default name and location of the log file by specifying a new location and name in the following form: On Macintosh OS X, you should use colons to separate directories in the TraceOutputFileName path rather than slashes.


TraceOutputFileName=<fully qualified path/filename>


For example, the following sample mm.cfg file enables error reporting and trace logging:
ErrorReportingEnable=1
TraceOutputFileEnable=1

The location of mm.cfg and its log file (i.e., flashlog.txt) is determined by OS. However, you can update the log file location and name through the TraceOutputFileName property.

The following table shows where to create mm.cfg for several operating systems.





























Operating SystemCreate mm.cfg file in this directory
Macintosh OS XMacHD:Library:Application Support:macromedia:
Microsoft Windows VistaC:\Users\user_name\
Microsoft Windows 2000/XPC:\Documents and Settings\user_name\
Microsoft Windows 95/98/ME%HOMEDRIVE%\%HOMEPATH%\
Linux
/home/user_name



The following table shows the default flashlog.txt file location:
























Operating SystemLocation of flashlog.txt
Macintosh OS XMacHD:Users:user_name:Library:Preferences:Macromedia:Flash
Player:Logs:flashlog.txt
Microsoft Windows VistaC:\Users\user_name\AppData\Roaming\Macromedia\Flash Player\Logs\flashlog.txt
Windows 95/98/ME/2000/XP
C:\Documents and Settings\user_name\Application Data\Macromedia\Flash Player\Logs\flashlog.txt
Linux/home/user_name/.macromedia/Flash_Player/Logs/flashlog.txt

Being a text file, there are several ways to read from the log file:
  • Notepad or its equivalent
  • Tail or some variant
  • FlashTracer
  • Using the tail view in Aptana
If you have trouble of generating flashlog.txt log file, check out this article--"Troubleshooting tips for .txt not being generated."

Sunday, January 11, 2009

Tools for Debugging AIR Applications

























Tools Descriptions
Flex Builder Debugger
  • Free videos about debugging with Flex Builder are available from Lynda.com.
  • With the <mx:TraceTarget/> tag present any where in the code which enables the tracing information, you can use the debugger version of Flash Player to track network traffic between your client and application server.
  • Further information about the Adobe Flex Builder debugger can be found here.

ADL (AIR Debug Launcher)

  • If you do not use Flex Builder 3 or your AIR application are not Flex-based, you can use ADL provided in AIR SDK.
  • With the ADL, you can debug either Flex-based or HTML-based applications.

Third-party Tools (ServiceCapture, Charles, and Ethereal/Wireshark)
  • Allow you to capture the network traffic (using Flash Remoting) or data flow between an AIR application and any server technologies.

AIR HTML Introspector
  • AIRIntrospector.js JavaScript file provided in the AIR SDK can be included in your application to help debug HTML-based or AJAX-based AIR applications.
  • You can download Aptana Studio to create/debug HTML/JavaScript based AIR Applications.
  • Include the AIRIntrospector.js file only when developing and debugging the applications. But, remove it in the packaged Adobe AIR application that you distribute.