Recently in Flex Category

using webtier compiler with flex 3

| 15 Comments

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

| 48 Comments

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

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

| 132 Comments

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

Recently, I got a request to provide a sample to pass different dataProvider to the same CellRenderer used in multiple columns of a DataGrid. i.e., there are multiple columns in a DataGrid that need to use the same ComboBox CellRenderer. However, the dataProvider for each of the column needs to be different. Obviously, there are several ways to do this. Here I will show two of them.

1. The first approach is tightly couple the main app and the CellRenderer.
This approach requires the CellRenderer has knowledge about the parent document. It define the different dataProvider in the main app for each column CellRenderer, and then the CellRenderer will fetch dataProvider and set the dataProvider of the ComboBox in setValue() based on the column Index we get from getCellIndex().columnIndex like this:

function setValue(str:String, item:Object, sel:Boolean) : Void
{ //Get values from the dataProvider
combo._visible =(item!=undefined);
if (item!=undefined){
var ind = getCellIndex().columnIndex;
trace ("ind="+ind);
if (ind==0) {
combo.dataProvider = parentDocument.nameDP;
} else if (ind==1){
combo.dataProvider = parentDocument.phoneTypesDP;

}
combo.selectedIndex = item.phoneTypes.index;
}
rowData = item;
size();
}
See sample passDiffDP.mxml and the cellrenderer passDiffDPCell.mxml.


2. The second approach is to create a generic CellRenderer.
If you want to have a generic CellRenderer that is not tightly coupled with the parent app, then you should not set dataProvider in the CellRenderer. Instead, you should have the parent document telling the cell renderer what the data provider is for a given column. In this way, the combo CellRenderer class can be generic and could be used by any application.

There should be different ways to create generic CellRenderer, but extending the DataGridColumn works pretty well for me.
The only thing that’s needed in the extended class is a dataProvider String. The code is as simple as the following:

class myDataGridColumn extends mx.controls.gridclasses.DataGridColumn
{
var dataProvider:String;
}

Now the new DataGridColumn will take a property dataProvider, so you can pass individual dataProvider to each column like this:
<myDataGridColumn dataProvider="nameDP" columnName="name" headerText="Name" cellRenderer="{passDiffDPCellFromMain}" editable="true"/>
<myDataGridColumn dataProvider="phoneTypesDP" columnName="phoneTypes" headerText="Phone Type" cellRenderer="{passDiffDPCellFromMain}" editable="false"/>

For more details, see sample code:
passDiffDPFromMain.mxml

passDiffDPCellFromMain.mxml

myDataGridColumn.as