Friday, October 31, 2008

Removing and Adding Options Dynamically

Using DHTML is beautiful because you can play with the DOM as you please. However JavaScript is not that consistent. Of all sources I find the one by W3C: W3 Schools the most comprehensive and technically correct.

If you are looking to add or remove options from a select box dynamically, using add and remove methods on select element is the most reliable way. For gory details have a look here:


Wednesday, September 24, 2008

Flex Data Services(FDS): FMS

FDS enables you to access and synchronize data across one or more applications built with Flex framework. FDS itself is a server-side java app designed to work with most Java app servers. FDS consists of four parts:
  • Flex Message Service (FMS)
  • Flex Data Management Service (FDMS)
  • Flex Proxy Service (FPS)
  • Remoting Service
FMS helps to build apps that support real-time chat and collaboration. Idea is to update app whenever server side data changes. In this article let us see how we can use FMS Java API (MessageBroker, AsyncMessage) to receive message in Flex.

1. Take the FDS blank application as your starting point

2. Open WEB-INF/flex/messaging-config.xml and add this destination node below default-adapter node:Destination Node Code

3. Define message consumer in MXML

<mx:Consumer id="consumer" destination="feed" message="messageHandler(event.message)"/>

4. Subscribe/Unsubscribe to message at desired part of the flex code as:

consumer.subscribe();
consumer.unsubscribe();

5. Whenever there is a message generated at the backend, now your flex application will hear it. A very simple sample java file that generates message will look like this:


Thursday, July 24, 2008

Large Numbers in JavaScript

Recently faced probelms with large numbers in JavaScript. These two resources were extrelely useful:
Hazards of large numbers in JavaScript
Big Integers in JavaScript

Hope it helps you too :).

Monday, July 14, 2008

Using Webservices

using AS or <mx:WebService> tag

For <mx:WebService> tag, specify id, url of the wsdl file and optionally fault handler function. You can trap an event called load that fires when WSDL loads successfully

You can use methods on a Web Service in three ways:
1.Undeclared Method: Use WS with id. Flex looks at WSDL for the method based on how it is called
2.Declared Method: Operations defined as children of WS tag using <mx:operation> tag. Args validated using WSDL
3.Fully Declared Method: Both operations and arguments declared using <mx:operation> and <mx:request> tag.

Declaring operations enables specifying event handlers for each operation

<mx:WebService id="myWebservice"
wsdl="http://myWsdlUrl/myWsdlFile.wsdl"
fault= handleFaultFunc(event)>
<mx:operation name="funcNameInWsdl" result="resultHandlingFunc(event)">
<mx:request>
<paramName1InWsdl> {asVar1ToPickInputFrom} </paramName1InWsdl>
<paramName2InWsdl> {asVar2ToPickInputFrom} </paramName2InWsdl>
</mx:request>
</mx:operation>
</mx:WebService>

Then to call the operation

myWebservice.funcNameInWsdl.send();

To do in AS:
var myWebservice:WebService = new WebService();
myWebservice.wsdl =
"http://myWsdlUrl/myWsdlFile.wsdl";
ws.loadWSDL(); /*Before calling any method we need to load wsdl. Use canLoadWSDL() to check if WSDL was loaded or not*/
ws.addEventListener("result", resultHandlingFunc);
ws.addEventListener("fault", handleFaultFunc);
ws.funcNameInWsdl(asVar1ToPickInputFrom, asVar2ToPickInputFrom);

Monday, June 2, 2008

Flex-AJAX Bridge

Flex-AJAX bridge is a small non-obtrusive code library. Use it to control a Flex component using JavaScript. Uses ExternalInterface class underneath. This is included in Flex3 installation installation_dir\frameworks\javascript\fabridge. Has some good samples to start working with.

Thursday, April 10, 2008

Object Introspection in Flex

Object Introspection can be a handy tool to learn about large objects without documentation or to list all public properties, methods etc at runtime

import flash.utils.*; and use the method describeType() , passing it target object to be inspected. The result may be parsed using E4X API

If you call describeType(this) , non-static members returned

If you call describeType(getDefinitionByName("MyClass")) , static members returned

An example from Adobe Flex 3 reference to use it for a Button. Assume a Button with id button1:

import flash.utils.*;

pubic function inspector():void{
//get E4X description
var classInfo:XML = describeType(button1);

//class name
var className:String = classInfo.@name.toString();

//variables and their types
var classVarStr:String="";

for each(var v:XML in classInfo..variable){
classVarStr+= "Variable "+ v.@name + "=" + button1[v.@name] + "("+v.@type+")\n";
}

//properties, type and value
var classPropStr:String="";

for each(var a:XML in classInfo..accessor){

//no need to get value if write only
if(a.@access == 'writeOnly'){
classPropStr+="Property "+ a.@name + "(" + a.@type + ")\n";
}else{
classPropStr+="Property "+ a.@name + "=" +button1[a.@name] + "(" + a.@type + ")\n";
}
}

//methods
var classMethodStr:String="";

for each(var m:XML in classInfo..method){
classMethodStr += "Method " + m.@name + "():" + m.@returnType + "\n";
}

}

Thursday, March 6, 2008

Percentage Width For Datagrid Columns

Specifying relative using percentage is a common need for UIs. Unfortunately I dont see a simple way to do this in Flex2.0. Penning down a workaround that works for me.
On creationComplete event of your DataGrid call a function that has a logic similar to this:

var idx:Number=0;
//myTable is the id for the dataGrid you want to manipulate
for each(var col:DataGridColumn in myTable.columns{
  switch(idx){
    case 0:
      col.width = summaryTable.width*0.23;
      break;
    case 1:
      col.width = summaryTable.width*0.13;
      break;
    case 2:
      col.width = summaryTable.width*0.10;
      break;
    case 3:
      col.width = summaryTable.width*0.11;
      break;
    case 4:
      col.width = summaryTable.width*0.11;
      break;
    case 5:
      col.width = summaryTable.width*0.11;
      break;
    case 6:
      col.width = summaryTable.width*0.17;
      break;
    case 7:
      col.width = summaryTable.width*0.04;
      break;
  }
  if(idx < summaryTable.columnCount){
    idx++;
  }
}

Yes, this is a bit ugly. Not only you need to know the exact number of columns, you need to also make sure that the sum of parts is 100. For slightly better maintainability at most you can use declared constants in the switch statement.

Tuesday, February 26, 2008

Drag and Drop Grid of Panels

I needed a grid of panels in which I could exchange the places held by panels by dragging and dropping. I should be able to toggle the visibility of the panel and re-arrange the panels as need be. The grid should be scalable. This would be something like the igoogle panel and is available in most AJAX frameworks like zkoss and yui. Keeping this in mind I have written this code for a 3x3 grid. You can adapt it to any size and any container.

The grids would look something like this:



You can check out the code at: http://docs.google.com/Doc?id=ddhf5h22_69w36cmdh

Any queries/problems /suggestions are welcome :)

Cheers!

Tuesday, February 19, 2008

Datagrid Fix

Was grappling with some Datagrid issues only to discover later that it is a known bug. For a list of datagrid bugs and fix provided by adobe:
Datagrid Bugs Hotfix at Adobe

Thursday, February 7, 2008

Mapping AS objects to Server-Side Java Objects

Such mappings can be useful when you are using a value object ie an object containing values.

AS class:
/*we mark a class we want to map with RemoteClass tag. alias is the exact location of the class*/
package valueObjects
{
[RemoteClass(alias="valueObjects.SampleVo")]
public class SampleVo{
public var val1:String = "val1";
public var num1:int = 1;

public function getServerVal(obj:SampleVo):SampleVo{
return new SampleVo();
}
}
}

Java class (you will have to configure it as a remote object):
package valueObjects;

public class SampleVo {
public String val1 = "val2";
public int num1 = 2;

public SampleVo getServerVal(SampleVo obj){
return new SampleVo();
}
}

If you have this, you can do this in flex while handling result on calling getServerVal function:
var vo:SampleVo = event.result as SampleVo;
resultTxt.text = vo.val1+vo.num1;

Wednesday, February 6, 2008

Implementing Singleton in Flex

Your singleton class should look somewhat like this

package managers {
  /*A singleton class which enforces only a single object is created for each key. To access the specific instance, use getInstance(key:String) */

  public class MySingleton{
    private static var instanceMap:Object = new Object();

    public function MySingleton(pri:PrivateClass){}

    public static function getInstance(key:String):MySingleton{
      if(MySingleton.instanceMap[key] == null){
        MySingleton.instanceMap[key] = new MySingleton(new PrivateClass());
      }
      return MySingleton.instanceMap[key];
    }
  }
}

/* PrivateClass is used to make constructor private (to implement Singleton)*/
class PrivateClass{ public function PrivateClass(){}}

Tuesday, February 5, 2008

Uploading File From Flex to Tomcat

To upload file from Flex to Java utilize the fileUpload utility provided by Apache. Go to http://commons.apache.org/fileupload/ to download the lib files and see documentation. This utility in turn depends on commons-io utitlity that you can get at http://commons.apache.org/io/ . Copy the jar files from these two utilities to WEB-INF/lib of your application.

In Flex use FileReference object to get the file to upload:

private var fileRef:FileReference;

private function fileBrowse():void{
   this.fileRef = new FileReference();
   fileRef.addEventListener(Event.SELECT,selectHandler);
   fileRef.browse();
}


private function selectHandler(event:Event):void{
   var request:URLRequest = new URLRequest("http://localhost:8080/FlexJava1/fileLoader.jsp");
   /*Map this to the servlet or jsp you wish to use to handle your file writing request*/
   fileRef.upload(request);
}




The jsp will be like this (O yes this should be done in a servlet but lazy me doing it in a jsp. But you be good and make a nice servlet :p):


<%@page import="org.apache.commons.fileupload.FileItemFactory"%>
<%@page import="org.apache.commons.fileupload.disk.DiskFileItemFactory"%>
<%@page import="org.apache.commons.fileupload.servlet.ServletFileUpload"%>
<%@page import="org.apache.commons.fileupload.FileItem"%>
<%@page import="java.util.List"%>
<%@page import="java.util.Iterator"%>
<%@page import="java.io.File"%>
<%@page import="java.io.FileOutputStream"%>
<%@page import="java.io.InputStream"%>

<%
// Create a factory for disk-based file items
FileItemFactory factory = new DiskFileItemFactory();
// Create a new file upload handler
ServletFileUpload upload = new ServletFileUpload(factory);
// Parse the request
List /* FileItem */ items = upload.parseRequest(request);


// Process the uploaded items
Iterator iter = items.iterator();

while (iter.hasNext()) {
   FileItem item = (FileItem) iter.next();
   //handling a normal form-field
   if (item.isFormField()) {
      System.out.println("Got a form field");
      String name = item.getFieldName();
      String value = item.getString();
      System.out.println("Name:"+name+",Value:"+value);
   } else {//handling file loads
      System.out.println("Not form field");
      String fieldName = item.getFieldName();
      String fileName = item.getName();
      String contentType = item.getContentType();
      boolean isInMemory = item.isInMemory();
      long sizeInBytes = item.getSize();
      System.out.println("Field Name:"+fieldName+",File Name:"+fileName);
      System.out.println("Content Type:"+contentType+",Is In Memory:"+isInMemory+",Size:"+sizeInBytes);

      byte[] data = item.get();
      FileOutputStream fileOutSt = new FileOutputStream("outagain.jpg");
      fileOutSt.write(data);
      fileOutSt.close();
   }
}
%>


You will find your file written under the Tomcat root installation folder

Monday, February 4, 2008

Using Remote Objects

Using remote object can be tedious and confusing if you want to do it from the scratch and want to understand everything at once. A better approach is to have something that works and build on it, understand it bit by bit. I used this approach for Tomcat but this should work well for any J2EE container like Websphere or JBoss. I am not focussing on Remote Object basics or RMI here, just how you can make it work for yourself for Java.


Download Adobe LiveCycle Data Services ES from:

http://www.adobe.com/products/livecycle/dataservices/

Install it for J2EE and not for integrated JRun. We will be using the express version. Alternatively you could use BlazeDS. To see the differences between the two visit this link:

Differences between Flex Data Services Express and BlazeDS

Please remember that using either means that you will have to buy it at some stage for commercial applications. See the respective licence for details. That being said these services are extremely useful and without them Flex looses a lot of utility.


  • The installation folder contains many things that you will be using as you understand flex more. For time being our interest lies in a file by name flex.war
  • Take flex.war and unzip the contents into a folder. Name it apporpriately. This folder will be your template for a blank flex application that you may want to develop on your server.
  • Take this skeleton folder and copy in the webapps directory of your Tomcat.
  • Browse to WEB-INF/flex folder. Open a file named license.properties and add license keys (ie if you have one) for flex builder, flex charting and flex data services.
  • In the same folder open file services-config.xml and see the security tag. Uncomment the line for tomcat server and comment the rest.
  • Open Flex builder. Go to File->New->Flex Project. Choose Flex Data Services for data access and compile application on the server when the page is viewed. Click Next. Browse to the folder in tomcat webapps where you are hosting the skeleton app. Validate location and name the root URL and context root appropriately. Click Next. Give an appropriate name to your project and click Finish.
  • You have set up the stage to use Remote Object.

    Now, copy the java class you intend to use in the appropriate directory under WEB-INF/classes. Lets say we have a class file from your compiled java file called MyRemoteObj.class made from this file:

    package app;

    public class MyRemoteObj{

    public String getMessage(){ return "hello"; }

    }

    Browse to WEB-INF/flex and open remoting-config.xml. Make sure it looks something like this:

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

    <service id="remoting-service" class="flex.messaging.services.RemotingService">

    <adapters> <adapter-definition id="java-object" class="flex.messaging.services.remoting.adapters.JavaAdapter" default="true"/>
    </adapters>

    <default-channels>
    <channel ref="my-amf"/>
    </default-channels>

    <destination id="responder">
    <properties>
    <source>app.MyRemoteObj</source>
    <scope>application</scope>
    </properties>
    </destination>

    </service>

    Remember this xml file is just one of the files uploaded by services-config.xml. It just helps in breaking our config xml into usable parts. <adapters> define the backend object. <channels> are defined in service-config. Here we just specify the channel we intend to use. destination is the part that helps flex use the remote object. id is ised to refer to it. source is its location under the WEB-INF/classes directory.

    Declare your remoter object in the MXML as

    <mx:RemoteObject id="remoteObjRef" destination="responder" fault="handleFault(event)" result="handelResult(event)"/>

    Use the id in AS to call the methods directly on the object: remoteObjRef.getMessage();

    Monday, January 28, 2008

    Pondering on AJAX and Flex

    After working with Flex and AJAX for some time I feel like looking back and asking myself when I should use what. My opinion is this:

    I think AJAX, more specifically yui, can be used for most of the web-applications. It is simpler to use and written pretty well.

    However if we need controls with interactive graphics/charting data or we have a very big and complex application, flex would be a better option.

    Lets face it, flex is more powerful and easy to develop (and maintain) of the two. However it has its learning curve and people with good flex skills & strong programming basics are not that easy to find. If your application is indeed that complex and demands a high degree of interaction and/or analytics, flex is a wise decision. Else it is like using a hammer to kill a fly. It is good but you dont have to use it if you dont need it :).

    DataGrid Rendering

    The default editing control for an editable column is a text field. It is possible to specify the editor via itemEditor attribute and editorDataField. Following controls can be specified:

    Button, Label, CheckBox, NumericStepper, ComboBox, Text, DateField, TextArea, Image, TextInput

    You can also specify your own control as long as it implements IDropInListItemRenderer interface in its class definition

    Item renderers can be used to customize looks of individual columns.

    One way is to make a custom renderer (say using Canvas) as an MXML component and giving the appropriate DataGridColumn the full-qualified path to itemRenderer property. Remember that the data property will help you in the renderer to access row data.

    Another way is using
    tag. Efficient but not modular. Inside the renderer tag you will have to place tag. What is inside this tag will have its own scope, will need its own imports. You can talk to the containing app using outerDocument scope. But the properties you wish to access have to be public.

    labelFunction signature for DataGrids is:

    labelFunctionName(item:Object,dataField:DataGridColumn)