Listing 1 A fragment of a portfolio.xml

<portfolio>
	<security>
   	<Symbol>MSFT</Symbol>
		<Quantity>10000</Quantity>
		<Price>33.38</Price>
		<Value>1</Value>
	</security>
	<security>
		<Symbol>IBM</Symbol>
		<Quantity>3000</Quantity>
		<Price>82.15</Price>
		<Value>1</Value>
	</security>
  ...
</portfolio>

Listing 2 The first version - portfolio1.mxml

<?xml version="1.0" encoding="utf-8"?>
<!--portfolio1.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns="*" >
 	<PortfolioView1 id="pv"/>
</mx:Application>

Listing 3 The first version of PortfolioView.mxml

<?xml version="1.0" encoding="utf-8"?>
<!-- PortfolioView1.mxml -->
<mx:Panel xmlns:mx="http://www.adobe.com/2006/mxml"
	title="Portfolio"	width="100%" height="100%" ...>
	<mx:XML format="e4x" id="portfolioModel" source="portfolio.xml" />
	<mx:DataGrid id="portfolioGrid" width="100%"
    dataProvider="{portfolioModel.security}">
	 <mx:columns>
 	  <mx:DataGridColumn dataField="Symbol"/>
	  <mx:DataGridColumn dataField="Quantity" textAlign="right"/>
	  <mx:DataGridColumn dataField="Price" textAlign="right"/>
	  <mx:DataGridColumn dataField="Value" textAlign="right"/>
	</mx:columns>
	</mx:DataGrid>
	 ...
</mx:Panel>

Listing 4 RemoteObject Tag

<mx:RemoteObject id="freshQuotes" destination="portfolio" fault="onFault(event);">
  <mx:method name="getQuotes" concurrency="last" result="onResult(event);"/>
</mx:RemoteObject>

Listing 5 Configuring a Flex remoting service

<destination id="Portfolio">
    <properties>
      <source>com.theriabook.ro.Portfolio</source>
    </properties>
  </destination>


Listing 6 A simple stock quote generator - Portfolio.java

package com.theriabook.ro;
import java.util.Random;
import com.theriabook.jms.dto.StockQuoteDTO;

public class Portfolio {
	static Random random = new Random();
	static StockQuoteDTO[] quotes = {
			new StockQuoteDTO("IBM", 82.0),
			new StockQuoteDTO("MSFT", 27.0),
			new StockQuoteDTO("ADBE", 38.0),
			new StockQuoteDTO("ORCL", 13.0)};
	double volatility=.05;
	public StockQuoteDTO[] getQuotes() {
		for (int i = 0; i < quotes.length;i++){
			quotes[i].last += random.nextGaussian()* volatility;
		}
  	return quotes;
	}
}

Listing 7 The Java DTO  -  StockQuoteDTO.java

package com.theriabook.jms.dto;
import java.io.Serializable;
public class StockQuoteDTO implements Serializable {
	private static final long serialVersionUID = 4672447577075475117L;
	public String symbol;
	public double last;
	public StockQuoteDTO(String sym, double newPrice){
		symbol = sym;
		last = newPrice;
	}
}

Listing 8 The ActionScript on the client: StockQuoteDTO.as

package com.theriabook.jms.dto {
[RemoteClass(alias="com.theriabook.jms.dto.StockQuoteDTO")]
public dynamic class StockQuoteDTO
{
	public var symbol:String;
	public var last:Number;
}

Listing 9 Processing received quotes

private function onResult(event:ResultEvent):void {
	   ...
	var quotes:Array = event.result as Array;
	applyQuotes(quotes);
  	// Pull the next set of quotes
	pullQuotes();
}

	private function applyQuotes(quotes: Array):void {
	  	for (var i:int=0; i<quotes.length; i++) {
			var quote:StockQuoteDTO = StockQuoteDTO(quotes[i]);
		 	var list: XMLList = portfolioModel.security.(Symbol==quote.symbol);
			if (list.length()!=0) {
				var row:XML = XML(list);
				row.Price = Math.round(100*quote.last)/100;
				row.Value = Math.round(row.Price * row.Quantity);
			}
		}
	}

Listing 10 Error processing

private function onFault(event:FaultEvent):void {
	 errorText = "Portfolio feed failure...";
	 errorTip = "Destination:" + event.currentTarget.destination + "\n" +
		    "Fault code:" + event.fault.faultCode + "\n" +
			 "Detail:" + event.fault.faultDetail;
    	 // Try to pull the new quotes
			 pullQuotes();
 }

Listing 11 PortfolioView1.mxml

<?xml version="1.0" encoding="utf-8"?>
<!-- PortfolioView1.mxml -->
<mx:Panel xmlns:mx="http://www.adobe.com/2006/mxml"
	title="Portfolio"
	width="100%" height="100%"
	 creationComplete="pullQuotes();"
>
	<mx:XML format="e4x" id="portfolioModel" source="portfolio.xml" />
	<mx:Label color="red" toolTip="{errorTip}" text="{errorText}" width="100%"/>
	<mx:DataGrid id="portfolioGrid" width="100%" dataProvider="{portfolioModel.security}" >
		<mx:columns><mx:Array>
				<mx:DataGridColumn dataField="Symbol"/>
				<mx:DataGridColumn dataField="Quantity" textAlign="right"/>
				<mx:DataGridColumn dataField="Price" textAlign="right"/>
				<mx:DataGridColumn dataField="Value" textAlign="right"/>
		</mx:Array></mx:columns>
	</mx:DataGrid>
<mx:RemoteObject id="freshQuotes" destination="portfolio"
  	 fault="onFault(event);"	 >
   <mx:method name="getQuotes" concurrency="last"
  	 result="onResult(event);"
 	 />
</mx:RemoteObject>
 <mx:Script><![CDATA[
    import mx.rpc.events.*;
    import com.theriabook.jms.dto.StockQuoteDTO;

    [Bindable]
    private var errorText:String;
    [Bindable]
    private var errorTip:String;

    private function onResult(event:ResultEvent):void {
    	errorText = "";
    	errorTip = "";
    	var quotes:Array = event.result as Array;
    	applyQuotes(quotes);
    	// Pull new quotes set
    	pullQuotes();
    }

		private function onFault(event:FaultEvent):void {
			errorText = "Portfolio feed failure...";
			errorTip = "Destination:" + event.currentTarget.destination + "\n" +
			 "Fault code:" + event.fault.faultCode + "\n" +
			 "Detail:" + event.fault.faultDetail;
    	// Pull new quotes set
			pullQuotes();
		}

    private function applyQuotes(quotes: Array):void {
    		for (var i:int=0; i<quotes.length; i++) {
					var quote:StockQuoteDTO = StockQuoteDTO(quotes[i]);
					var list: XMLList = portfolioModel.security.(Symbol==quote.symbol);
					if (list.length()!=0) {
						var row:XML = XML(list);
						row.Price = Math.round(100*quote.last)/100;
						row.Value = Math.round(row.Price * row.Quantity);
					}
 			} 
    }
		private function pullQuotes():void{
			setTimeout(	function ():void {freshQuotes.getQuotes(); 	},1000	);
		}
  ]]></mx:Script>
</mx:Panel>

Listing 5.12 Adding the pie chart to the PortfolioView

<?xml version="1.0" encoding="utf-8"?>
<!-- PortfolioView2.mxml -->
<mx:Panel xmlns:mx=http://www.adobe.com/2006/mxml>
	...
	<mx:DataGrid id="portfolioGrid" width="100%" height="50%"
                 dataProvider="{portfolioModel.security}"
	</mx:DataGrid>
	 <mx:PieChart id="portfolioPie" dataProvider="{portfolioModel.security}"
   showDataTips="true" width="100%" height="50%">
		<mx:series>
    <mx:Array>
     <mx:PieSeries labelPosition="callout" field="Value"
         labelFunction="showPosition" nameField="Symbol" explodeRadius="2"/>
    </mx:Array>
	 </mx:series>
	</mx:PieChart>
	...
 <mx:Script>
  ...
  private function showPosition(data:Object, field:String, index:Number,
                       percentValue:Number):String {
   return data.Symbol + "\n" + "Shares:" + data.Quantity + "\n" +
           "Price:" + data.Price + "\n" + "Value:" + data.Value ;
  }
 </mx:Script>
</mx:Panel>


Listing 5.13 PortfolioView2.mxml

<?xml version="1.0" encoding="utf-8"?>
<!-- PortfolioView2.mxml -->
<mx:Panel xmlns:mx="http://www.adobe.com/2006/mxml" 	title="Portfolio"
	width="100%" height="100%"	 creationComplete="pullQuotes();" >
	<mx:XML format="e4x" id="portfolioModel" source="portfolio.xml" />
	<mx:Label color="red" toolTip="{errorTip}" text="{errorText}" width="100%"/>
	<mx:DataGrid id="portfolioGrid" width="100%" height="50%"
                  dataProvider="{portfolioModel.security}">
		<mx:columns><mx:Array>
				<mx:DataGridColumn dataField="Symbol"/>
				<mx:DataGridColumn dataField="Quantity" textAlign="right"/>
				<mx:DataGridColumn dataField="Price" textAlign="right"/>
				<mx:DataGridColumn dataField="Value" textAlign="right"/>
		</mx:Array></mx:columns>
	</mx:DataGrid>

 <mx:PieChart id="portfolioPie" dataProvider="{portfolioModel.security}" showDataTips="true" width="100%"
  height="50%">
		<mx:series>
     <mx:Array>
	 <mx:PieSeries labelPosition="callout"	field="Value"
       labelFunction="showPosition" nameField="Symbol" explodeRadius="2" />
    </mx:Array>
	 </mx:series>
	</mx:PieChart>

<mx:RemoteObject id="freshQuotes" destination="portfolio"
	 fault="onFault(event)">
   <mx:method name="getQuotes" concurrency="last" result="onResult(event)"/>
</mx:RemoteObject>
 <mx:Script><![CDATA[
    import mx.rpc.events.*;
    import com.theriabook.jms.dto.StockQuoteDTO;

    [Bindable]
    private var errorText:String;
    [Bindable]
    private var errorTip:String;

    private function onResult(event:ResultEvent):void {
    	errorText = "";
    	errorTip = "";
    	var quotes:Array = event.result as Array;
    	applyQuotes(quotes);
    	// Pull new quotes set
    	pullQuotes();
    }

		private function onFault(event:FaultEvent):void {
			errorText = "Portfolio feed failure...";
			errorTip = "Destination:" + event.currentTarget.destination + "\n" +
			 "Fault code:" + event.fault.faultCode + "\n" +
			 "Detail:" + event.fault.faultDetail;
    	// Pull new quotes set
			pullQuotes();
		}
    private function applyQuotes(quotes: Array):void {
      for (var i:int=0; i<quotes.length; i++) {
				var quote:StockQuoteDTO = StockQuoteDTO(quotes[i]);
				var list: XMLList = portfolioModel.security.(Symbol==quote.symbol);
				if (list.length()!=0) {
					var row:XML = XML(list);
					row.Price = Math.round(100*quote.last)/100;
					row.Value = Math.round(row.Price * row.Quantity);
				}
    }
    } 
		private function pullQuotes():void{
			setTimeout(	function ():void {	 freshQuotes.getQuotes();	},1000);
		}
private function showPosition(data:Object, field:String, index:Number,
                    percentValue:Number):String {

  return data.Symbol + "\n" + "Shares:" + data.Quantity +
     "\n" + "Price:" + data.Price + "\n" + "Value:" + data.Value ;
 }

  ]]></mx:Script>
</mx:Panel>


Listing 5.14 Adding a stacked view

<?xml version="1.0" encoding="utf-8"?>
<!-- PortfolioView3.mxml -->
<mx:Panel...>
 <mx:ViewStack id="vs" width="100%" height="100%">
	<mx:Canvas label="Show Grid" icon="{iconGrid}" >
		<mx:DataGrid id="portfolioGrid" ...height="100%"/>
	</mx:Canvas>
	<mx:Canvas label="Show Chart" icon="{iconChart}" >
		 <mx:PieChart id="portfolioPie" ... height="100%"/>
</mx:Canvas>
 </mx:ViewStack>
   	 <mx:ToggleButtonBar dataProvider="{vs}" horizontalGap="5" />
 <mx:RemoteObject id="freshQuotes" .../>
<mx:Script><![CDATA[
   ...
[Embed(source="images/icon_chart.png")]
[Bindable]
public var iconChart : Class;
[Embed(source="images/icon_grid.png")]
[Bindable]
public var iconGrid : Class;	
]]></mx:Script>
</mx:Panel>

Listing 5.15 PortfolioView3.mxml

<?xml version="1.0" encoding="utf-8"?>
<!-- PortfolioView3.mxml -->
<mx:Panel xmlns:mx="http://www.adobe.com/2006/mxml" 	title="Portfolio"
	width="100%" height="100%" 	 creationComplete="pullQuotes();" >
	<mx:XML format="e4x" id="portfolioModel" source="portfolio.xml" />
	<mx:Label color="red" toolTip="{errorTip}" text="{errorText}" width="100%"/>
  <mx:ToggleButtonBar dataProvider="{vs}" horizontalGap="5" />

	<mx:ViewStack id="vs" width="100%" height="100%">
	<mx:Canvas label="Show Grid" icon="{iconGrid}" >
		<mx:DataGrid id="portfolioGrid" width="100%" height="100%"
	    dataProvider="{portfolioModel.security}">
<mx:PieSeries labelPosition="callout"	field="Value"
       labelFunction="showPosition" nameField="Symbol" explodeRadius="2" />
    </mx:Array>
	 </mx:series>
	</mx:PieChart>

<mx:RemoteObject id="freshQuotes" destination="portfolio"
	 fault="onFault(event)">
   <mx:method name="getQuotes" concurrency="last" result="onResult(event)"/>
</mx:RemoteObject>
 <mx:Script><![CDATA[
    import mx.rpc.events.*;
    import com.theriabook.jms.dto.StockQuoteDTO;

    [Bindable]
    private var errorText:String;
    [Bindable]
    private var errorTip:String;

    private function onResult(event:ResultEvent):void {
    	errorText = "";
    	errorTip = "";
    	var quotes:Array = event.result as Array;
    	applyQuotes(quotes);
    	// Pull new quotes set
    	pullQuotes();
    }

		private function onFault(event:FaultEvent):void {
			errorText = "Portfolio feed failure...";
			errorTip = "Destination:" + event.currentTarget.destination + "\n" +
			 "Fault code:" + event.fault.faultCode + "\n" +
			 "Detail:" + event.fault.faultDetail;
    	// Pull new quotes set
			pullQuotes();
		}
    private function applyQuotes(quotes: Array):void {
      for (var i:int=0; i<quotes.length; i++) {
				var quote:StockQuoteDTO = StockQuoteDTO(quotes[i]);
				var list: XMLList = portfolioModel.security.(Symbol==quote.symbol);
				if (list.length()!=0) {
					var row:XML = XML(list);
					row.Price = Math.round(100*quote.last)/100;
					row.Value = Math.round(row.Price * row.Quantity);
				}
    }
    } 
		private function pullQuotes():void{
			setTimeout(	function ():void {	 freshQuotes.getQuotes();	},1000);
		}
"Detail:" + event.fault.faultDetail;
    	// Pull new quotes set
			pullQuotes();
		}
  private function applyQuotes(quotes: Array):void {
      for (var i:int=0; i<quotes.length; i++) {
				var quote:StockQuoteDTO = StockQuoteDTO(quotes[i]);
				var list: XMLList = portfolioModel.security.(Symbol==quote.symbol);
				if (list.length()!=0) {
					var row:XML = XML(list);
					row.Price = Math.round(100*quote.last)/100;
					row.Value = Math.round(row.Price * row.Quantity);
				}
    }
    } 
		private function pullQuotes():void{
			setTimeout(	function ():void { freshQuotes.getQuotes();	},1000);
		}

		private function showPosition(data:Object, field:String, index:Number,
                        percentValue:Number):String {
      return data.Symbol + "\n" + "Shares:" + data.Quantity + "\n" + 
           "Price:" + data.Price + "\n" + "Value:" + data.Value ;
    }

		[Embed(source="images/icon_chart.png")]
   [Bindable]
		public var iconChart : Class;
   [Embed(source="images/icon_grid.png")]
   [Bindable]
   public var iconGrid : Class;

  ]]></mx:Script>

Listing 5.16 PortfolioView4.mxml

<?xml version="1.0" encoding="utf-8"?>
<!-- PortfolioView4.mxml -->
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="100%" height="100%" >
 	<mx:RemoteObject id="freshQuotes" destination="portfolio" fault="onFault(event)">
   <mx:method name="getQuotes" concurrency="last" result="onResult(event)" />
	</mx:RemoteObject>
	<mx:XML format="e4x" id="portfolioModel" source="portfolio.xml" />

<mx:Panel title="Portfolio" width="100%" height="100%" creationComplete="pullQuotes();" >
	<mx:ViewStack id="vs" width="100%" height="100%">
	<mx:Canvas label="Show Grid" icon="{iconGrid}" >
		<mx:DataGrid id="portfolioGrid" width="100%" height="100%"
	    dataProvider="{portfolioModel.security}">
			<mx:columns><mx:Array>
<mx:DataGridColumn dataField="Symbol"/>
					<mx:DataGridColumn dataField="Quantity" textAlign="right"/>
					<mx:DataGridColumn dataField="Price" textAlign="right"/>
					<mx:DataGridColumn dataField="Value" textAlign="right"/>
			</mx:Array></mx:columns>
		</mx:DataGrid>
	</mx:Canvas>
	<mx:Canvas label="Show Chart" icon="{iconChart}" >
		 <mx:PieChart id="portfolioPie" dataProvider="{portfolioModel.security}" 
		 showDataTips="true" width="100%" height="100%">
			<mx:series>
	      <mx:Array>
	       <mx:PieSeries labelPosition="callout" 
	         field="Value" labelFunction="showPosition" 
	         nameField="Symbol" explodeRadius="0.02" />
	      </mx:Array>
		 </mx:series>
		</mx:PieChart>
	</mx:Canvas>
 </mx:ViewStack>

 <mx:Script><![CDATA[
    import mx.rpc.events.*;
    import com.theriabook.jms.dto.StockQuoteDTO;

    [Bindable]
    private var errorText:String;
    [Bindable]
    private var errorTip:String;

    private function onResult(event:ResultEvent):void {
    	errorText = "";
    	errorTip = "";
    	var quotes:Array = event.result as Array;
    	applyQuotes(quotes);
    	// Pull new quotes set
    	pullQuotes();
    }

		private function onFault(event:FaultEvent):void {
			errorText = "Portfolio feed failure...";
			errorTip = "Destination:" + event.currentTarget.destination + "\n" +
			 "Fault code:" + event.fault.faultCode + "\n" +
			 "Detail:" + event.fault.faultDetail;
    	// Pull new quotes set
			pullQuotes();
		}

   private function applyQuotes(quotes: Array):void {
      for (var i:int=0; i<quotes.length; i++) {
var quote:StockQuoteDTO = StockQuoteDTO(quotes[i]);
				var list: XMLList = portfolioModel.security.(Symbol==quote.symbol);
				if (list.length()!=0) {
					var row:XML = XML(list);
					row.Price = Math.round(100*quote.last)/100;
					row.Value = Math.round(row.Price * row.Quantity);
				}	      }
    }
		private function pullQuotes():void{
			setTimeout( function ():void {freshQuotes.getQuotes();	},1000	);
		}

	 private function showPosition(data:Object, field:String, index:Number,
                        percentValue:Number):String {
      return data.Symbol + "\n" + "Shares:" + data.Quantity + "\n" + 
           "Price:" + data.Price + "\n" + "Value:" + data.Value ;
  }

		[Embed(source="images/icon_chart.png")]
  [Bindable]
		public var iconChart : Class;
  [Embed(source="images/icon_grid.png")]
  [Bindable]
  public var iconGrid : Class;

  ]]></mx:Script>
</mx:Panel>
<mx:HBox horizontalAlign="right" width="100%" paddingRight="5" paddingTop="5">
	<mx:Label color="red" toolTip="{errorTip}" text="{errorText}" width="150"/>
 	 <mx:ToggleButtonBar dataProvider="{vs}" horizontalGap="5" />
</mx:HBox>
</mx:Canvas>