<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>mac martine</title>
    <link rel="alternate" type="text/html" href="http://www.macmartine.com/blog/" />
    <link rel="self" type="application/atom+xml" href="http://www.macmartine.com/blog/atom.xml" />
   <id>tag:www.macmartine.com,2008:/blog//1</id>
    <link rel="service.post" type="application/atom+xml" href="http://www.macmartine.com/blog/mt-atom.cgi/weblog/blog_id=1" title="mac martine" />
    <updated>2008-04-10T16:21:10Z</updated>
    <subtitle>dallying with Flex, Air, and other surprises...</subtitle>
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type 3.2</generator>
 
<entry>
    <title>Installing Coldfusion and JRun on OS X</title>
    <link rel="alternate" type="text/html" href="http://www.macmartine.com/blog/2008/04/installing_coldfusion_and_jrun_1.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.macmartine.com/blog/mt-atom.cgi/weblog/blog_id=1/entry_id=33" title="Installing Coldfusion and JRun on OS X" />
    <id>tag:www.macmartine.com,2008:/blog//1.33</id>
    
    <published>2008-04-10T16:21:53Z</published>
    <updated>2008-04-10T16:21:10Z</updated>
    
    <summary>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&apos;t. Here were the biggies...</summary>
    <author>
        <name>Mac Martine</name>
        <uri>http://www.macmartine.com/blog/</uri>
    </author>
            <category term="ColdFusion" />
            <category term="Linux" />
    
    <content type="html" xml:lang="en" xml:base="http://www.macmartine.com/blog/">
        <![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>]]>
        
    </content>
</entry>
<entry>
    <title>Adding a user to sudoers file</title>
    <link rel="alternate" type="text/html" href="http://www.macmartine.com/blog/2008/04/adding_a_user_to_sudoers_file.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.macmartine.com/blog/mt-atom.cgi/weblog/blog_id=1/entry_id=34" title="Adding a user to sudoers file" />
    <id>tag:www.macmartine.com,2008:/blog//1.34</id>
    
    <published>2008-04-09T15:59:31Z</published>
    <updated>2008-04-09T16:00:05Z</updated>
    
    <summary>On Linux you&apos;ll need to add your user account to the sudoers file so you can run certain tasks as a superuser (sudo, su). Here&apos;s an easy way: Log in with your user account (not as root): [martine@machine ~]# sudo...</summary>
    <author>
        <name>Mac Martine</name>
        <uri>http://www.macmartine.com/blog/</uri>
    </author>
            <category term="Linux" />
    
    <content type="html" xml:lang="en" xml:base="http://www.macmartine.com/blog/">
        <![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>]]>
        
    </content>
</entry>
<entry>
    <title>Crossdomain.xml files in Rails projects</title>
    <link rel="alternate" type="text/html" href="http://www.macmartine.com/blog/2008/04/crossdomainxml_files_in_rails.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.macmartine.com/blog/mt-atom.cgi/weblog/blog_id=1/entry_id=35" title="Crossdomain.xml files in Rails projects" />
    <id>tag:www.macmartine.com,2008:/blog//1.35</id>
    
    <published>2008-04-08T16:44:35Z</published>
    <updated>2008-04-08T16:44:04Z</updated>
    
    <summary>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. I&apos;ve found one exception which is if you are making...</summary>
    <author>
        <name>Mac Martine</name>
        <uri>http://www.macmartine.com/blog/</uri>
    </author>
            <category term="Flex" />
            <category term="Rails" />
    
    <content type="html" xml:lang="en" xml:base="http://www.macmartine.com/blog/">
        <![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>]]>
        
    </content>
</entry>
<entry>
    <title>Resolving gcc errors installing sqlite3 gem on Leopard</title>
    <link rel="alternate" type="text/html" href="http://www.macmartine.com/blog/2008/04/resolving_gcc_errors_installin.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.macmartine.com/blog/mt-atom.cgi/weblog/blog_id=1/entry_id=36" title="Resolving gcc errors installing sqlite3 gem on Leopard" />
    <id>tag:www.macmartine.com,2008:/blog//1.36</id>
    
    <published>2008-04-03T17:02:07Z</published>
    <updated>2008-04-03T17:03:08Z</updated>
    
    <summary>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. Running ‘sudo ./configure --prefix=/usr/local’ would...</summary>
    <author>
        <name>Mac Martine</name>
        <uri>http://www.macmartine.com/blog/</uri>
    </author>
            <category term="OS X" />
            <category term="SQLite" />
    
    <content type="html" xml:lang="en" xml:base="http://www.macmartine.com/blog/">
        <![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>]]>
        
    </content>
</entry>
<entry>
    <title>Flex and ColdFusion: RemoteObjects and WebServices</title>
    <link rel="alternate" type="text/html" href="http://www.macmartine.com/blog/2008/04/flex_and_coldfusion_remoteobje.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.macmartine.com/blog/mt-atom.cgi/weblog/blog_id=1/entry_id=37" title="Flex and ColdFusion: RemoteObjects and WebServices" />
    <id>tag:www.macmartine.com,2008:/blog//1.37</id>
    
    <published>2008-04-02T19:33:57Z</published>
    <updated>2008-04-02T19:47:43Z</updated>
    
    <summary>Once you have a ColdFusion CFC you can call it&apos;s methods with a RemoteObject or via a WebService. RemoteObjects are usually preferred for their performance speed. Here we&apos;ll create a super basic example of calling a CFC from both a...</summary>
    <author>
        <name>Mac Martine</name>
        <uri>http://www.macmartine.com/blog/</uri>
    </author>
            <category term="ColdFusion" />
            <category term="Flex" />
    
    <content type="html" xml:lang="en" xml:base="http://www.macmartine.com/blog/">
        <![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/>]]>
        <![CDATA[To set up our examples, let create a most basic CFC. Let's call this file NEWCFComponent.cfc and this'll be it's contents:
<br/><br/>
<textarea rows="10" cols="60">
<cfcomponent displayname="CF_Service" output="false">

<cffunction name="WelcomeMsg" access="remote" returntype="string">
	
	<cfargument name="name" type="string" required="yes">
		<cfreturn "YO, #name#!">

</cffunction>

</cfcomponent>

</textarea>
<br/><br/>
You can see this simply takes the #name# variable that it retrieves and returns the welcome message "Yo, #name#!".
<br/><br/>
Okay, let's first call this with a WebService. Just create a basic local Flex project.
Here's the main application for that project:
<br/><br/>
<textarea rows="25" cols="60">
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">

	<mx:Script>
		<![CDATA[
			import mx.rpc.events.FaultEvent;
			import mx.rpc.Fault;
			import mx.rpc.events.ResultEvent;
			
			private function onResult( e : ResultEvent ) :void
			{
				msg.text = e.result.toString();
			}
			
			private function onFault( e : FaultEvent ) :void
			{
				trace( 'Oops!' );
			}
			
			
		]]&gt;
	</mx:Script>
	
	<mx:WebService id="ws"
	 wsdl="http://<server-name-or-IP>:8500/cf/CF_Service/NewCFComponent.cfc?wsdl"
	 showBusyCursor="true">
		<mx:operation name="WelcomeMsg"
	 		result="onResult(event)"
	 		fault="onFault(event)">
	 		<mx:request xmlns="">
	 			<name>
	 				{_name.text}
	 			</name>
	 		</mx:request>
	 	</mx:operation>
	 </mx:WebService>

	<mx:Button x="284" y="10" label="Get Welcome Message." click="ws.WelcomeMsg.send()"/>
	<mx:TextInput id="msg" x="681" y="10"/>
	<mx:TextInput id="_name" x="116" y="10"/>
	<mx:Label x="10" y="12" text="Enter your name:"/>
	
</mx:Application>
</textarea>
<br/><br/>

Modify the 'wsdl' attribute of the WebService tag as necessary to point to your CF server.
<br/><br/>

That's it! Now Run the Flex app, enter your name, click the button and see your welcome message!
<br/><br/>
Now let's do the same thing but use a RemoteObject.
<br/><br/>
Create a Flex Project and in the Flex Project Wizard choose 'ColdFusion' for the server type and 'ColdFusion Flash Remoting'. Point the 'Web root' and 'Root URL' to your CF server.
<br/><br/>

Use the same contents for the Flex application as above except remove the WebService tag and all it's contents, and put this in it's place:

<br/><br/>
<textarea rows="5" cols="60">
	<mx:RemoteObject id="ws" destination="ColdFusion" source="cf.CF_Service.NewCFComponent">
    	<mx:method name="WelcomeMsg" result="onResult(event)" fault="onFault(event)"/>
	</mx:RemoteObject>
</textarea>
<br/><br/>
The 'destination' is the remote destination as defined in remoting-config.xml (located in the <cf-server-root>/WEB-INF/flex directory). 'ColdFusion' is a pre-defined, built-in destination.
The 'source' attribute should point to the location of your CFC starting at the server root. Note that this does not include the CFC extension, just the name of the CFC.
<br/><br/>
Go ahead and run the app and it should behave just the same as the WebService version we created above, but maybe faster.
<br/><br/>
If you want to create you own destination you can do that easily. Open remoting-config.xml (located in the <cf-server-root>/WEB-INF/flex directory and add this destination:
<br/><br/>
<textarea rows="25" cols="60">

<destination id="cfRemotingExample">
  <channels>
    <channel ref="my-cfamf"/>
  </channels>
  <properties>
    <source>cf.CF_Service.NewCFComponent</source>
      <!-- define the resolution rules and access level of the cfc being invoked -->
      <access>
      <!-- Use the ColdFusion mappings to find CFCs, by default only CFC files under your webroot can be found. -->
      <use-mappings>false</use-mappings>
      <!-- allow "public and remote" or just "remote" methods to be invoked -->
      <method-access-level>remote</method-access-level>
    </access>
 
    <property-case>
      <!-- cfc property names -->
      <force-cfc-lowercase>false</force-cfc-lowercase>
      <!-- Query column names -->
      <force-query-lowercase>false</force-query-lowercase>
      <!-- struct keys -->
      <force-struct-lowercase>false</force-struct-lowercase>
    </property-case>
  </properties>
</destination>
</textarea>
<br/><br/>
The 'source' attribute should point to the location of your CFC starting at the server root. This should be identical to the 'source' attribute you had in your RemoteObject tag. 
<br/><br/>
Now a couple quick modifications to the RemoteObject and we're good to go:

<br/><br/>

<textarea rows="5" cols="60">
	<mx:RemoteObject id="ws" destination="cfRemotingExample" showBusyCursor="true">
    	<mx:method name="WelcomeMsg" result="onResult(event)" fault="onFault(event)"/>
	</mx:RemoteObject>
</textarea>

<br/><br/>

Notice we just changed the 'destination' attribute to point to our new destination name, and we removed the 'source' attribute because we included that in the <source> of our custom destination in remoting.config.xml.














For now we'll just use the default remote destination configured in remoting-config.xml (located in the <cf-server-root>/WEB-INF/flex directory)

]]>
    </content>
</entry>
<entry>
    <title>Linux: chcon to change security context (to solve permissions problems with mounted shares)</title>
    <link rel="alternate" type="text/html" href="http://www.macmartine.com/blog/2008/04/linux_chcon_to_change_security_1.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.macmartine.com/blog/mt-atom.cgi/weblog/blog_id=1/entry_id=31" title="Linux: chcon to change security context (to solve permissions problems with mounted shares)" />
    <id>tag:www.macmartine.com,2008:/blog//1.31</id>
    
    <published>2008-04-02T17:03:46Z</published>
    <updated>2008-04-02T17:04:12Z</updated>
    
    <summary>On my Fedora server I was creating some shared folders that I could mount from my other machines. So I created a Samba share, and chmod-ed the directories. From my other machine I mounted a share and all seemed swell...</summary>
    <author>
        <name>Mac Martine</name>
        <uri>http://www.macmartine.com/blog/</uri>
    </author>
            <category term="Linux" />
    
    <content type="html" xml:lang="en" xml:base="http://www.macmartine.com/blog/">
        <![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>]]>
        
    </content>
</entry>
<entry>
    <title>Adobe Online Developer Week</title>
    <link rel="alternate" type="text/html" href="http://www.macmartine.com/blog/2008/03/adobe_online_developer_week.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.macmartine.com/blog/mt-atom.cgi/weblog/blog_id=1/entry_id=30" title="Adobe Online Developer Week" />
    <id>tag:www.macmartine.com,2008:/blog//1.30</id>
    
    <published>2008-03-24T17:42:00Z</published>
    <updated>2008-03-24T17:45:41Z</updated>
    
    <summary>Join us for the Adobe Online Developer Week which already under way! http://adobe.com/go/2008_developer_week There are a bunch of cool sessions about Flex, AIR, LCDS and more......</summary>
    <author>
        <name>Mac Martine</name>
        <uri>http://www.macmartine.com/blog/</uri>
    </author>
            <category term="AIR" />
            <category term="Flex" />
    
    <content type="html" xml:lang="en" xml:base="http://www.macmartine.com/blog/">
        <![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>]]>
        
    </content>
</entry>
<entry>
    <title>Flex 3 and AIR 1.0 released!</title>
    <link rel="alternate" type="text/html" href="http://www.macmartine.com/blog/2008/02/flex_3_and_air_10_released.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.macmartine.com/blog/mt-atom.cgi/weblog/blog_id=1/entry_id=29" title="Flex 3 and AIR 1.0 released!" />
    <id>tag:www.macmartine.com,2008:/blog//1.29</id>
    
    <published>2008-02-25T19:39:10Z</published>
    <updated>2008-02-25T19:47:23Z</updated>
    
    <summary>Check &apos;em out! http://www.adobe.com/products/flex/ http://www.adobe.com/products/air/ And here&apos;s a good New York Times article about AIR: Adobe Blurs Lines Between PC and Web...</summary>
    <author>
        <name>Mac Martine</name>
        <uri>http://www.macmartine.com/blog/</uri>
    </author>
            <category term="AIR" />
            <category term="Flex" />
    
    <content type="html" xml:lang="en" xml:base="http://www.macmartine.com/blog/">
        <![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>]]>
        
    </content>
</entry>
<entry>
    <title>Data storage and caching with SQLite databases and Adobe AIR</title>
    <link rel="alternate" type="text/html" href="http://www.macmartine.com/blog/2008/02/data_storage_and_caching_with.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.macmartine.com/blog/mt-atom.cgi/weblog/blog_id=1/entry_id=26" title="Data storage and caching with SQLite databases and Adobe AIR" />
    <id>tag:www.macmartine.com,2008:/blog//1.26</id>
    
    <published>2008-02-12T17:45:43Z</published>
    <updated>2008-02-12T21:25:13Z</updated>
    
    <summary>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...</summary>
    <author>
        <name>Mac Martine</name>
        <uri>http://www.macmartine.com/blog/</uri>
    </author>
            <category term="AIR" />
            <category term="Actionscript" />
            <category term="Flex" />
            <category term="SQLite" />
    
    <content type="html" xml:lang="en" xml:base="http://www.macmartine.com/blog/">
        <![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>]]>
        
    </content>
</entry>
<entry>
    <title>InsideRIA launched today</title>
    <link rel="alternate" type="text/html" href="http://www.macmartine.com/blog/2008/01/insideria.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.macmartine.com/blog/mt-atom.cgi/weblog/blog_id=1/entry_id=25" title="InsideRIA launched today" />
    <id>tag:www.macmartine.com,2008:/blog//1.25</id>
    
    <published>2008-01-21T19:27:55Z</published>
    <updated>2008-01-21T19:12:25Z</updated>
    
    <summary>Check out InsideRIA.com which was launched today. It&apos;s an online community developed by O&apos;Reilly and sponsored by Adobe, which will provide a number of resources for information about RIA&apos;s, RIA development, and that which is related, with lots of attention...</summary>
    <author>
        <name>Mac Martine</name>
        <uri>http://www.macmartine.com/blog/</uri>
    </author>
            <category term="AIR" />
            <category term="Actionscript" />
            <category term="Flex" />
    
    <content type="html" xml:lang="en" xml:base="http://www.macmartine.com/blog/">
        <![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>]]>
        
    </content>
</entry>
<entry>
    <title>&apos;Designing For Flex&apos; series on devnet</title>
    <link rel="alternate" type="text/html" href="http://www.macmartine.com/blog/2008/01/robs_ui_articles.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.macmartine.com/blog/mt-atom.cgi/weblog/blog_id=1/entry_id=27" title="'Designing For Flex' series on devnet" />
    <id>tag:www.macmartine.com,2008:/blog//1.27</id>
    
    <published>2008-01-16T22:02:31Z</published>
    <updated>2008-01-17T17:19:30Z</updated>
    
    <summary>If you haven&apos;t seen it yet I highly recommend taking the time to read through Rob Adams&apos;s 8 part series of articles about designing Flex applications. The last article in the series, Making your Applications Safe, just went live a...</summary>
    <author>
        <name>Mac Martine</name>
        <uri>http://www.macmartine.com/blog/</uri>
    </author>
            <category term="Design" />
            <category term="Flex" />
    
    <content type="html" xml:lang="en" xml:base="http://www.macmartine.com/blog/">
        <![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>]]>
        
    </content>
</entry>
<entry>
    <title>Deferred instantiation of mediators in a PureMVC Flex application</title>
    <link rel="alternate" type="text/html" href="http://www.macmartine.com/blog/2008/01/deferred_instantiation_of_medi.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.macmartine.com/blog/mt-atom.cgi/weblog/blog_id=1/entry_id=22" title="Deferred instantiation of mediators in a PureMVC Flex application" />
    <id>tag:www.macmartine.com,2008:/blog//1.22</id>
    
    <published>2008-01-14T23:14:39Z</published>
    <updated>2008-01-16T17:08:54Z</updated>
    
    <summary>I&apos;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&apos;s been great...</summary>
    <author>
        <name>Mac Martine</name>
        <uri>http://www.macmartine.com/blog/</uri>
    </author>
            <category term="Actionscript" />
            <category term="Flex" />
            <category term="PureMVC" />
    
    <content type="html" xml:lang="en" xml:base="http://www.macmartine.com/blog/">
        <![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>]]>
        
    </content>
</entry>
<entry>
    <title>Creating authenticated/signed Flickr API calls in Flex/Actionscript</title>
    <link rel="alternate" type="text/html" href="http://www.macmartine.com/blog/2008/01/creating_authenticatedsigned_f.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.macmartine.com/blog/mt-atom.cgi/weblog/blog_id=1/entry_id=21" title="Creating authenticated/signed Flickr API calls in Flex/Actionscript" />
    <id>tag:www.macmartine.com,2008:/blog//1.21</id>
    
    <published>2008-01-14T22:32:26Z</published>
    <updated>2008-01-15T15:56:41Z</updated>
    
    <summary>Since the individual doc pages for the Flickr API calls don&apos;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 Flickr User Authentication docs,...</summary>
    <author>
        <name>Mac Martine</name>
        <uri>http://www.macmartine.com/blog/</uri>
    </author>
            <category term="Flex" />
            <category term="Flickr API" />
    
    <content type="html" xml:lang="en" xml:base="http://www.macmartine.com/blog/">
        <![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>]]>
        
    </content>
</entry>
<entry>
    <title>MD5 for Actionscript</title>
    <link rel="alternate" type="text/html" href="http://www.macmartine.com/blog/2008/01/md5_for_actionscript_1.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.macmartine.com/blog/mt-atom.cgi/weblog/blog_id=1/entry_id=20" title="MD5 for Actionscript" />
    <id>tag:www.macmartine.com,2008:/blog//1.20</id>
    
    <published>2008-01-14T22:25:15Z</published>
    <updated>2008-01-14T23:42:33Z</updated>
    
    <summary>I&apos;m working on a Flex/AIR application that requires Flickr authentication so I needed an MD5 class for Actionscript. Here&apos;s the one i&apos;ve been using and it&apos;s been working great. It&apos;s simple and doesn&apos;t have a load of extra unnecessary baggage....</summary>
    <author>
        <name>Mac Martine</name>
        <uri>http://www.macmartine.com/blog/</uri>
    </author>
            <category term="AIR" />
            <category term="Flex" />
            <category term="Flickr API" />
    
    <content type="html" xml:lang="en" xml:base="http://www.macmartine.com/blog/">
        <![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>]]>
        
    </content>
</entry>
<entry>
    <title>Setting itemRenderer in Actionscript</title>
    <link rel="alternate" type="text/html" href="http://www.macmartine.com/blog/2007/12/setting_itemrenderer_in_action.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.macmartine.com/blog/mt-atom.cgi/weblog/blog_id=1/entry_id=19" title="Setting itemRenderer in Actionscript" />
    <id>tag:www.macmartine.com,2007:/blog//1.19</id>
    
    <published>2007-12-14T15:35:44Z</published>
    <updated>2007-12-14T16:26:16Z</updated>
    
    <summary>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...</summary>
    <author>
        <name>Mac Martine</name>
        <uri>http://www.macmartine.com/blog/</uri>
    </author>
    
    <content type="html" xml:lang="en" xml:base="http://www.macmartine.com/blog/">
        <![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>

]]>
        
    </content>
</entry>

</feed> 

