Posts in Category "Flex"

Notes about caching

1. caching to the disk is controlled by browser, not by flex/flash. The browser cache can be saved to the disk, flash player cache will only be in the memory.
2. By default, browsers can cache content over http ( if you didn’t set no-store no-cache in the header ).
http://stackoverflow.com/questions/174348/will-web-browsers-cache-content-over-https
3. However, browsers may not cache content to disk over https by default and you need to configure it.
For IE, you can turn on the feature by change setting at:
Tools > Internet Options > Advanced tab > Security section > Do not save encrypted pages to disk
For Firefox, see details in
http://blogs.atlassian.com/developer/2007/07/when_caching_is_not_caching.html
4. Only signed RSLs can be stored in the player cache, unsigned will be in browser cache. Only Adobe can create signed RSLs. If you create an RSL that contains a customer library, it will be unsigned, so can’t be in player cache. There is no workaround for this at the moment. Your option is to use unsigned with browser’s cache.
5. If your app get an connect problem over the first request, but works fine after a refresh, that usually is caused by the content cache over https issue. See above for how to correct it.

RTMFP — Real-Time Media Flow Protocol

A great new article about RTMFP

http://broadcast.oreilly.com/2009/04/adobes-real-time-media-flow-pr.html

using webtier compiler with flex 3

In flex 2, the webtier compiler is included in the SDK. But in flex 3, it is no longer included in the flex 3sdk install. You have to install and configure it separately. The following links will show you how to install and configure it.

http://labs.adobe.com/wiki/index.php/Flex_Module_for_Apache_and_IIS

http://livedocs.adobe.com/flex/3/html/help.html?content=apache_3.html

http://opensource.adobe.com/wiki/display/flexsdk/Downloads

There are two type of configuration:

1. config with Apache or IIS connector. If you are using Apache or IIS as your web server, then this may be the approach you want to take.

2. install as a J2EE app. This approach will install a webtier.war to your machine. Then you can deploy this war file to the app server you are using. You should deploy it as extracted app, and put your flex app page under the web root.

Problem:

When you run a flex app page with the webtier compiler, it runs fine the first time you request it. If you modify anything in the code and recompile that page, then you may see the following Error:

TypeError: Error #1010: A term is undefined and has no properties.
at mx.styles::StyleManagerImpl/initProtoChainRoots()
at mx.styles::StyleManager$/http://www.adobe.com/2006/flex/mx/internal::initProtoChainRoots()

See bug http://bugs.adobe.com/jira/browse/LCDS-387 for details.

Workaround:
By default, we are using incremental compile to do the compiling, but the incremental compile has some issues. The workaround is to not use the incremental compile.

in flex-webtier-config.xml; set the incremental-compile to false:
<incremental-compile>false</incremental-compile>

Once the change is made, the webtier compiler will work properly.

How to turn on debug trace in Flex

When you encounter issue wit your flex app, one useful tool for troubleshooting is to turn on debug in flex to get some output that will provide some clue of the cause of he problem. Here is how to turn it on from server-side as well as from client-side:
1. From server side:
In the services-config.xml, set the logging level to debug, and set filters to include the service you need:

<target class=”flex.messaging.log.ConsoleTarget” level=”debug”>
<properties>
<prefix>[Flex hotfix2] </prefix>
<includeDate>true</includeDate>
<includeTime>true</includeTime>
<includeLevel>true</includeLevel>
<includeCategory>true</includeCategory>
</properties>
<filters>
<pattern>Endpoint.*</pattern>
<pattern>Service.*</pattern>
<pattern>Protocol.*</pattern>
<pattern>Message.*</pattern>
<pattern>DataService.*</pattern>
<pattern>Configuration</pattern>
</filters>
</target>

See available pattern in doc:

http://livedocs.adobe.com/livecycle/8.2/programLC/programmer/lcds/help.html?content=services_logging_3.html

2. To turn on trace in JGroup:
in jgroups-tcp.xml, add <TRACE/> tag just before the </config> line :

<config>
….
<TRACE/>
</config>

3. To turn on from client-side:
Make sure flashlog.txt is enabled, i.e, have the following setting in mm.cfg
TraceOutputFileEnable=1
ErrorReportingEnable=1
See more details in the doc here
There is a good blog regarding mm.cfg here as well.

Then in your flex app, add the following tag:
<mx:TraceTarget/>

4. To turn on the flash player policy logging

see http://www.adobe.com/devnet/flashplayer/articles/fplayer9_security_05.html

Tips for working with time zone in flex app

1. Understand how date and time are determined by flex (player on the client machine)
From flex doc we can see:
“The Date class lets you retrieve date and time values relative to universal time (Greenwich mean time, now called universal time or UTC) or relative to local time, which is determined by the local time zone setting on the operating system that is running Flash Player. ”

This mean if one user’s machine is using “Automatically adjust clock for daylight saving changes”, the time displaied in flex app may be different with another user who is running the same flex app without “Automatically adjust clock for daylight saving changes” on his machine.

“Automatically adjust clock for daylight saving changes” can be checked from
Control Panel –> Date and time –>Time Zone.

2. Understand how date and time are determined by Java ( On server machine)
1). The JVM determines the correct Coordinated Universal Time (UTC) by comparing the QUTCOFFSET value to the local time for the system
The JVM returns the correct local time to the system by using the Java system property user.timezone.
The default value for QUTCOFFSET is zero (+00:00).
The QUTCOFFSET value allows the JVM to determine the correct value for the local time. For example, the value for QUTCOFFSET to specify central standard time (CST) is -6:00. To specify central daylight time (CDT), QUTCOFFSET has a value of -5:00.
The user.timezone Java system property uses UTC time as the default value. Unless you specify a different value, the JVM recognizes UTC time as the current time.
See more details in here

2). you need correct patches for Java to get correc date and time.

— There is a patch for jdk you may want to double check:
http://sunsolve.sun.com/search/document.do?assetkey=1-26-102836-1
— if you are using Solaris, you may need this patch
http://sunsolve.sun.com/search/document.do?assetkey=1-26-103044-1
— if you are using 1.4.2_10 or lower version of JDK, you need this patch
http://kb.adobe.com/selfservice/viewContent.do?externalId=kb400722

3). To verify your time zone setting in JDK, read this
http://publib.boulder.ibm.com/infocenter/wasinfo/v4r0/index.jsp?topic=/com.ibm.support.was.doc/html/WebSphere_Application_Server/1173447.html
Download time.jsp from there, and run it on your server.
To change timezone setting in Java, you can use java arg:
-Duser.timezone=America/Los_Angeles
If you are using Jrun as app sever, this can be change in JRun_install/bin/jvm.config file:
java.args=-Xms32m -Xmx384m -Dsun.io.useCanonCaches=false -Duser.timezone=Etc/UCT

3. synchronize time znoe on client and server
If you want to enter time in the client’s local time – regardless of the timezone your in at the time of data entry, and keep the date in UTC zone on both server and client side, see example

Note, don’t forget you also need to set JAVA VM timezone to UTC for this example.

How to apply chart license to flex 3

Some user found that after upgrade from FB2/Flex2 to FB3/Flex3, the chart watermark appears in the app. This is because the license has not applied correctly. There are certain changes regarding how we get license info, and they are described in the doc http://livedocs.adobe.com/flex/3/html/help.html?content=configuring_environment_2.html
Also see Blog entries:
http://raghuonflex.wordpress.com/2008/02/19/changes-in-flex-beta-3-licensing-model/
http://raghuonflex.wordpress.com/2008/02/20/how-to-apply-the-data-visualization-license-on-command-line-in-flex-3/

Basically, here are the things you need to know:
1. If you want to compile with flex 3 SDK, you will need a new license for flex 3. The license for flex 2 sdk would not work.
2. To apply the license from FB3, go to Help –> Manage flex license, then type in the license key. It should look like this: 1377-xxxx-xxxx-xxxx-xxxx-xxxx.
3. To apply the license in flex-config.xml:
<flex-config>
<licenses>
<license>
<product>flexbuilder3</product>
<serial-number>1377-xxxx-xxxx-xxxx-xxxx-xxxx</serial-number>
</license>
</licenses>

<compiler>

</compiler>
</flex-config>

4. To apply the license in license.properties file:
The path to the license.properties file for various OS are changes for flex 3, they are now at:
1).”../Documents and Settings/All Users/Application Data/Adobe/Flex” directory on Windows
2).”Library/Application Support/Adobe/Flex” directory on MAC
3).”$HOME/.adobe/Flex” on Linux

Example of Designing Loosely Coupled Flex 2 Components — pass data from main to child component

There is a good article regarding Designing Loosely Coupled Flex 2 Components. This is a good place to learn about different ways to design your components in Flex 2. On the third page of this article, it demonstrated how to Create Custom Event ActionScript Classes for sending complex data with an example. This example shows how to send data to the parent page by dispatch an event from the child component. What if you want to dispatch the event from the parent page, and pass the data into the child? Here is a simple example to show how we can accomplish that.

1. create a customer event ActionScript class:

In order to pass extra data via event, a customer event class is needed. We do this by extends existing Flex event classes and inherit all the events of the base class.  Here we create myEvent.as to pass selectedAlbum with the event.

myEvent.as:

package
{
     import flash.events.Event;
     import mx.core.Application;

    public class myEvent extends Event
   {
            public var myAlbum:String;
            public function myEvent(selectedAlbum:String,type:String) {
                     super(type);
                     this.myAlbum = selectedAlbum;
                     Application.application.lb.text=myAlbum;
           }
           public override function clone():Event{
                    return new myEvent(myAlbum,type);
           }
  }
}

2.  Create the main application:

The main application has a datagrid. The goal is to be able to display data in a new state based on selected row in the datagrid. The follwoing two handlers are the most improtant:

1).datagrid’s itemClick event handler itemClickEvent():  this will get the selected row and value of selectedAlbum.

2).eventHandler(): this will display the new state, dispatch event myEvent (must make sure the event is dispatched after the child is created), and pass selectedAlbum to the child component. We reference the child component as <v:looselyCoupledChild />.

Note, eventObj = new myEvent(selectedAlbum,"passID");

Here, passID is the event name we will define in the Metadata of the child component:

<mx:Metadata>
[Event(name="passID", type="myEvent")]
</mx:Metadata>

main flex page looselyCoupled.mxml:

<?xml version="1.0" encoding="utf-8"?>

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:v="*" layout="vertical">

<!–This example passes selectedAlbum to child.mxml by listening  to myEvent –>        

<mx:Script>

        <![CDATA[    

                      import flash.events.EventDispatcher;

                      import mx.events.ListEvent;

                      import mx.collections.ArrayCollection;

                      [Bindable]

                      public var selectedAlbum:String;

                      public var eventObj:myEvent;

                      [Bindable]

                      private var initDG:ArrayCollection = new ArrayCollection([

            {Artist:’Pavement’, Album:’Slanted and Enchanted’, 

                      Price:11.99, SalePrice: true },

            {Artist:’Pavement’, Album:’Brighten the Corners’,   

                      Price:11.99, SalePrice: false }

          ]);  

        private function itemClickEvent(event:ListEvent):void {

                                    selectedAlbum=event.currentTarget.selectedItem.Album;

                                    eventObj = new myEvent(selectedAlbum,"passID");

                                    this.dispatchEvent(eventObj);

                                    lb1.text=eventObj.myAlbum;

      }

                             private function eventHandler(stateView:String):void{

                             //the stateView must be created before the event dispatch.

                                    this.currentState = stateView;

                                    dispatchEvt();

                      }

                      private function dispatchEvt():void{

                                    eventObj = new myEvent(selectedAlbum,"passID");

                                    this.dispatchEvent(eventObj);                                

                      }                

        ]]>

</mx:Script>

<mx:Label id="lb"  text="show selectedAlbum — from myEvent"/>

<mx:Label id="lb1"  text="show selectedAlbum — from eventObj.myAlbum"/>

<mx:DataGrid  id="dg" dataProvider="{initDG}"  itemClick="itemClickEvent(event)">

</mx:DataGrid>

<mx:Button x="117" y="240" label="dispaly Album"  id="bt" click="eventHandler(‘child’)" />

          <mx:states>

                        <mx:State name="child">

                                      <mx:AddChild position="lastChild">

                                                                <v:looselyCoupledChild />

                                      </mx:AddChild>

                        </mx:State>

          </mx:states>     

</mx:Application>

3. create the child component:

In the child component, we need to add event listener to listen to passID as following:   Application.application.addEventListener("passID", passIDHandler);

looselyCoupledChild.mxml:

<?xml version="1.0" encoding="utf-8"?>
<mx:Panel xmlns:mx="http://www.adobe.com/2006/mxml" width="400" height="300" initialize="initHandler()" >
<mx:Metadata>
[Event(name="passID", type="myEvent")]
</mx:Metadata>
<mx:Script>
<![CDATA[

import mx.core.Application;
import myEvent;
private function initHandler():void{
Application.application.addEventListener("passID", passIDHandler);
}

private function passIDHandler(event:myEvent):void {
tinput.text = event.myAlbum;
}

]]>
</mx:Script>

<mx:Label text="Album you selected from event:" x="26" y="10"/>
<mx:TextInput x="107" y="8" id="tinput" />
<mx:Label x="291" y="10" text="Album you selected from selectedAlbum:"/>
<mx:TextInput x="372" y="8" text="{Application.application.selectedAlbum}"/>

</mx:Panel>

Note, Application.application.addEventListener("passID", passIDHandler);
  This means we will always have a reference to the child. If you are concerned about memory issue, you should check and destroy the event when it is done. If you don’t want to destroy the event, you can set weakRef to true in addEventListener.

To test the sample,

1). run looselyCoupled.mx, and select a row. You will see the Album name displayed on top of the datagrid.

2). click on "dispaly Album" Button, you will see the Album name has passed into the child component.

3). select another row in the datagrid, you will see the value in the child component is changed as well.

Links to nice flex 2 examples

1. Design loosely coupled Flex 2 components
http://mxdj.sys-con.com/read/276919_1.htm

2. Export datagrid to Excel:
If manfully copy from a datagrid and paste to Excel is sufficient , see:
http://www.cflex.net/showFileDetails.cfm?ObjectID=298&Object=File&ChannelID=1
http://mannu.livejournal.com/348299.html#cutid1
If you need the application to generate the excel for you , see: http://cfsilence.com/blog/client/index.cfm/2007/1/24/Exporting-A-Flex-DataGrid-To-Excel
http://www.meutzner.com/blog/index.cfm/2006/12/8/Export-to-Excel-with-Flex-20-and-ColdFusion

3.Internationalizing Flex Apps
http://ajaxdevelopersjournal.com/read/316376.htm
http://mannu.livejournal.com/300260.html

4. Coloring the Background of Cells
http://weblogs.macromedia.com/pent/archives/flex_solutions/index.cfm

5.
Scaling an image with smoothing

blog.739saintlouis.com

6. Unicode support
In order for it to work, you have to make sure
1).your font must support those characters.
2). you need to set the correct fontFamily,
3). you need to set character ranges

Here are couple of simple examples:
http://www.mail-archive.com/flexcoders@yahoogroups.com/msg06651.html
http://www.mail-archive.com/flexcoders@yahoogroups.com/msg41352.htmlMore to come ….

MouseWheel support on MacOS X

It seams that flex is unable to receive the MOUSE_WHEEL MouseEvent on Mac computers. This is because Flash MouseWheel is not supported on Mac by default. This has been submitted as an enhancement request already. At the meantime, there are add-on examples you can consider. See one of them here:

http://reefscape.net/?p=13

http://blog.pixelbreaker.com/2006/11/08/flash/swfmacmousewheel/

How to access cfc on your Coldfusion server from flex app on a separate server.

Coldfusion 7.0.2 added flex feature support, hence you can access your cfc service from flex app. See a good article by Kyle about how this works at here.

The above article described how to access cfc using RemoteObject in flex app when your cfc and mxml pages are both on the same Coldfusion server. If you have your cfc services in an existing Coldfusion app, and you want to create new flex app on a remote server, how do you access the existing cfc services now? Here we will go through the steps to make that configuration work.

The reason the example works in above article is because CF 7.0.2 implemented gateway to access AMF, and by default a destination/channel is defined in CF app WEB-INF/flex/services-config.xml. When running the flex app on a remote server, we will need to use flex app gateway instead, and configure destination/channel in the flex app.

Let us use the example in the above article http://www.adobe.com/devnet/flex/articles/helloworld.html, download helloworld_cfc.zip to your machine.

1. Extract HelloWorld.cfc to your Coldfusion app root. For me, it is C:\flex\jrun4\servers\cfusion\cf702. Here, cfusion is a server instance, /cf702 is the context root. It uses port 8300.

2. Extract folder HelloWorld_ro to your flex app root. For me, it is C:\flex\jrun4\servers\default\samples2, default is a server instance, /samples2 is the context root. It uses port 8700.

3. Copy the following and Paste it into your flex app WEB-INF/flex/remoting-config.xml, inside the <service> tag, parallel to other destination tag.

<destination id=”ColdFusion”><channels> <channel ref=”my-cfamf”/> </channels> <properties> <source>*</source> </properties> </destination>

4. Copy the following and Paste into your flex app\’s WEB-INF/flex/services-config.xml, inside <channels> tag, parallel to other channel-definition.

<channel-definition id=”my-cfamf” class=”mx.messaging.channels.AMFChannel”> <endpoint uri=”http://{server.name}:{server.port}{context.root}/flex2gateway/” class=”flex.messaging.endpoints.AMFEndpoint”/> <properties> <polling-enabled>false</polling-enabled> <serialization> <instantiate-types>false</instantiate-types> </serialization> </properties> </channel-definition>

5. Define your endpoint. You can configure the destination in servicees-config.xml. See above channel-definition you just added. You can change uri=”http://{server.name}:{server.port}{context.root}/flex2gateway/” to point to your real server name and port. For this example, it is http://linIp:8300/cf702/flex2gateway.

Or you can override it in your RemoteObject tag:

<mx:RemoteObject endpoint=”http://linIp:8300/cf702/flex2gateway/”
id=”myService”
destination=”ColdFusion”
source=”HelloWorld”><mx:method name=”sayHelloString” result=”handleStringResult(event)” fault=”Alert.show(event.fault.message)” /></mx:RemoteObject>

6. Make sure both Coldfusion and flex server are running.

7. run HelloWorld_ro.mxml either from flex builder or by request
http://localhost:8700/samples/HelloWorld_ro/ HelloWorld_ro.mxml,
you should see a button with label "get String Remote Object", click on it, you should see "Hello World!" displayed on top of the button.

8. If you are using standalone Coldfusion with default install, then put HelloWorld.cfc under C:\CFusionMX7\wwwroot. Note the context root now is /. If you are using port 8500 for this server, then your endpoint would be:
endpoint=”http://linIp:8500/flex2gateway/”

Note, step 3 to step 6 is to configure channel in the configuration files. You can also assign channels on the client at run time by creating a ChannelSet object that contains one or more Channel objects, and assigning the ChannelSet to a service componen. See flex doc for details.