Code I/O

A topnotch site

Leave a comment

5 Minutes on Adobe Flex: Marshalling AS3 Object to XML

Here is a handy method that can quickly convert AS3 Object to XML.

		public static function objectToXML(object:Object, qualifiedName:String):XML
			var qName:QName = new QName(qualifiedName);
			var xmlDocument:XMLDocument = new XMLDocument();
			var simpleXMLEncoder:SimpleXMLEncoder = new SimpleXMLEncoder(xmlDocument);
			var xmlNode:XMLNode = simpleXMLEncoder.encodeValue(object, qName, xmlDocument);

			return new XML(xmlDocument.toString());


5 Minutes on Adobe Flex: Server Push with FUSE (ActiveMQ) and BlazeDS

Working in a fast paced environment demands everything to be quick.  Adobe Flex has been our choice to create rapid prototypes; In this post, I want to give a step-by-step guide to setup Server Push simulation using FUSE message broker on the server side and BlazeDS on the Adobe Flex side.

Here is what you require to start:

  • Download and install FUSE message broker: Installed at FUSE_HOME (C:progressfuse-message-broker-5.3.1-02-00)
  • Download and install Apache Tomcat: Installed at TOMCAT_HOME (C:Program FilesApache Software FoundationTomcat 5.5)
  • Download BlazeDS: Put the blazeds.war file into TOMCAT_HOME/webapps

You need the following files from FUSE_HOME/lib/web and FUSE_HOME/lib; Copy them into TOMCAT_HOME/shared/lib


After the primary components are installed and the dependent libraries copied; we’re set to ready to configure the system for server push; Follow the steps in the same order in which it is illustrated to keep it easy.

Create a new file “blazeds.xml” file in TOMCAT_HOME/conf/Catalina/localhost

<?xml version="1.0" encoding="UTF-8"?>
<Context path="blazeds">
    <Resource name="jms/flex/TopicConnectionFactory"
        description="JMS Connection Factory"

    <Resource name="jms/feedMessageTopic"
        description="a simple topic"

Here, the resources for JMS are defined.   The TopicConnectonFactory is bound to the broker, which is used by BlazeDS to manage the communication.  The feedMessageTopic is the internal BlazeDS reference to a topic named “flex-client-broadcast-topic” which will be created on the ActiveMQ platform.  From the FUSE admin window, we can send a message to topic “flex-client-broadcast-topic” and see that in the flex app.

Making BlazeDS function with JMS: The following files must be updated correctly, observe the topic name, it must be consistent; which is a must to get the server push should work seamlessly.

Edit TOMCAT_HOME/blazeds/WEB-INF/web.xml; add the following lines to web-app container

        <description>Connection Factory</description>


The above configuration binds the BlazeDS web-app to the JMS resources created in the context definition.

Edit TOMCAT_HOME/blazeds/WEB-INF/flex/messaging-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<service id="message-service"

        <adapter-definition id="actionscript" class="" default="false" />
        <adapter-definition id="jms" class="" default="true"/>

        <channel ref="my-polling-amf"/>

    <destination id="flex-client-broadcast-topic">

		<channel ref="my-polling-amf"/>
		<channel ref="my-streaming-amf"/>
		<channel ref="my-amf"/>

        <adapter ref="jms"/>

The messaging-config.xml hooks up the BlazeDS and JMS adaptors to work correctly.  Focus on the destination id “flex-client-broadcast-topic” this must match the physical name used during the context definition.  As well, BlazeDS JMS messaging is done via “my-polling-amf“.  This is the channel responsible for streaming content to the flex app, hence it is a must to be defined in “services-config.xml”.

Edit TOMCAT_HOME/blazeds/WEB-INF/flex/services-config.xml; add the following channel information

        <channel-definition id="my-streaming-amf" class="mx.messaging.channels.StreamingAMFChannel">
            <endpoint url="http://{}:{server.port}/{context.root}/messagebroker/streamingamf" class="flex.messaging.endpoints.StreamingAMFEndpoint"/>

When all the configuration changes are done, we can boot up the processes required for this setup to work, and can see the server push in action.

launch FUSE_HOME/bin/activemq.bat

restart tomcat

open a browser and launch the URL http://localhost:8161/admin/topics.jsp

At this point of time, if you observe the list of topics, you should see the topic name “flex-client-broadcast-topiclisted with 1 consumer connection to it.  If you’ve reached this point, you’re set for the next step.

Create a simple Flex App (FeedClientApp.mxml)

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="" layout="absolute" creationComplete="onAppCreated(event)">


		import mx.collections.ArrayCollection;

		private var entries:ArrayCollection = new ArrayCollection();

		private function onAppCreated(event:Event):void{

		private function messageHandler(event:MessageEvent):void{
			var xml:XML = new XML(event.message.body as String);

		private function onConnect(event:Event):void{

	<mx:Consumer id="consumer"

	<mx:List dataProvider="{entries}" width="100%" height="100%" labelField="label"/>

  • Compile and run this piece of code.
  • Go to http://localhost:8161/admin/send.jsp?JMSDestination=flex-client-broadcast-topic&JMSDestinationType=topic
  • Send a message body as follows: <item><label>SAP</label></item>
  • You should now see “SAP” render in the list.

In the next post I’ll show the producer component which can be developed independently.


5 Minutes on Technology: Comparison of RIA technologies

HTML5, Flash, Silverlight, CURL are few of the technologies available for Rich Internet Applications.  Flash is mature, Silverlight is evolving, CURL is less known and the newbie HTML5 is being pushed higher and higher everyday by Apple and Google.  The expectations are higher on HTML5.

It is just a matter of time until all features of HTML5 are available in all modern browsers 😉 Google Chrome implements most of the features and is a good candidate to evaluate core features.

I’ve compared Flash, Silverlight and HTML5 to find a good contender.  My finding is that all technologies are very competent in terms of features and hence making a right choice is upto the customer demands.  However, if one wants to go by standard features (HTML) and stay away from proprietary technologies, HTML5 is a good bet and a long term strategy.

Here is the comparison matrix on google spreadsheet.

Thanks for stopping by and checking out the matrix.  If you have any suggestions/comments please pass it on so that I can incorporate them after evaluating it.

Leave a comment

5 minutes on Adobe Flex: A service proxy pattern for applications

The process of communication involved between Rich Internet Applications and Server components is very repeatable:

  • Sending request to server
  • handling its result or fault, and
  • finally processing the result for the application to provide desired functionality

The process involves invoking services and handling responses individually, One can think of simplifying the process by introducing the Service Proxy pattern, which becomes handy to manage the entire application specific communications.

The benefit of this pattern is that, one can process results specifically with respect to business logic at the same time having a unified interface to manage server side interactions.

package service
 import mx.controls.Alert;
 import mx.rpc.http.HTTPService;

 public class ServiceProxy
 private static var SERVICE_URL:String;
 public static function getURL():String{
 return SERVICE_URL;
 public static const TERMS_AND_CONDITIONS_PAGE:String = "/sub_tac.html";

 public function ServiceProxy()
 throw new Error("ServiceProxy cannot be instantiated");

 public static const CHECK_SUBSCRIBER:String     = "CHECK_SUBSCRIBER";
 public static const LOAD_DICTIONARY:String         = "LOAD_DICTIONARY";
 public static const SUBSCRIBE:String             = "SUBSCRIBE";
 public static const UNSUBSCRIBE:String             = "UNSUBSCRIBE";

 private static function init():void {
 {script:"/php/load_dictionary.php",         method:"GET",    success:"", failure:""});

 {script:"/php/change_subscriptions.php",     method:"POST",    success:"/sub_success.html", failure:""});

 {script:"/php/check_subscriber.php",         method:"POST",    success:"", failure:""});

 {script:"/php/subscribe.php",                 method:"POST",     success:"/sub_success.html", failure:""});

 {script:"/php/unsubscribe.php",             method:"POST",    success:"/unsub_success.html", failure:""});

 private static var registry:Object = null;
 public static function getObjectByTag(tag:String):Object{
 if(registry == null){
 registry = {};


 return registry[tag];

 public static function register(handle:String, object:Object):Boolean {
 registry[handle] = object;
 return true;

 return false;

 public static function execute(tag:String, xml:XML=null, callback:Function=null):void {
 var o:Object = getObjectByTag(tag);
 if(o == null){
 throw new Error(tag + " is not supported currently!!");

 var s:HTTPService = new HTTPService();

 s.url = SERVICE_URL + o.script;
 s.method = o.method;
 s.contentType = HTTPService.CONTENT_TYPE_XML;
 s.resultFormat = HTTPService.RESULT_FORMAT_E4X;

 if(xml != null){
 s.request = xml;

 function resultHandler(event:ResultEvent):void
 var xml:XML = XML(event.result);

 trace("RESULTn" + xml);
 if(callback != null){

 function faultHandler(event:FaultEvent):void
 trace("ERROR: " + event.message);"Error communicating to server, try again later", "Communication Fault");


 public static function initFromURL():void
 var url:String = FlexGlobals.topLevelApplication.url;
 var protocol:String = "http";
 var server:String = "";
 var port:String = "8085";
 var prefix:String = "/referral-network";

 if ("file://") >= 0)
 var i:int = url.indexOf("://");
 if (i >= 0) {
 protocol = url.substring(0, i);

 url = url.replace(protocol + "://", "");
 url = url.substring(0,"/"));

 var array:Array = url.split(":");
 if (array.length >= 1)
 server = array[0];
 if (array.length >= 2)
 port = array[1];
 if (protocol != null && protocol == "https")
 port = "443";
 port = "80";

 SERVICE_URL = protocol + "://" + server + ":" + port + prefix;

Here is a simple usage of the pattern

public function unSubscribe():void{
	var xml:XML = <input />;

	var profile:XML = <profile />;

	trace("DATA TO SEND: " + xml);
	ServiceProxy.execute(ServiceProxy.UNSUBSCRIBE, xml, unsubscribeResultHandler);

private function unsubscribeResultHandler(xml:XML):void{
	// Your Business Logic Here ...

1 Comment

5 Minutes on Adobe Flex: Mimic file upload for in-memory contents …

Ever imagined uploading a file without using FileReference.upload?

In a web-app, access to filesystem is restricted, and at times, there is no need to refer to a file.  However, there may be situation where there is need to persist in-memory contents on servers.

The idea is to send contents from internal buffer which are non-file reference objects.  The fundamental behind  this is to fill in the content headers and mimic fileupload using HTTPService and here is the snippet for spoofing it.

Remember, though one can spoof the file upload, the trigger must be coming from an UI object (like a Button click event), otherwise, Flash will fail to upload the content.

public function spoofFileUpload(inputText:String,
 faultHander:Function=null):void {

 var boundary:String = UIDUtil.createUID();
 var service:HTTPService = new HTTPService();

 service.method = "POST";
 service.contentType = "multipart/form-data; boundary=—————————" + boundary;

 var content:String = "—————————" + boundary + "nr";
 content += 'Content-Disposition: form-data; name="uploadfile"; filename="' + fileName + '";' + "nr";
 content += 'Content-Type: text/plain' + "nrnr";
 content += inputText + "nr";
 content += "—————————" + boundary + "nr";
 content += 'Content-Disposition: form-data; name="Submit"' + "nr" + "Submit" + "nr";
 content += "—————————–" + boundary + "–nr";

 service.request = content;
 service.resultFormat = HTTPService.RESULT_FORMAT_E4X;

 if(faultHander != null){
 service.addEventListener(FaultEvent.FAULT, faultHander);

 if(resultHandler != null){
 function httpResult(event:ResultEvent):void
 var xml:XML = XML(event.result);
 trace("SERVER RESPONSE: " + xml);
 // Invoke your result handler here

 // Send Request


5 Minutes on Adobe Flex – A tutorial on getting Flex and Java to process Microsoft Excel files …

In this 5 minute series, lets look into a scenario of uploading a Microsoft excel file to servlet parse it using Apache POI API to determine possible column type by sampling data in each column.

What you need?
Download Apache POI binaries from and load it into your eclipse environment. Since this example uses Apache fileupload API’s, you’ll also require them from

In a nutshell, the dependent libraries you need is as follows:

Take an Excel file which has the following content (presuming the first row is always a header):
Sample Input spreadsheet

The following listing of CDS_Demo.mxml is to upload file to servlet and get back the columns and possible data type as result.  We’ll try to build more intelligence to find more use of these techniques. For now, the simple basics.

import mx.rpc.http.HTTPService;
			import mx.controls.Alert;
			private var fileReference:FileReference = new FileReference();
			private var FILE_UPLOAD_URL:String = "http://localhost:8080/cdss/upload";

			private function onImportFileButtonClick():void {

			private function doImportFile():void
				var fileFilter:FileFilter = new FileFilter("Data Files (*.txt; *.csv; *.xls)","*.txt;*.csv;*.xls");

			private function onFileSelect(event:Event):void

	  		private function onFileComplete(event:Event):void
	  			importFileName.text =;

			private function onIOError(event:Event):void
			{"Server is Down/Unreachable, Please try again later"
					, "Connection to Server Failed");
			private function processReponse(event:DataEvent):void
	            var dataString:String = (;
	            var xmlData:XML = XML(dataString);
	            var xmlList:XMLList = xmlData.children().children();
	            dataGrid.dataProvider = xmlList;

			private function onParseFileButton():void
				fileReference.addEventListener(DataEvent.UPLOAD_COMPLETE_DATA, processReponse);
				fileReference.addEventListener(IOErrorEvent.IO_ERROR, onIOError);
	  			fileReference.upload(new URLRequest(FILE_UPLOAD_URL));

<mx:VBox height="100%"  verticalAlign="top">
 <mx:Spacer />
 <mx:HBox width="100%" verticalAlign="middle">
 <mx:Text  text="Select File" />
 <mx:TextInput id="importFileName" width="485" editable="false"/>
 <mx:Button id="importFileButton" label="..." click="onImportFileButtonClick()" width="36"/>
 <mx:Button id="parseFileButton" label="Suggest" click="onParseFileButton()"/>

 <mx:DataGrid id="dataGrid" width="672" height="50%">
 <mx:DataGridColumn headerText="Column Name" dataField="@name" width="200"/>
 <mx:DataGridColumn headerText="Data Type" dataField="@type" width="100"/>
 <mx:DataGridColumn headerText="Sample" dataField="@value" width="100"/>

The above code will get the response XML and display them in a datagrid. Once you get the idea on how to do this, you can play around with the API and explore more.

The following code illustrates how Apache POI, specifically HSSF API – I like the way it’s named “Horrible” 😉 Pun aside, I really appreciate how Apache has put this together to help developers work with hetrogenous environments and find solutions that will just work 🙂

This is how the web.xml looks

 <display-name>CDS upload service</display-name>




Here is the full source listings of servlet code:

package net.foss.cdss.service;

import java.util.Properties;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.foss.cdss.domain.Constants;
import net.foss.cdss.utils.FileUploader;
import net.foss.cdss.utils.FileUtils;

import org.apache.log4j.PropertyConfigurator;

public class FileUploaderServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private static String fileStorePath = null;

public FileUploaderServlet() {

public void init(ServletConfig config) throws ServletException {

Properties loggingProperties = new Properties();
loggingProperties.setProperty(“log4j.rootLogger”, “debug, A1”);
loggingProperties.setProperty(“log4j.appender.A1”, “org.apache.log4j.ConsoleAppender”);
loggingProperties.setProperty(“log4j.appender.A1.layout”, “org.apache.log4j.PatternLayout”);
loggingProperties.setProperty(“log4j.appender.A1.layout.ConversionPattern”, “%d{ABSOLUTE} %5p %c{1}:%L – %m%n”);

fileStorePath = (config.getInitParameter(Constants.FILESTORE_PATH));
if(null == fileStorePath) {
throw new ServletException(“Check web.xml init-param property for ” + Constants.FILESTORE_PATH + ” it is either missing or is not defined correctly”);


protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
FileUploader fileUploader = new FileUploader(request, response);

package net.foss.cdss.domain;

public class Constants {
public static final String FILESTORE_PATH = “net.foss.cdss.filestore”;

package net.foss.cdss.utils;


public class MyFileUtils {
public static boolean fileExists(String fileName){
File simpleFile = new File(fileName);

public static void createNonExistantDirs(String dirName){
File dir = new File(dirName);

public static void deleteDirectory(String dirName){
FileUtils.deleteDirectory(new File(dirName));
catch( Exception e ) {

package net.foss.cdss.utils;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.log4j.Logger;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;

public class FileUploader {
private static final Logger logger = Logger.getLogger(FileUploader.class.getName());

private String uuid = null;
private HttpServletRequest request = null;
private HttpServletResponse response = null;

public class ResponseData{
public String name;
public String type;
public String value;

public ResponseData(String name, String type, String value){ = name;
this.type = type;
this.value = value;

public FileUploader(HttpServletRequest request, HttpServletResponse response) {
this.request = request;
this.response = response;

this.uuid = UUID.randomUUID().toString();

public void uploadFilesTo(final String fileStorePath) throws ServletException, IOException {
List fileItems = new ServletFileUpload(new DiskFileItemFactory()).parseRequest(request);
if(fileItems == null){
logger.debug(“uploadFilesTo: No fileitems from client!”);


Iterator fileIterator = fileItems.iterator();

FileItem fileItem = (FileItem);
if(fileItem == null){
logger.debug(“uploadFilesTo: null fileItem cannot be processed”);

// definitely not a form item
if(!fileItem.isFormField()) {
String uploadPath = fileStorePath + File.separator + uuid;
File fileWorkingOn = new File(uploadPath + File.separator + fileItem.getName());

if(fileWorkingOn == null){
logger.debug(“uploadFilesTo: File Path null!”);
else {
logger.debug(“uploadFilesTo: fileStorePath = ” + fileWorkingOn.getAbsolutePath());


catch( Exception e ) {
logger.error(“uploadFilesTo: Exception during uploadFilesTo”);

private void sendResponse(HashMap hm){
Iterator iterator = hm.keySet().iterator();

StringBuffer buff = new StringBuffer();

while(iterator.hasNext()) {
String key =;
ResponseData rd = hm.get(key);

buff.append(“” +
+ “”);

logger.debug(“xml = ” + buff);

response.setDateHeader(“Expires”, 0);
try {
ServletOutputStream out = response.getOutputStream();
} catch (IOException e) {
logger.debug(“Exception obtaining outputstream”);

private void processFile(String fileName){
try {
FileInputStream fis = new FileInputStream(fileName);

// Treat input as Excel File
HSSFWorkbook wb = new HSSFWorkbook(fis);

// Take first sheet
HSSFSheet sheet = wb.getSheetAt(0);

// Read first row to sample data
HSSFRow headerRow = sheet.getRow(0);
HSSFRow dataRow = sheet.getRow(1); // Assuming data exists for sampling

HashMap pairs = new HashMap();

// Read each cell content and print it out.
for(int cellnum = 0; cellnum < headerRow.getLastCellNum(); cellnum++){
HSSFCell headerCell = headerRow.getCell(cellnum);
HSSFCell dataCell = dataRow.getCell(cellnum);

// Assume first row is always a header row
String colHeader = headerCell.getRichStringCellValue().toString();
logger.debug("row = " + headerRow.getRowNum() + " col = " + cellnum + " content = " + colHeader);

// Try different types
if(dataCell.getCellType() == HSSFCell.CELL_TYPE_NUMERIC){
// Uses column header to determine if it’s date
if(colHeader.toLowerCase().contains(“date”)) {
String DATE_FORMAT = “dd-MM-yyyy”;
SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
pairs.put(colHeader, new ResponseData(colHeader, “DATE”, “” +
else {
pairs.put(colHeader, new ResponseData(colHeader, “NUMERIC”, “” + dataCell.getNumericCellValue()));
else if(dataCell.getCellType() == HSSFCell.CELL_TYPE_STRING){
pairs.put(colHeader, new ResponseData(colHeader, "STRING", dataCell.getRichStringCellValue().toString()));
else if(dataCell.getCellType() == HSSFCell.CELL_TYPE_BOOLEAN){
pairs.put(colHeader, new ResponseData(colHeader, "BOOLEAN", "" + dataCell.getBooleanCellValue()));
else {
pairs.put(colHeader, new ResponseData(colHeader, "UNDETERMINED", ""));

} catch (FileNotFoundException e) {
logger.debug("File " + fileName + " does not exist!");
} catch (IOException e) {
logger.debug("IOException while reading " + fileName);

Once everything is working, here is the output that will be generated, hope this was fun for you …
Sample output

1 Comment

5 Minutes on Adobe Flex – Is flex for future web …

Adobe Flex is a lightweight cross-platform SDK, which enables the creation and deployment of rich-client applications. Flex is based on Adobe Flash, and with the addition of Flex Data Services, developers can integrate these rich clients with J2EE server side applications.

This document briefly outlines how Flex can offer a useful addition to the current enterprise application landscape.


Consider the following routine developer requirements:

  • develop an enterprise/web application
  • expose the power of back-end functionality
  • provide a rich client that can deliver a ‘WOW’ factor

While these may be routine activities, the ongoing drive towards efficient and agile development means that there is a constant demand for better solutions.

If one takes a simple client-server architecture, a number of options are available.


Server Side

A variety of technology combinations are available on the server-side, from a fully Open Source stack like Linux-Apache-MySQL-PHP to vendor-specific proprietary implementations using Websphere, WebLogic, DB2, Oracle, SQLServer, etc.

These back-end solutions often provide powerful business solutions, but to truly empower end users, developers must provide an accessible and intuitive user interface.

Client Side

When implementing web application, frameworks such as Struts, JSF, Velocity or SpringMVC is handy.

AJAX gained a lot of popularity over time and it became the preferred way to provide rich user experience.  In combination with above frameworks and asynchronous communication tactics, the way your web application responds was transformed; however, there are certain limitations of AJAX:

JavaScript development tools: Since the advent of Internet in 1992, from static days, one has urged to see dynamic content and in 1995 JavaScript showed some promise.  But it’s over 15years now, but it has not gotten any good tools until Google’s GWT came out.  But for languages like C++, Java and other languages, the tool support has been pretty good.  Lack of such professional tools makes it harder for debugging, troubleshooting issues.

Exposure of logic: Since JavaScript is all client side scripting, browsers will just showoff your code and expose your logic, unless you obfuscate it.

Availability of talent: Finding developers, integrators, maintainers, support persons who have exposure to blend of these technologies with-in your budget is really hard.

Managing and presenting data using HTML: Imagine business intelligence reporting applications which has to display tons of data, provide you interactivity to change criteria on reporting to get the right information to help you make a decision with lots of client side scripting is a tremendous task and comes with risks.

Few advantages of Adobe Flex:

Quick Prototyping: Without the pain of a complex content management, one can quickly build applications for a demo and get the audiences captivated.

Desktop or Web: Building the same application for desktop and web is an awesome power to target broad spectrum of users.

Learning curve: Seamless integration with existing Java code; Familiar Eclipse environment.  Having worked with HTML and JavaScript, one should be able to grasp MXML/.AS extremely fast.

Security: Flex provides intense server-side security; protection from cross-domain and zone access; flash security on client side.

Agile: Easily change design, prototype and the processes.

Development and runtime worries: FlexBuilder SDK removes browser and platform worries (unlike with HTML/JavaScript/AJAX) and since Adobe Flash is available on different platforms deployability and testability should be easy.

With all these, seeking a tool like Delphi, Power Builder, or Visual Basic has presumably ended for developing web applications.  There is competing ones like Flex/AIR, Java/JavaFX, and Microsoft Silverlight and may the best one prevail; and my current vote goes to Adobe Flex.

Check out few enterprise applications trying to push Adobe Flex to its limits:

Finally have a look at