Saturday, March 1, 2008

Reading remote XML data in Flex

We all know that Flex 2 provides ArrayCollection , XMLListCollection to read XML and consume the data.
However in case the XML contains only a single set of Data entries ArrayCollection are not the right solution.
Assuming the XML is
<dataroot>
<Capital>
<city>Delhi</city>
<country>India</country>
</Capital>
</dataroot>


In order to read this XML you have two ways to do

<mx:HTTPService id="rpcPatHTTP" url="sample.xml" resultFormat="object" result="handlerCapital(event)" />

<mx:Script>
<![CDATA[

[Bindable]
var myAC:ArrayCollection = new ArrayCollection();
private function handlerCapital(event:ResultEvent):void
{
myAC = event.result.dataroot.Capital as ArrayCollection


}

]]>
</mx:Script>

In the above case if you try to get the length of the myAC ArrayCollection, you will get 0
so
myAC.length will give 0

In such cases you should use the XMLListCollection. So the above example will be rewritten as

<mx:HTTPService id="rpcPatHTTP" url="sample.xml" resultFormat="e4X" result="handlerCapital(event)" />

<mx:Script>
<![CDATA[

[Bindable]
var myXML:XMLListCollection;
private function handlerCapital(event:ResultEvent):void
{
myXML = new XMLListCollection(event.result.Capital);

}

]]>
</mx:Script>


Now if you try to find the length of the collection you will get 1 so myXML.length will give 1, which is correct.

So my recommendation is use XMLListCollection over ArrayCollections to store the incoming remote data since you never know the number of entries in the XML file

Saturday, February 16, 2008

Display Images from remote server in flex2.

I had a tough time in finding the resources that give working examples on this topic. Let me set the context of the problem then this discussion will make more sense.
There are times when you want to display images from various sources on the internet on your flex page, or you have a image server and you want to display the images from the server on to your page.
There are two ways of doing this
1. The server has sent you the image in the form of a byte array and you just want to render that byte array on your flex page
2. To mention the URL of the image and ask flex to display the image from that URL

Note: Only jpg,png,gif and swf files can be displayed.


Method 1 (byte array)

This is quite simple. (courtesy http://www.kineticz.net/blahg/2007/07/26/rending-a-bitmap-from-a-bytearray-in-flash/ )

I am giving the pieces of the code. Basically Assuming that you have your byte array ready with you from the server. I will explain how to render


<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="init()">
<mx:Script>
<![CDATA[

private function renderImage():void
{
var byteLoader:Loader = new Loader();
byteLoader.loadBytes(Your_Byte_Array_Name);
imageCanvas.rawChildren.addChild(byteLoader);
}
</mx:Script>
<mx:Canvas id="imageCanvas" left="10" top="189" right="528" bottom="10"/>

</mx:Application>

We essentially have to do the following three steps:
step1 : declare an instance of Loader class.

var byteLoader:Loader = new Loader();

step2: Now load the bytes of the byte array in the loader. This is going to load the bytes in the security context of your application
byteLoader.loadBytes(your_byte_array);

step3: You need to have a canvas control where the image will be displayed so you must have something like
<mx:Canvas id="imageCanvas" left="10" top="189" right="528" bottom="10"/>

step4: Finally load the Byte Array in the canvas
imageCanvas.rawChildren.addChild(byteLoader);


Method 2: Directly accessing the images using Image URL
In this method I will give a sample code that will access the image using the image URL. First I will give the sample implementation and then explain whats need to be done. The code has been taken from http://onflex.org/flexapps/applications/ProgressiveImageLoading/srcview/index.html


<?xml version="1.0" encoding="utf-8"?>
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
initialize="appInit()"
layout="absolute"
viewSourceURL="srcview/index.html"
backgroundGradientAlphas="[1.0, 1.0]"
backgroundGradientColors="[#FFFFFF, #FFFFFF]">

<mx:Script>
<![CDATA[

// Progressive Image Loading

import flash.net.URLStream;
import flash.net.URLRequest;
import flash.utils.getTimer;

// loader to hold the loaded bytes
public var loader:Loader;

// URLStream to load the image bytes
public var imageStream:URLStream;

// ByteArray to hold aggregate image data
public var imageData:ByteArray;

// Set up initial conditions when the application initializes
public function appInit():void
{
//create a URLStream to load data in. The incoming data will be obtained using URLStream.
imageStream = new URLStream();
//add some event listeners for PROGRESS and COMPLETE. This will help in order to determine when the image download is complete
imageStream.addEventListener( ProgressEvent.PROGRESS , imageStreamProgress );
imageStream.addEventListener( Event.COMPLETE , imageStreamComplete );

//create a fresh loader instance
// this is similar to the Method 1 . Only thing is that the byte Array has not been obtained till now.
loader = new Loader();
imageCanvas.rawChildren.addChild( loader );
}

public function imageStreamProgress( event:Event ):void
{
// if there are no bytes do nothing
if( imageStream.bytesAvailable == 0 ) return

// ooo bytes process the image data
this.processImageData();
}

public function imageStreamComplete( event:Event ):void
{
// if connected, stop that.
if ( imageStream.connected ) imageStream.close();

// lets refresh the displayList after rendering cycle
imageCanvas.callLater( this.processImageData );
}

public function processImageData():void
{
// if connected, read all the bytes that have been loaded into the aggregate bytearray. The byte Array is filled with the incoming data
if ( imageStream.connected ) imageStream.readBytes( imageData , imageData.length );

// clean up the loader
loader.unload();

//push the aggregate bytearray of loaded image data in there.
loader.loadBytes( imageData );
}

public function loadImage( input:String ):void
{
//if connected we need to stop that
if ( imageStream.connected ) imageStream.close();

//lets load a new image url
imageStream.load( new URLRequest( input + '?' + getTimer() ) );

// clean out all the crud in that loader
loader.unload();

//create a fresh bytearray to store aggregate image data
imageData = new ByteArray();
}

]]>
</mx:Script>


<!-- this is the place that we are accessing the jpg image from our server-->
<mx:Button click="loadImage('http://sampleserver/scripts/sample.jpg')" y="10" label="Load sample" x="371" />

<mx:Canvas id="imageCanvas" left="10" top="40" right="10" bottom="10"/>

</mx:Application>


A rough algorithm

1. Create a URLStream to access the remote image URL
2. Create a loader object
3. Create a byte Array
4. Create a canvas or some container where to render the image. Associate the loader object as a child of this canvas
5. Listen to the events
ProgressEvent.PROGRESS,Event.COMPLETE. These will help in knowing if the download is over or still progressing
6. We load the URL to the URLStream
7. Clear the loader
8. initialize the ByteArray
9. Now listen to the events.
If the Progress event occurs then
10. Read the bytes into the byteArray and then load the bytes to the loader. So we will see the some portion of the image on the client
If the Complete Event occurs then
11 close the URLStream.







Sunday, February 10, 2008

Books to read for Ruby on Rails

I will suggest the following books to learn ruby on rails
One should first learn ruby since rails is based on this. There are two interesting books I would recommend
Learning Ruby, Oreilly Publishers
The book talks about the syntactical details of Ruby in a simple and practical manner with lots of example

The other book is
Ruby For Rails,David Black,Manning Publication
The book explains Ruby as well as Rails. Lot of examples are given so that will help in easy understanding of the topic. The advantage of this book is that its a complete deal it talks about Ruby, Rails and gives an example Rails application.

For Rails:
1. http://www.onlamp.com/pub/a/onlamp/2005/01/20/rails.html
Refer to the above URl. This is like the first guide that every Rails beginner must refer to. The page explains how to install rails, How to write the hello world in rails. It also gives an example to complete the overview of Rails

2. Agile Web Development with Rails,second Edition:
This is the book of Rails. Written by the creator of rails (DHH) himself is the most authenticated account of the Rails framework. Usually the books written by the language creators are little tough to understand e.g. Kernighan &Richie 's C, Bjarne Stroustrup's C++, But this book is very simple to understand. The book talks about the internals of Rails framework and also develops an application. Its a must to read book

One thing I have noticed in the books that are being written these days, the authors are more inclined towards explaining the practical aspects of the language giving examples rather than just a theoretical overview.

Saturday, February 9, 2008

Logger in rails

By default log files are created in the log directory. But if you want to control you logs then you can specify it in the config/environment.rb file

# Include your application configuration below
#Added to include the logging capability in the code
MY_LOGGER = Logger.new("c:/logging_rail.log")
MY_LOGGER.level = Logger::DEBUG

From the code use lgger as
MY_LOGGER.info("-----------------------------");
MY_LOGGER.info("INFO: Inside function");
MY_LOGGER.info("INFO: At:"+1.hour.from_now.to_s);
MY_LOGGER.debug("DEBUG:executeQueryByID--queryid:"+params[:queryid]);

Friday, February 8, 2008

Web as a platform --my views


Web2.0 is all about the platform.

In layman terms we call OS as a platform , this is because it gives us the necessary support that is required to develop applications and to use them. OS alone is of no use if there are no applications. The popularity of a OS (Windows,Linux) is based on the number of user/system applications it provides and the support it provides to develop new applications. Linux is quite popular among students since it provides vast support for development of applications. Another reason why we want platform is because it allows thousand of users to contribute to the development of new applications without worrying about the low level details of the system. Also the developers of the OS can concentrate on developing the platform while other people can develop the applications which they think are useful.

Think it this way If there was no OS then you would be required to perform all the memory management, task scheduling all by yourself. Even a Hello World program could then become a 1 month project !!. In simple words the kinds of application which we can develop now a days in few hours would have taken months.


Now a days all the current programming paradigms are based on frameworks .NET, J2EE, Ruby on Rails rather than on a particular language specifications. Users first look what all support a particular framework gives in terms of architecture, classes, language and then start using it. The reason why Rails is gaining so much popularity is because of the framework (the richness of the platform it provides)

The bottom line is that users want ability to extend the systems rather than just be a dumb user.


Web2.0 supports this philosophy in a big way.

The new websites/web portals are coming with the idea of providing the platform/framework. They provide the user various APIs that help him to develop the applications and plug them in their framework.E.g. facebook. The users are developing mashups that are the result of remixing multiple APIs together to create a new application. The development in web had never been so prominent as it is happening now. Like OS is running various processes which can share some information among themselves, similarly in web the portals can share information in the form on RSS feeds. The web is full of resources : Photos from Flickr, Videos from YouTube, Social Networking APIs from Facebook, Bookmarks from delicious, Storage and Computing power form Amazon, Financial services from Yahoo, Maps from Google and list goes on (This is like the drivers, Communication libraries a typical OS provide) you can use them and come up with wonderful applications.


The main reason for this success is because when you provide an application rather than a platform you have defined an intended use which has limited use. But when you provide a platform you open the opportunities for developing applications which even you had never thought about before. This is how Facebook has become so popular.Its a win-win situation for the facebook and its users


1. The popularity of the facebook is touching sky (Benefit for facebook)

2. The users can do experiments and come up with really cool applications which the creator may not have thought about. (user are happy so is facebook)

3. It creates an interest in the tech savvy users to use more and more of the facebook and hence the user faithfulness (user are happy so is facebook)

4. Overall it is helping in the growth of the craze for the web. (Most important)


I will say that the philosophy of Web2.0 to provide a platform has started the web revolution which is going to change the way the applications were developed forever.





Sunday, February 3, 2008


require_gem error


c:/ruby/bin/rake.bat:24: undefined method `require_gem' for main:Object (NoMethodError)

I encountered this error when I installed rails version 2.0.2. I wanted to use
call rake db:migrate

when I encountered the error
"c:/ruby/bin/rake.bat:24: undefined method `require_gem' for main:Object (NoMethodError)"

I was able to remove this error by following way:

1. open the rake.bat file. This file is present in the bin folder of ruby. For me the path was c:rubybinrake.bat
2. The file will look like the following:
@echo off
if not "%~f0" == "~f0" goto WinNT
ruby -Sx "%0" %1 %2 %3 %4 %5 %6 %7 %8 %9
goto endofruby
:WinNT
"%~d0%~p0ruby" -x "%~f0" %*
goto endofruby
#!/bin/ruby
#
# This file was generated by RubyGems.
#
# The application 'rake' is installed as part of a gem, and
# this file is here to facilitate running it.
#

require 'rubygems'
version = "> 0"
if ARGV.size > 0 && ARGV[0][0]==95 && ARGV[0][-1]==95
if Gem::Version.correct?(ARGV[0][1..-2])
version = ARGV[0][1..-2]
ARGV.shift
end
end
require_gem 'rake', version
load 'rake'

__END__
:endofruby


3. You need to replace the line
require_gem 'rake'version
with
gem 'rake',version

4. The file rake.bat will now look like
@echo off
if not "%~f0" == "~f0" goto WinNT
ruby -Sx "%0" %1 %2 %3 %4 %5 %6 %7 %8 %9
goto endofruby
:WinNT
"%~d0%~p0ruby" -x "%~f0" %*
goto endofruby
#!/bin/ruby
#
# This file was generated by RubyGems.
#
# The application 'rake' is installed as part of a gem, and
# this file is here to facilitate running it.
#

require 'rubygems'
version = "> 0"
if ARGV.size > 0 && ARGV[0][0]==95 && ARGV[0][-1]==95
if Gem::Version.correct?(ARGV[0][1..-2])
version = ARGV[0][1..-2]
ARGV.shift
end
end
gem 'rake', version
load 'rake'

__END__
:endofruby



Hope that this should solve your problem
ActiveRecord::StatementInvalid in GreetingController#index
Mysql::Error: Unknown system variable 'NAMES': SET NAMES 'utf8'

This error occurs if you are using rails 2.0.2.

As far as I understood, in case of rails 2.0.2 when we create a new project, the default database adapter is SQLlite.
In order to use mysql, one need to explicitly tell,
rails -d mysql cookbook

Assuming that you have already created the three database tables: cookbook_development, cookbook_test, cookbook_production,
if you look at the database.yml file that is present in the config folder, you will see the the following lines
development:
adapter: mysql
encoding: utf8
database: cookbook_development
username: root
password: your_password
host: localhost

similarly for test and production.
The singular pint is the addition of the new line encoding: utf8. This is a new addition, if you were using rails version <= 2.0.1, this line is missing.
So I removed the line from development, test, production settings so that my database.yml now looks as
development:
adapter: mysql
database: cookbook_development
username: root
password: your_password
host: localhost

Now if you again run the server and try to access any function of the project from the browser the error wont occur.