Tuesday, September 15, 2009

Flex : Downloading a Binary (Excel) File

Context:
It was surprising for me to know that flex calls like navigateToURL(urlReq,"_self"); are stateless calls. This essentially means that I cannot attach a listener or hook my custom method calls upon events. So, if you are trying to download a dynamically generated binary file using Flex and want the UI to notify the user of any errors / progress of the operation, you cannot.

Finding the solution wasn't straight forward - I noticed a hand ful of developers asking the same question on various forums. Here is how I have solved this problem.

The Approach:
There were two approaches to solve this problem at high level.

  1. Use serverside component to catch all the errors (including throwable- if you are using Java) and spool it as part of the response OR generated file. However, this is not a fool proof approach coz it will not be able to handle error conditions like server going down or network error etc.
  2. Better approach would be to leverage FileReference class that comes bundled with Flex. This will allow users the download the file from a URL. One can also pass parameters while creating URLRequest in case the file needs to be generated dynamically (which was precisely the case for us)

The code that does the trick:









01 private var fileRef:FileReference;
02 private var popupPanel:Panel=null;
03 private function sendRequest():void
04 {
05 var urlStr:String = "/myWebService/services/GenerateFile"
06 urlStr = urlStr + "?param1=someValue1";
07 urlStr = urlStr + "&param2=someValue2";
08 urlStr = urlStr + "&param3=someValue3";
09 urlStr = urlStr + "&param4=someValue4";
10 urlStr = urlStr + "&param5=someValue5";
11
12
13 initPopup();
14
15 try
16 {
17 var urlReq:URLRequest = new URLRequest(urlStr);
18 urlReq.method = URLRequestMethod.GET;
19
20 fileRef = new FileReference();
21 fileRef.addEventListener("complete", commpleteHandler);
22 fileRef.addEventListener("open", showPopup);
23 fileRef.download(urlReq, reportType.text+".xls");
24 }
25 catch(error:Error)
26 {
27 Alert.show("Could not generate file", "Error");
28 }
29 }
30
31 private function initPopup()
32 {
33 var vb:VBox = new VBox();
34 vb.setStyle("paddingBottom", 5);
35 vb.setStyle("paddingLeft", 5);
43 vb.setStyle("paddingRight", 5);
44 vb.setStyle("paddingTop", 5);
45 vb.percentHeight=100;
46 vb.percentWidth=100;
47
48 popupPanel=new Panel();
49 popupPanel.width=this.parentDocument.width / 2;
50 popupPanel.height=this.parentDocument.height / 5;
51
52 popupPanel.x = this.parentDocument.parentDocument.width / 3
53 popupPanel.y=this.parentDocument.parentDocument.height / 3;
54
55
56 var reportStatus:Label = new Label();
57 reportStatus.text="Please wait while file is generated.";
58 reportStatus.move(100, 100)
59
60 vb.addChild(reportStatus);
61
62 var cancelButton:Button = new Button();
63 cancelButton.setFocus();
64 cancelButton.label="Cancel";
65 cancelButton.x = popupPanel.width/2 - 40
66 cancelButton.y = popupPanel.height/2 - 20
67 cancelButton.addEventListener(MouseEvent.MOUSE_UP, cancelHandler);
68 vb.addChild(cancelButton)
69
70 popupPanel.title = reportType.text + " Status"
71 popupPanel.addChild(vb);
72 }
73
74 private function cancelHandler(event:Event):void
75 {
76 try
77 {
78 fileRef.cancel();
79 PopUpManager.removePopUp(popupPanel);
80 }
81 catch(error:*)
82 {
83 Alert.show"Could not cancel the file generation.", "Error");
84 }
85 }
86
87 private function commpleteHandler(event:Event) : void
88 {
89 PopUpManager.removePopUp(popupPanel);
90 }
91
92 private function showPopup(event:Event) : void
93 {
94 PopUpManager.addPopUp(popupPanel,this,true);
95 }




A few things to keep in mind:

  1. The code above uses only two types of listeners "complete" and "open" - you may want to use various other events supported here e.g. "progress", "select" etc
  2. The code above demonstrates the functionality - may have not been coded the best :)



Flip Side of using FileReference:

One flip side I have noticed about this implementation is the File Save As dialogue box (attached a screenshot below. This dialogue may turn out to be annoying for users where they just want to download the

Another thing to keep in mind is that when clicked cancel button in the code sample above - if a time consuming process was invoked at the server side - it will not interrupt. The method call - fileRef.cancel() method will only cancel the HTTP request. Application server will not be able to identify this and halt the process it started upon receiving the request

Conclusion:

If there is a requirement to track the state of the URL call and build functionality dependent on it (e.g. showing progress bar etc.) FileReference object e.g. showing the progress bar for file being downloaded or notify user of the HTTP Errors or a server side error in the file generation if this was for a dynamically created binary file based on user request

Tuesday, August 18, 2009

Perl : Finding Installed Modules in Perl

Context:
I was working on a solution to upload data from an excel file - that contains macros - using Perl. Perl is a module based implementation of parsing langugage and has a different module used for Windows / Linux based implementation for parsing / creating excel files (Win32::OLE->GetActiveObject('Excel.Application') viz. Spreadsheet::ParseExcel )

Perl file would work on Windows environment but not on Linux. I will not get into the details what the error message I got and what does it means for now.

Commands to list Perl modules:
After a while of googling - I figured out following one line script that will list all the Perl modules installed on Linux environment.

perl -MFile::Find=find -MFile::Spec::Functions -lwe 'find { wanted => sub { print canonpath $_ if /\.pm\z/ }, no_chdir => 1 }, @INC'

here is the same command to for Windows:
perl -MFile::Find=find -MFile::Spec::Functions -lwe find { wanted => sub { print canonpath $_ if /\.pm\z/ }, no_chdir => 1 }, @INC
Nothing much has changed other than double quotes highlighted in red.

An Alternate Way:
One can also try executing following command to fetch the details. If there is an error while execuing command, it means the module is not installed.

perl -MSample::Module -e 'print "\nModule is Installed\n\n"'

sample output - installed module:
bash-3.2$ perl -MExtUtils::Installed -e 'print "\nModule is Installed\n\n"'
Module is Installed
bash-3.2$


Sample output - module that is not installed:
bash-3.2$ perl -MSpreadsheet::ParseExcel -e 'print "\nModule is Installed\n\n"'
Can't locate Spreadsheet/ParseExcel.pm in @INC (@INC contains: /usr/lib64/perl5/site_perl/5.8.8/x86_64-linux-thread-multi ... /usr/lib64/perl5/5.8.8/x86_64-linux-thread-multi /usr/lib/perl5/5.8.8 .).
BEGIN failed--compilation aborted.
bash-3.2$

Hope this helps . . .

Thursday, August 13, 2009

Blogger : Code formatting support and Blogger

It would be difficult for someone like me - being a software developer - to eschew from writing technical blog. It is a best practice to share the code and give example wherever possible. I started blogging recently and as it appears, lack of ability to format the code is becoming a major hold up for me to document every day learning if not sharing.

I am more of switching from Wiki to Blogging - and hence this problem, but there seems to be a scope for development if one can do. I have been a big fan of wiki. I absolutely love how smart macros does it offer and do all the hard I hate it when it comes to writing some code and 'Ctrl + Shft + F' short cut doesn't work. How dependent I have become on the editors is a topic - not for today's blog.

Syntax highlight is a very basic feature - I would use it day in and day out. I don't get it on blogger! I have to go to some sites to covert the code to HTML first and then replace all the HTML tags to comply with the standards.

One more thing which I miss is excel macros in WiKi. It just doesn't get limited there. Wiki seems to offer a pluggable framework. I have seen people add their own macros for various applications.

Reference Material:
Some sites I have found while I re-searched this subject online are:
  1. Java 2 Html tool converts java code into HTML and is available as online applet http://www.java2html.de/
  2. Built on Java2Html but offers a way to covert esp. flex action script code in HTML with syntax highlight. http://keg.cs.uvic.ca/flexdevtips/java2html/
  3. explains how to get formatting up and running on your blogger account http://codeblog.kello.se/2009/01/07/getting-code-formatting-with-syntax-highlighting-to-work-on-blogger/
  4. If you want an HTML based tool - here is one for you. However, the flip side is that it cannot highlight the code - http://codeformatter.blogspot.com/2009/06/about-code-formatter.html
  5. Something that I have read about but not tried - http://www.manoli.net/csharpformat/
Conclusion:
Blogger may not be an obvious choice of a technology geek! There are some basic features, I would like to see before I find it addictive!

Tuesday, August 11, 2009

Java : Garbage Collection

Context:
I got a query - how does garbage collection work in Java? This was the time I started gathering details by means of googling. The details compiled here are based on my research online. Please note that the question I was asked about is very generic - and the details below touch upon the topic at very high level.


What is a Garbage collection?
Garbage collection is a mechanism in java which works on mark and sweep basis and relives programmers from spending time in writing code to claim back the memory allocated to the objects.

The mechanism also is part of Java's security strategy. It will prevent current program to crash JVM instance by means of memory hazards.

This service of course doesn't come free, it causes a small overhead since the process has to be continuously running in the background. However, keep in mind that scale of the application will determine the magnitude of overhead caused by this process.

How it works?

Garbage collector will iterate over all the available objects. The ones which are left out are marked for garbage collection. In the sweep stage, Garbage Collector deletes the objects for which the heap space was allocated and make it available to executing program.

Garbage collector will determine eligibility of an object by measuring its "reachability" from the root node. Any objects which are referred to by a root is a live object. Subsequently any objects referred to by a live object is also considered live object. Objects which are not reachable are dead and will be removed from heap space.

There are algorithms used by Garbage collectors to mark "reachable" objects abut it would be a subject in itself to learn more about them.

Garbage Collection Strategies

The garbage collectors might use Compacting and Copying strategies to deal with heap fragmentation.

What are generations?

Generations refer to the life span of the variables. Local variables for example are the most short lived ones and will be the first ones to be identified and claimed back. They are called young generations. Old generations are the objects which survive across multiple collections. Old and Young generations symbolize the memory pool available to store such objects.

When young generations are filled up, it causes minor collection and when tenured generation pool will cause Major Collection to occur. Note that later is much a slow process considering the fact that it involves all live objects

Java program is allocated heap space. Every thread is allocated a separate stack of functions and stacks reside in Heaps. Local variables are part of stacks.

Conclusion:

Although JVM encapsulates memory management under the hood - knowing how it works will make the developers write code more consciously keeping scalability in mind.

More (Technical) resources:

  1. Command line parameters which come for JMV's performance improvement are described by Sun here: http://java.sun.com/javase/technologies/hotspot/vmoptions.jsp
  2. The details on how to performance tune Garbage Collection in java 1.5 is given here - http://java.sun.com/docs/hotspot/gc5.0/gc_tuning_5.html

Flex : Making flex application full screen

Context:
While performing unit testing of a new module I was transition a couple months back, I figured out a problem. The button that read "Toggle Full Screen" did not work how it should have i.e. it didn't switch between browser and full screen mode.

Why full screen doesn't work?
RTFM still holds true. None really read the manual to make it work. Merely copy pasting the code from Adobe example / sample code doesn't work!!

One needs to make changes in the java script / html templates as they are the ones which will initialize flash player and allow it to run or not run in full screen mode.

How to make it work?
You may want to walk thru following steps to verify all the elements to make flex application full screen are in place

  1. You must have version 9,0,28,0 or later of Flash Player installed to use full-screen mode and 9,0,115,0 or later for hardware-scaled full-screen mode (You can check it here - http://kb2.adobe.com/cps/155/tn_15507.html)
  2. Check if index.template.html contains reference to AC_FL_RunContent function.
  3. If yes, update the function to also include following pair of parameters
    AC_FL_RunContent(
    "src", "${swf}",
    "width", "${width}",
    "height", "${height}",
    "align", "middle",
    "id", "${application}",
    "quality", "high",
    "bgcolor", "${bgcolor}",
    "name", "${application}",
    "allowScriptAccess","sameDomain",
    "type", "application/x-shockwave-flash",
    "pluginspage", href="http://www.adobe.com/go/getflashplayer">http://www.adobe.com/go/getflashplayer, "allowFullScreen", "true"
  4. Update <object> tag in index.template.html to include parameter allowFullScreen and set its value to "true" <param name="allowFullScreen" value="true" >
  5. If you are using <embed> tag - you need to update it to set value of allowFullScreen attribute to true e.g. <embed
    src="${swf}.swf" quality="high" bgcolor="${bgcolor}"
    width="${width}" height="${height}" name="${application}" align="middle"
    play="true"
    loop="false"
    quality="high"
    allowScriptAccess="sameDomain"
    type="application/x-shockwave-flash"
    pluginspage="http://www.adobe.com/go/getflashplayer"
    allowFullScreen="true" />
  6. The flex code is in place to toggle the mode from normal to fullscreen and vice versa

Conclusion:

Its easy to miss on trivial things and reading the manual and doing implementation will save clients from going baffled! :-)

Thursday, July 30, 2009

Flex : How expensive pretty looking DataGrids are?

In software world - especially while thriving on Rapid Application Development, people start with prototype development. Under the influence of re-usability - developers land up using the same prototype to build the application framework. At this point in time - probably none would have anticipated the scalability and the volume of data. A small application works like grand-ma and end users get pissed!


Whole gamut of changes has brought the Flex DataGrids to work very slow for an intranet based application.


We ran into this classic case of short-sighted-ness in recent past. Clients came to us frustrated about "performance" of Flex DataGrid implementation in various modules in our application.


While analyzing - we realized that
  1. there were way too many containers used in hierarchical fashion in the layout
  2. Data Grids were using labels for displaying the data and applying dynamic styling
  3. Item Renderer implementation of Labels was such that it would cause
  4. Large amount of data was being transferred over XML from server to the client application

Let's take an example of each of them:

1) Too many contain hierarchies
The way flex layout and children component display works is by applying algorithms to determine x, y position and preferred size and styling. When a flash player runs out of a browser - it is at mercy of memory allocated to browser instance. The more it has to do with limited resources, the more time it will take i.e. degraded performance.


2) Labels as Item renderers in data grids
Think about it from a different perspective. We have a data grid with 45 rows and 28 columns. Based on the display region out of 1260 - required number of label objects will be initialized. The re-draw logic on flex display may invoke various methods on all these object instances even on a mouse move! Even if the execution time for each of them is in milliseconds, multiply it with number of cells visible and you will see how performance degrades.



3) Item renderer implementation

A Label used as ItemRenderer is fine but one has to be mindful of how best to use it? I am sure one cannot call start extending the component by including Label in MXML script and initialize the attribute of Label to cause method calls for colors and text e.g. following declaration may not be a great way to initialize a Label that will be used as itemRenderer.

<mx:Label xmlns:mx="http://www.adobe.com/2006/mxml" color="{(String)(getColorCode(data))}" text="{ getLabelText(data ) }" >


4) Large amount of data transfer between browser and server
Think of a couple of thousands of lines with 38 columns each to be retrieved - be converted to java objects - java objects be converted to XML format - xml be sent to the client - client to parse the xml within memory allocation limits - generate collection of local data types...
There is possibly a scope of improvement 1) to avoid converting the java object to xml and back by switching to binary data transfer and 2) Using a faster data transfer protocols like AMF.

Conclusion:
I would only want to imphasise the importance of giving enough weightage to trivial looking things from beginning and to address the issues in rightest possible way to avoid aging of application and ensuring of scalability.

Tuesday, July 28, 2009

Flex : AdvancedDataGridColumn - problem and solution to make only selected columns editable


Context:

AdvandedDataGridColumn stores list data and stylesheets for AdvancedDataGrid. "editable" is a property of AdvancedDataGridColumn intending to make the column editable or uneditable. When made editable (set editable="true" for the AdvancedDataGridColumn) the cells in the editable column will allow a user to change the cell values by invoking a user specified or default (text) editor in the cell by pressing F2 or with a single mouse click on the cell.

When set a column in AdvancedDataGrid implementation; a user while navigating thru the grid using keyboard will be able to press F2 key and make the cell editable just like Microsoft Excel.

Flex developers will not realize the issue till the time requirement is around implementing something simple. The moment one has to make only selected columns editable; the problem will surface up.

The problem:
When pressed F2 when the datagrid cell is selected, irrespective of editable propertly set to false, column will become editable.
This issue is acknowledged by Adobe Fex but still waiting to be fixed at Adobe's end. Take a look at following URL for more details on this issue - http://bugs.adobe.com/jira/browse/FLEXDMV-2084

Solution at High Level:
My approach to solution was to utlize the event propagation to intercept the keyboard event and hoook my validation to decide if the event should be prevented or allowed.

1. Trap the keyboard event on AdvancedDataGrid
2. Validate if the column isEditable
2.1 if yes: let the control flow thru the business logic to update the cell
2.2 if no: prevent the event propagation further

Implementation Details:
I would want a custom function to be invoked before making the cell editable.

AdvancedDataGrid allows this by letting you specify method name as value of itemEditBeginning attribute in AdvancedDataGrid declaration.

It might look something like this:

validateColumnEditability(event)" selectionMode="multipleCells" editable="true" />

Implementation of validateColumnEditability() might look something like:

public function validateColumnEditability(event:AdvancedDataGridEvent):void
{
if(event.dataField == "allowedCol1" event.dataField== "allowedCol1" ...)
{
//this will return the control and make the column editable
return;
}
else
{
//This will prevent event from being propagated thru the stack
event.preventDefault();
}
}

Further Improvements:
The list of the editable can be made a collection and performing look up on the collection would be much easier / better than string coparison
The function can be coded in utility class as static function (this will require you to import the utility class and invoke this static method.

Please note:
Above code defines the approach to fix the problem and not the best way to code