<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
   <channel>
      <title>mac martine</title>
      <link>http://www.macmartine.com/blog/</link>
      <description>dallying with Flex, Air, and other surprises...</description>
      <language>en</language>
      <copyright>Copyright 2008</copyright>
      <lastBuildDate>Thu, 10 Apr 2008 08:21:53 -0800</lastBuildDate>
      <generator>http://www.sixapart.com/movabletype/?v=3.2</generator>
      <docs>http://blogs.law.harvard.edu/tech/rss</docs> 

            <item>
         <title>Installing Coldfusion and JRun on OS X</title>
         <description><![CDATA[<p>I spent a lot of time getting ColdFusion to run on Leopard. I wish I had kept better track of all the errors I sorted through on path to figuring it out, but unfortunately I didn't. <br />
Here were the biggies though. First make sure to get Update 7 for JRun. I didn't find the updates at first which slowed me down.</p>

<p>Additionally (and the most frustrating), is it turned out that setting java.home in jvm.config was not enough to make JRun use the specified JRE. I wanted it to use JVM 1.5.0. Running './jrun -info' (from the JRun bin directory) returned "Apple Inc. 1.5.0_13-119 Java HotSpot(TM) Client VM", so it appeared to be finding the JVM I wanted it to use, but it wasn't working. So I set the classpath in ~/.bash_profile as well. That didn't cut it either. Finally I found <a href="http://www.talkingtree.com/blog/index.cfm/2006/5/17/CFMX-MacOSX-JVM142">Steven Erat's entry</a> where he had similar issues. </p>

<p>What did resolve it was to change the CurrentJDK alias in System/Library/Frameworks/JavaVM.framework/Versions in addition to the changes already made. <br />
Steven's entry has good directions on how to do so. It seemed to me that setting java.home in jvm.config should have taken care of everything, but it didn't You can to set the JVM in 3 places.</p>

<p>Once I had it running with JDK 1.5, I'd get this error:</p>

<p>Error 500</p>

<p>Could not invoke Java compiler, please make sure jikesw is in /Applications/JRun4/bin or put a JDK bin directory in your path.</p>

<p>jrunx.compiler.JavaCompiler$NoCompilerFoundException: Could not invoke Java compiler, please make sure jikesw is in /Applications/JRun4/bin or put a JDK bin directory in your path.<br />
	at jrunx.compiler.JavaCompiler.outProcessCompile(JavaCompiler.java:474)<br />
        .................</p>

<p>Basically it can't find javac, and I still have no idea why. The servers running but the sample JSP's aren't getting compiled. You could probably just compile the apps manually but I haven't done that. </p>

<p>Well, there's no great solution here, but hopefully this'll help you to get going with whatever you decide.  The problem with changing the CurrentJDK alias to 1.4.2 is that then everything on your system will be using that. That's a hassle for me with all my Eclipse installs, etc where I need JDK 1.5.</p>]]></description>
         <link>http://www.macmartine.com/blog/2008/04/installing_coldfusion_and_jrun_1.html</link>
         <guid>http://www.macmartine.com/blog/2008/04/installing_coldfusion_and_jrun_1.html</guid>
         <category>ColdFusion</category>
         <pubDate>Thu, 10 Apr 2008 08:21:53 -0800</pubDate>
      </item>
            <item>
         <title>Adding a user to sudoers file</title>
         <description><![CDATA[<p>On Linux you'll need to add your user account to the sudoers file so you can run certain tasks as a superuser (sudo, su). Here's an easy way:</p>

<p>Log in with your user account (not as root):<br />
[martine@machine ~]# sudo<br />
Password:  <root password><br />
[root@machine martine]# chmod +w /etc/sudoers<br />
[root@machine martine]# echo 'martine ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers<br />
[root@machine martine]# chmod -w /etc/sudoers</p>]]></description>
         <link>http://www.macmartine.com/blog/2008/04/adding_a_user_to_sudoers_file.html</link>
         <guid>http://www.macmartine.com/blog/2008/04/adding_a_user_to_sudoers_file.html</guid>
         <category>Linux</category>
         <pubDate>Wed, 09 Apr 2008 07:59:31 -0800</pubDate>
      </item>
            <item>
         <title>Crossdomain.xml files in Rails projects</title>
         <description><![CDATA[<p>Usually when you need to allow a swf on one server access to data on another domain you would put a crossdomain.xml file in the root folder of that server. </p>

<p>I've found one exception which is if you are making a call to Rails the crossdomain.xml file to the 'public' folder of your Rails project.</p>]]></description>
         <link>http://www.macmartine.com/blog/2008/04/crossdomainxml_files_in_rails.html</link>
         <guid>http://www.macmartine.com/blog/2008/04/crossdomainxml_files_in_rails.html</guid>
         <category>Rails</category>
         <pubDate>Tue, 08 Apr 2008 08:44:35 -0800</pubDate>
      </item>
            <item>
         <title>Resolving gcc errors installing sqlite3 gem on Leopard</title>
         <description><![CDATA[<p>The following error kept coming up when trying to install Sqlite3 on OS X (actually, the same thing happened when trying to install Fink too). It was finally resolved by installing the latest XCode packages.</p>

<p>Running ‘sudo ./configure --prefix=/usr/local’</p>

<p>would return:</p>

<p>checking build system type... i386-apple-darwin9.2.2<br />
checking host system type... i386-apple-darwin9.2.2<br />
checking for gcc... gcc<br />
checking for C compiler default output file name... <br />
configure: error: C compiler cannot create executables<br />
See `config.log' for more details.</p>

<p><br />
Here’ all the important stuff from the log:</p>

<p>## ----------- ##<br />
## Core tests. ##<br />
## ----------- ##</p>

<p>configure:2062: checking build system type<br />
configure:2080: result: i386-apple-darwin9.2.2<br />
configure:2102: checking host system type<br />
configure:2117: result: i386-apple-darwin9.2.2<br />
configure:2187: checking for gcc<br />
configure:2203: found /usr/bin/gcc<br />
configure:2214: result: gcc<br />
configure:2452: checking for C compiler version<br />
configure:2459: gcc --version >&5<br />
i686-apple-darwin8-gcc-4.0.1 (GCC) 4.0.1 (Apple Computer, Inc. build 5367)<br />
Copyright (C) 2005 Free Software Foundation, Inc.<br />
This is free software; see the source for copying conditions.  There is NO<br />
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.</p>

<p>configure:2462: $? = 0<br />
configure:2469: gcc -v >&5<br />
Using built-in specs.<br />
Target: i686-apple-darwin8<br />
Configured with: /private/var/tmp/gcc/gcc-5367.obj~1/src/configure --disable-checking -enable-werror --prefix=/usr --mandir=/share/man --enable-languages=c,objc,c++,obj-c++ --program-transform-name=/^[cg][^.-]*$/s/$/-4.0/ --with-gxx-include-dir=/include/c++/4.0.0 --with-slibdir=/usr/lib --build=powerpc-apple-darwin8 --with-arch=nocona --with-tune=generic --program-prefix= --host=i686-apple-darwin8 --target=i686-apple-darwin8<br />
Thread model: posix<br />
gcc version 4.0.1 (Apple Computer, Inc. build 5367)<br />
configure:2472: $? = 0<br />
configure:2479: gcc -V >&5<br />
gcc: argument to `-V' is missing<br />
configure:2482: $? = 1<br />
configure:2505: checking for C compiler default output file name<br />
configure:2532: gcc    conftest.c  >&5<br />
/usr/bin/ld: /usr/lib/gcc/i686-apple-darwin8/4.0.1/../../../libSystem.dylib unknown flags (type) of section 6 (__TEXT,__literal16) in load command 0<br />
collect2: ld returned 1 exit status<br />
configure:2535: $? = 1<br />
configure:2573: result: <br />
configure: failed program was:<br />
| /* confdefs.h.  */<br />
| #define PACKAGE_NAME "sqlite"<br />
| #define PACKAGE_TARNAME "sqlite"<br />
| #define PACKAGE_VERSION "3.5.7"<br />
| #define PACKAGE_STRING "sqlite 3.5.7"<br />
| #define PACKAGE_BUGREPORT ""<br />
| /* end confdefs.h.  */<br />
| <br />
| int<br />
| main ()<br />
| {<br />
| <br />
|   ;<br />
|   return 0;<br />
| }<br />
configure:2580: error: C compiler cannot create executables<br />
See `config.log' for more details.</p>

<p>## ----------- ##<br />
## confdefs.h. ##<br />
## ----------- ##</p>

<p>#define PACKAGE_NAME "sqlite"<br />
#define PACKAGE_TARNAME "sqlite"<br />
#define PACKAGE_VERSION "3.5.7"<br />
#define PACKAGE_STRING "sqlite 3.5.7"<br />
#define PACKAGE_BUGREPORT ""</p>

<p>configure: exit 77<br />
</p>]]></description>
         <link>http://www.macmartine.com/blog/2008/04/resolving_gcc_errors_installin.html</link>
         <guid>http://www.macmartine.com/blog/2008/04/resolving_gcc_errors_installin.html</guid>
         <category>OS X</category>
         <pubDate>Thu, 03 Apr 2008 09:02:07 -0800</pubDate>
      </item>
            <item>
         <title>Flex and ColdFusion: RemoteObjects and WebServices</title>
         <description><![CDATA[Once you have a ColdFusion CFC you can call it's methods with a RemoteObject or via a WebService.
RemoteObjects are usually preferred for their <a href="http://www.themidnightcoders.com/blog/2007/03/flex-remoteobject-vs-webservice.html">performance speed</a>.
<br/><br/>
Here we'll create a super basic example of calling a CFC from both a WebService and a RemoteObject. The application will simply let you enter your name, click a button, call the CFC and return a welcome message including your name.
<br/><br/>]]></description>
         <link>http://www.macmartine.com/blog/2008/04/flex_and_coldfusion_remoteobje.html</link>
         <guid>http://www.macmartine.com/blog/2008/04/flex_and_coldfusion_remoteobje.html</guid>
         <category>ColdFusion</category>
         <pubDate>Wed, 02 Apr 2008 11:33:57 -0800</pubDate>
      </item>
            <item>
         <title>Linux: chcon to change security context (to solve permissions problems with mounted shares)</title>
         <description><![CDATA[<p>On my Fedora server I was creating some shared folders that I could mount from my other machines.<br />
So I created a Samba share, and chmod-ed the directories.<br />
From my other machine I mounted a share and all seemed swell -- that is, until I tried to add a file. It kept telling me I didn't have sufficient permissions. Finally I figured out that chmod-ing was not enough, and that I had to change the context of the directory on the linux server:</p>

<p>chcon -R -t samba_share_t /path/to/share </p>

<p>I could then add files from the remote machine! Phew.</p>

<p>To get more info on the 'chcon' (change context) command, run 'info chcon'</p>]]></description>
         <link>http://www.macmartine.com/blog/2008/04/linux_chcon_to_change_security_1.html</link>
         <guid>http://www.macmartine.com/blog/2008/04/linux_chcon_to_change_security_1.html</guid>
         <category>Linux</category>
         <pubDate>Wed, 02 Apr 2008 09:03:46 -0800</pubDate>
      </item>
            <item>
         <title>Adobe Online Developer Week</title>
         <description><![CDATA[<p>Join us for the Adobe Online Developer Week which already under way!<br />
<a href="http://adobe.com/go/2008_developer_week">http://adobe.com/go/2008_developer_week</a></p>

<p>There are a bunch of cool sessions about Flex, AIR, LCDS and more...</p>]]></description>
         <link>http://www.macmartine.com/blog/2008/03/adobe_online_developer_week.html</link>
         <guid>http://www.macmartine.com/blog/2008/03/adobe_online_developer_week.html</guid>
         <category></category>
         <pubDate>Mon, 24 Mar 2008 09:42:00 -0800</pubDate>
      </item>
            <item>
         <title>Flex 3 and AIR 1.0 released!</title>
         <description><![CDATA[<p>Check 'em out!</p>

<p><a href="http://www.adobe.com/products/flex/">http://www.adobe.com/products/flex/</a></p>

<p><a href="http://www.adobe.com/products/air/">http://www.adobe.com/products/air/</a></p>

<p>And here's a good New York Times article about AIR: <a href="http://www.nytimes.com/2008/02/25/technology/25adobe.html?ref=technology">Adobe Blurs Lines Between PC and Web</a></p>]]></description>
         <link>http://www.macmartine.com/blog/2008/02/flex_3_and_air_10_released.html</link>
         <guid>http://www.macmartine.com/blog/2008/02/flex_3_and_air_10_released.html</guid>
         <category></category>
         <pubDate>Mon, 25 Feb 2008 11:39:10 -0800</pubDate>
      </item>
            <item>
         <title>Data storage and caching with SQLite databases and Adobe AIR</title>
         <description><![CDATA[You may or may not know by now that the AIR runtime includes a version of SQLite engine. Being a smaller implementation of SQL, SQLite supports all your usual database transactions, a lot of the complex queries, and triggers. With it,you can create a database to store all the data for your Flex/AIR desktop applications, store data for offline use of your Flex/AIR desktop/web applications, or for caching of data. It's all done in the same way. I was recently working on an application where I wanted the user to have an option to be logged in automatically when the app was launched, so the first time the user logged in I created a database to cache that login info. From then on when the application is launched it checks to see if the database exists, and if so it grabs the login info, and logs them in automatically.
<br/><br/>
I've made a simple example which is a super simple desktop application which stores it's data in a SQLite database. The idea and implementation here is very similar to what I just described for the caching example. On launch, we first check to see if the database exists. If it does, that means it ought to contain some data so we grab the data and display it. If the database doesn't exist, we create it and add our one default entry, then load it into the application. The user can then add, remove, and update entries. When each of these transactions sends a result of success, we reload all the data in the database. Obviously in a real-world application this wouldn't be a great idea; that's too much overhead. One option would be to just manipulate the dataProvider ArrayCollection after each successful transaction -- but for this simple example I'm leaving it the way it is for the intent of simply demonstrating using SQLite.
<br/><br/>
At this point I think I'll let the code speak for itself.
<br/><br/><br/>
ﾠ

Basically you'll notice the basic steps are:
<br/><br/>
   1. Create a connection: connection = new SQLConnection();<br/>
   2. Define the database file: dbFile = File.applicationStorageDirectory.resolvePath(dbFileString);<br/>
   3. Open (or create and open ) the database: connection.open(dbFile);<br/>
   4. Create an empty SQLStatement: var sql : SQLStatement = new SQLStatement();<br/>
   5. Create a query: var sqlString : String = "CREATE TABLE Users (" +<br/>
      &nbsp;&nbsp;&nbsp;&nbsp; " uid INTEGER PRIMARY KEY AUTOINCREMENT, " +<br/>
      &nbsp;&nbsp;&nbsp;&nbsp; " name TEXT, " +<br/>
      &nbsp;&nbsp;&nbsp;&nbsp; " phonenumber TEXT)";<br/>
   6. Attach the connection and the query to the SQLStatement:<br/>
          &nbsp;&nbsp;&nbsp;&nbsp; sql.sqlConnection = connection;<br/>
          &nbsp;&nbsp;&nbsp;&nbsp; sql.text = sqlString;<br/>
   7. Create event listeners for success and failure:<br/>
          &nbsp;&nbsp;&nbsp;&nbsp; sql.addEventListener(SQLEvent.RESULT, onDBCreateTableResult);<br/>
          &nbsp;&nbsp;&nbsp;&nbsp; sql.addEventListener(SQLErrorEvent.ERROR, onDBCreateTableError);<br/>
   8. Execute! : sql.execute()<br/><br/><br/><br/>

ﾠ
<textarea rows="50" cols="60">
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" 
	width="438" height="251" 
	creationComplete="onCreationComplete()">

<mx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.events.DataGridEvent;
import mx.collections.ArrayCollection;

[Bindable] public var dp : ArrayCollection = new ArrayCollection();

private var connection : SQLConnection;
public var dbStatement : SQLStatement;

public var dbFile : File;
public var dbFileString : String = "exampledb.db";

public function onCreationComplete():void
{
	connection = new SQLConnection();
	dbFile = File.applicationStorageDirectory.resolvePath(dbFileString);
	
	// does the database exist?
	if( dbFile.exists )
	{
		// the database exists, so let's open it and read in the data
		connection.open(dbFile);
		loadData();
	} else {
		// the database does not exists, so let's create it
		createDB();
	}
}

public function createDB() : void
{
	connection.addEventListener(SQLEvent.OPEN, onDBCreateResult);
	connection.addEventListener(SQLErrorEvent.ERROR, onDBError);

	// the following line creates the database if it does not exists, but we already know it doesn't
	connection.open(dbFile);
}

private function onDBCreateResult(event:SQLEvent):void
{
	// we successfully created the database, so let's create our table
	createTable();
}

/*
For this example we can use this error result handler for all our transactions
*/
private function onDBError(event:SQLErrorEvent):void
{
	Alert.show( event.error.name + " " + event.error.errorID + "\n" + event.error.details + "\n" + event.error.message);
}

public function createTable() : void
{
	var sql : SQLStatement = new SQLStatement();
	sql.sqlConnection = connection;
	
	var sqlString : String = "CREATE TABLE Users (" +
	" uid INTEGER PRIMARY KEY AUTOINCREMENT, " +
	" name TEXT, " +
	" phonenumber TEXT)";
	sql.text = sqlString;
	
	sql.addEventListener(SQLEvent.RESULT, onDBCreateTableResult);
	sql.addEventListener(SQLErrorEvent.ERROR, onDBCreateTableError);
	
	sql.execute();
	
	sqlString = "INSERT INTO Users ( name, phonenumber) " +
	"VALUES ( 'Mac Martine', '555-1212')";
	sql.text = sqlString;
	
	//sql.addEventListener(SQLEvent.RESULT, onDBAddResult);
	sql.addEventListener(SQLErrorEvent.ERROR, onDBError);
	
	sql.execute();
}

private function onDBCreateTableResult(event:SQLEvent):void
{
	trace('table created');
	loadData();
}

private function onDBCreateTableError(event:SQLErrorEvent):void
{
	Alert.show( event.error.name + " " + event.error.errorID + "\n" + event.error.details + "\n" + event.error.message);
	trace( event.error.name + " " + event.error.errorID + "\n" + event.error.details + "\n" + event.error.message);
}

private function loadData():void
{
	dbStatement = new SQLStatement();
	dbStatement.sqlConnection = connection;
	
	var sqlQuery:String = "select * from Users";
	dbStatement.text = sqlQuery;
	
	dbStatement.addEventListener(SQLEvent.RESULT, onRetrieveDataResult);
	dbStatement.addEventListener(SQLErrorEvent.ERROR, onDBError);
	
	dbStatement.execute();
}

private function onRetrieveDataResult(event:SQLEvent):void
{
	var result : SQLResult = dbStatement.getResult();
	dp = new ArrayCollection();
	for each( var el : Object in result.data )
	{
		dp.addItem( { uid: el.uid, name: el.name, phonenumber: el.phonenumber } );
	}
	trace('cache retrieved');
}

public function add():void
{
	var sql : SQLStatement = new SQLStatement();
	sql.sqlConnection = connection;
	
	dbStatement = new SQLStatement();
	dbStatement.sqlConnection = connection;
	
	var sqlString : String = "INSERT INTO Users ( name, phonenumber) " +
	"VALUES ( '(edit me)', '555-1212')";
	sql.text = sqlString;
	
	sql.addEventListener(SQLEvent.RESULT, onDBAddSuccess);
	sql.addEventListener(SQLErrorEvent.ERROR, onDBError);
	
	sql.execute();

}

public function onDBAddSuccess( event : SQLEvent ):void
{
	var result : SQLResult = dbStatement.getResult();
	var uid : Number = event.currentTarget.sqlConnection.lastInsertRowID;
	loadData();
}

public function remove():void
{
	var selectedItemUid : Number = dg.selectedItem.uid;
	var selectedIndex : Number = dg.selectedIndex;
	if( selectedIndex >= 0 )
	{
		var sql : SQLStatement = new SQLStatement();
		sql.sqlConnection = connection;
		
		dbStatement = new SQLStatement();
		dbStatement.sqlConnection = connection;
		
		ﾠﾠﾠﾠﾠﾠﾠﾠﾠﾠﾠﾠﾠﾠﾠﾠﾠﾠﾠﾠvar sqlString : String = "DELETE FROM Users WHERE uid=" + selectedItemUid;
		sql.text = sqlString;
		
		sql.addEventListener(SQLEvent.RESULT, onDBRemoveResult);
		sql.addEventListener(SQLErrorEvent.ERROR, onDBError);
		
		sql.execute();
		
	} else {
		Alert.show("You do not have a row selected to delete.");
	}
}

public function onDBRemoveResult( event : SQLEvent ):void
{
	loadData();
}

public function update( event : DataGridEvent ):void
{
	var sql : SQLStatement = new SQLStatement();
	sql.sqlConnection = connection;
	
	dbStatement = new SQLStatement();
	dbStatement.sqlConnection = connection;
	
	var sqlString : String = "UPDATE Users SET name = '" + event.itemRenderer.data.name + "' WHERE uid = " + event.itemRenderer.data.uid;
	sql.text = sqlString;
	
	//sql.addEventListener(SQLEvent.RESULT, onDBAddResult);
	sql.addEventListener(SQLErrorEvent.ERROR, onDBError);
	
	sql.execute();
}

]]&gt;
</mx:Script>

<mx:DataGrid id="dg" dataProvider="{dp}" x="10" y="37" width="407" height="202" editable="true" itemFocusOut="update(event)" >
<mx:columns>
<mx:DataGridColumn headerText="Name" dataField="name" editable="true" />
<mx:DataGridColumn headerText="Phone Number" dataField="phonenumber"/>
</mx:columns>
</mx:DataGrid>

<mx:LinkButton x="300" y="10" label="Add" click="add()"/>
<mx:LinkButton x="354" y="10" label="Remove" click="remove()"/>

</mx:WindowedApplication>

</textarea>]]></description>
         <link>http://www.macmartine.com/blog/2008/02/data_storage_and_caching_with.html</link>
         <guid>http://www.macmartine.com/blog/2008/02/data_storage_and_caching_with.html</guid>
         <category></category>
         <pubDate>Tue, 12 Feb 2008 09:45:43 -0800</pubDate>
      </item>
            <item>
         <title>InsideRIA launched today</title>
         <description><![CDATA[<p>Check out <a href="http://InsideRIA.com">InsideRIA.com</a> which was launched today. It's an online community developed by O'Reilly and sponsored by Adobe, which will provide a number of resources for information about RIA's, RIA development, and that which is related, with lots of attention on Flex, AIR, Actionscript and Flash.</p>

<p> </p>]]></description>
         <link>http://www.macmartine.com/blog/2008/01/insideria.html</link>
         <guid>http://www.macmartine.com/blog/2008/01/insideria.html</guid>
         <category></category>
         <pubDate>Mon, 21 Jan 2008 11:27:55 -0800</pubDate>
      </item>
            <item>
         <title>&apos;Designing For Flex&apos; series on devnet</title>
         <description><![CDATA[<p>If you haven't seen it yet I highly recommend taking the time to read through Rob Adams's <a href="http://www.adobe.com/devnet/flex/articles/fig_pt1.html">8 part series</a> of articles about designing <a href="http://www.adobe.com/cfusion/showcase/index.cfm?event=finder&productid=26724&loc=en_us">Flex applications</a>. The last article in the series, <a href="http://www.adobe.com/devnet/flex/articles/fig_pt8.html">Making your Applications Safe</a>, just went live a couple of days ago. It's an excellent guide to creating good experiences for your users.</p>

<p><br />
The Designing for Flex series includes the following articles:</p>

<ul>
  <li><a href="http://www.adobe.com/devnet/flex/articles/fig_pt1.html">Part 1: Overview and discovering Flex</a> </li>
  <li><a href="http://www.adobe.com/devnet/flex/articles/fig_pt2.html">Part 2: Planning your application </a></li>
  <li><a href="http://www.adobe.com/devnet/flex/articles/fig_pt3.html">Part 3: Structuring your application</a> </li>
  <li><a href="http://www.adobe.com/devnet/flex/articles/fig_pt4.html">Part 4: Merging the web and the desktop</a></li>
  <li><a href="http://www.adobe.com/devnet/flex/articles/fig_pt5.html">Part 5: Designing content displays</a></li>
  <li><a href="http://www.adobe.com/devnet/flex/articles/fig_pt6.html">Part 6: Guiding with motion</a></li>
  <li><a href="http://www.adobe.com/devnet/flex/articles/fig_pt7.html">Part 7: Making your application fast</a></li>
  <li><a href="http://www.adobe.com/devnet/flex/articles/fig_pt8.html">Part 8: Making your application safe</a></li>
  <li><a href="http://www.adobe.com/devnet/flex/articles/fig_appendixa.html">Appendix A: List of best practices</a></li>
  <li><a href="http://www.adobe.com/devnet/flex/articles/fig_appendixb.html">Appendix B: For further reading</a><br />
  </li>
</ul>]]></description>
         <link>http://www.macmartine.com/blog/2008/01/robs_ui_articles.html</link>
         <guid>http://www.macmartine.com/blog/2008/01/robs_ui_articles.html</guid>
         <category></category>
         <pubDate>Wed, 16 Jan 2008 14:02:31 -0800</pubDate>
      </item>
            <item>
         <title>Deferred instantiation of mediators in a PureMVC Flex application</title>
         <description><![CDATA[<p>I'm creating my first project using PureMVC after using Cairngorm for a few projects. Once I started understanding the concepts and intent behind each of the architecture components (Proxies and Models, Views and Mediators, Controllers and Commands), it's been great in it's relative simplicity. I did printed out the docs and read over them everyday at lunch for a few days in a row just make it all really sink it, but it didn't take too long to click. <br />
The best part is that I've had a few questions so I decided to check out the PureMVC forums on the PureMVC site. So far everything I've searched has returned a thread with a very detailed, extensive answer from Cliff! The days go so much easier when there's easy to find and good information about whatever your working with.</p>

<p>One of the problems I ran into pretty quickly was that I had a TabNavigator with 3 tabs where the contents aren't to be drawn or loaded until they are clicked on. <br />
I initially tried to register the mediators for those 3 view components at startup, which to no surprise threw runtime errors because the views didn't yet exist. Not being sure what the best solution was here, I searched the forums and found <a href="http://forums.puremvc.org/index.php?topic=113.0">this thread</a>.</p>

<p>I went with Cliff's recommendation (deferred instantiation) and here's what I have now:</p>

<p>My TabNavigator has 3 tabs each containing one custom component named "tags", "groups", "info".<br />
In each of these components I have a creationComplete event which calls an onCreationComplete function, which in turn dispatches a custom Event:</p>

<pre>
dispatchEvent( new ComponentLoadedEvent( ComponentLoadedEvent.COMPONENT_LOADED, true, false, this ) );
</pre>

<p>The mediator of the TabNavigator itself listens for this event and calls handleLoad when it hears it:</p>

<pre>
mainComponent.addEventListener( ComponentLoadedEvent.COMPONENT_LOADED, handleLoad );
</pre>

<p>The handleLoad() registers the appropriate mediator for the loaded component:</p>

<pre>
public function handleLoad( e : Event ):void
{
    var component :Object 	= e["component"].name;
			
    switch(component)
    { 
        case "tags":
            facade.registerMediator( new TagsMediator( mainComponent.tags )  );
            break;
        case "groups":
            facade.registerMediator( new GroupsMediator( mainComponent.groups )  );
            break;
        case "info":
            facade.registerMediator( new UploadStatusMediator( mainComponent.info )  );
            break;
    }
}
</pre>

<p><br />
</p>]]></description>
         <link>http://www.macmartine.com/blog/2008/01/deferred_instantiation_of_medi.html</link>
         <guid>http://www.macmartine.com/blog/2008/01/deferred_instantiation_of_medi.html</guid>
         <category></category>
         <pubDate>Mon, 14 Jan 2008 15:14:39 -0800</pubDate>
      </item>
            <item>
         <title>Creating authenticated/signed Flickr API calls in Flex/Actionscript</title>
         <description><![CDATA[<p>Since the individual doc pages for the Flickr API calls don't tell you how to create a signed API call, it took me a minute to figure it out. This info can be found in the <a href="http://www.flickr.com/services/api/misc.userauth.html">Flickr User Authentication docs</a>, but here's how to create a signed call.</p>

<p>Let's say you want to call flickr.people.getUploadStatus.<br />
Well, the call requires authentication or else it won't do you any good. Once you are authenticated you create the call by performing the following steps:</p>

<p>1) Create a string using the required parameter names plus their values in alphabetical order (i.e. "api_key" + api_key_value .) Then preceed this string with the shared_secret, and append the string with the string "method" plus the method name. Note that every authenticated call requires both the auth_token and api_sig arguments. </p>

<p>So, in the case of flickr.people.getUploadStatus the string would look something like:</p>

<pre>
var api_sig : String = shared_secret + "api_key" + api_key_value+ "auth_token" + token_value + "method" + "flickr.people.getUploadStatus"
</pre>

<p>2) Then get the MD5() of this string. As I mention in another post, I use <a href="http://gsolofp.blogspot.com/2006/01/actionscript-3-md5-and-sha1.html">this</a> class, and simply call  MD5.encrypt( myString )</p>

<pre>
var api_sig_encrypted : String = MD5.encrypt( api_sig );
</pre>

<p>3) We can then make the call:</p>

<pre>
var params : Object = { "method": "flickr.people.getUploadStatus", "api_key": api_key, "api_sig" : api_sig_encrypted, "auth_token" : auth_token }; 
codeService.request = params;
codeService.url 	= "http://api.flickr.com/services/rest/";

<p>codeService.addEventListener( ResultEvent.RESULT, getUploadStatusResult );<br />
codeService.addEventListener( FaultEvent.FAULT, faultResult );</p>

<p>codeService.send();<br />
</pre></p>]]></description>
         <link>http://www.macmartine.com/blog/2008/01/creating_authenticatedsigned_f.html</link>
         <guid>http://www.macmartine.com/blog/2008/01/creating_authenticatedsigned_f.html</guid>
         <category></category>
         <pubDate>Mon, 14 Jan 2008 14:32:26 -0800</pubDate>
      </item>
            <item>
         <title>MD5 for Actionscript</title>
         <description><![CDATA[<p>I'm working on a Flex/AIR application that  requires Flickr authentication so I needed an MD5 class for Actionscript. <a href="http://gsolofp.blogspot.com/2006/01/actionscript-3-md5-and-sha1.html">Here's</a> the one i've been using and it's been working great. It's simple and doesn't have a load of extra unnecessary baggage.</p>]]></description>
         <link>http://www.macmartine.com/blog/2008/01/md5_for_actionscript_1.html</link>
         <guid>http://www.macmartine.com/blog/2008/01/md5_for_actionscript_1.html</guid>
         <category></category>
         <pubDate>Mon, 14 Jan 2008 14:25:15 -0800</pubDate>
      </item>
            <item>
         <title>Setting itemRenderer in Actionscript</title>
         <description><![CDATA[Some things seem so straight-forward once you figure them out, but sometimes it takes some experimenting to find the working solution. One thing I got stumped on for a bit recently was trying to set an itemRenderer in Actionscript. So I thought I'd share this one-liner -- you just have to cast it as a ClassFactory:

<pre>

listObj.itemRenderer = new ClassFactory( com.martine.components.myItemRenderer );

</pre>

]]></description>
         <link>http://www.macmartine.com/blog/2007/12/setting_itemrenderer_in_action.html</link>
         <guid>http://www.macmartine.com/blog/2007/12/setting_itemrenderer_in_action.html</guid>
         <category></category>
         <pubDate>Fri, 14 Dec 2007 07:35:44 -0800</pubDate>
      </item>
      
   </channel>
</rss>
