Making air do crazy things

So technically Adobe Air doesn't have direct OS level integration, we can only hope the next version does. But that doesn't mean it's not possible. Louie Penaflor (a member of the Digital Primates team) has still been able to make AIR bend to his will, with some help from the Artemis project. He has written an application that let's AIR control his scanner. So from inside his application he can scan his travel receipts.

Read all about it here: http://www.restlessthinker.com/blog/?p=69

FlexCamp Chicago presentation and examples

First I just want to thank everyone who attended the FlexCamp in Chicago. As promised here is the presentation I did and the two examples I walked through.

Presentation
Examples
(these use the sample database that ship with ColdFusion)

Flex Camp Chicago! - limited space available, sign up now while you still can

Are you a flex developer? Are you still learning new things about flex? Are you planning on learning flex? Do you want to meet other flex developers in the area? Do you live near Chicago, IL?

Then you need to register and come to the next Flex Camp right here in Chicago, on Jan 18th, before it sells out. Plus you get a FREE COPY OF "Adobe Flex 2: Training from the Source" - thanks to PeachPit Press.

Flex Camp is a one day, all day, conference about Flex with something for everyone - Flex Component development, Air development, CF Integration, and Java Integration. Plus I'm a speaker!

And it's easy to get to, Flex Camp will be located at the Illinois Technology Association, 200 S. Wacker Drive, 15th Floor. Which is right by Union Station in downtown Chicago.

Click here to learn more and register:
http://www.flexcampchicago.com/

Tapper, Nimer & Assoc. + Digital Primates IT Consulting

I'm happy to finally be able to tell the world that Tapper, Nimer & Associates and Digital Primates have decided to join forces. Now that the lawyers are done the merger is complete.

The new company will be keeping the name Digital Primates. If you'd like to learn more about Digital Primates check out our web site at http://www.digitalprimates.net

It's an exciting time in the RIA world and for us it just got a lot more exciting!

P.S. We are looking for a few great flex developers and flash video experts. If you're interested send me your resume.

dpUnit = new flex unit testing framework

[Update] Correction: The name is dpUint, not dpUnit. I guess I'm so used to all of XUnit frameworks I didn't even notice the spelling difference at first.

In case you didn't see this earlier Mike Labriola from Digital Primates (http://www.digitalprimates.net) has released a new open source unit testing framework for flex this week ( dpUnit )

Why is this cool?:

  • 1. Support full testing of Asynchronous actions (correctly).
  • 2. Trigger and listen for any event in your application and validate it in the unit test.(UI, Validation, or server).
  • 3. hain a series of actions into a sequence.
    This means you can define a series of application actions in your test case and they will be executed in sequence during the test. But even better - you can also add waits between these steps so the test case will not perform the next step until some event has been fired from the current step or timed-out and failed. For instance until a property has been set (VALUE_COMMIT event).
  • 4.You can write UI Component unit tests!!!!
    This is unique to dpUnit - With dpUnit you can instantiate a new UI Component and trigger events and test that the UI Component actual does what it should. Instead of just testing individual functions or classes


    For instance if have a edit form component, you can create a new instance and set the values of the different form fields. Then you can trigger the validation and run asserts in your unit tests to check that the form validation happened correctly.

Let me say this again, you can write UI Component Unit tests!.

Download it here

Baby meet world - world meet baby nimer!

No one ever called me the quickest blogger, but I'm excited to announce the newest nimer in the world.



Kayden Michael Nimer
Born: Oct 29th 2007
7lbs 10oz - 21" long


Kayden is a perfectly healthy baby boy and both mom and are baby are doing great. So being a new dad I can't stop thinking about the question where do I start with all of these cool toy options? :)

Flex Tip - Trigger validation when submitting form

I just noticed a common pattern in the way I do validation, so I thought I would share. (in case you didn't know this already)

The validators are great at telling the user what is required or failing validation as the tab through the form. However they don't actually block the user from submitting the invalid form. But there is a simple way to do this with the validators.

1. Group all of the validators into an MX:ARRAY tag, and give it a unique id. - I usually use "validators"

<mx:Array id="validators">
   <mx:StringValidator source="{abbreviations}" property="text" required="true"/>
   <mx:StringValidator source="{subcode}" property="text" required="true"/>
   <mx:StringValidator source="{name}" property="text" required="true"/>
   <mx:StringValidator source="{letterType}" property="text" required="true"/>
   <mx:StringValidator   source="{scheduleType}" property="text" required="true"/>
</mx:Array>

Since the validators are now all grouped in an Array, you can call the Validator.validateAll() function to check them all at once.

2. Use this if statement in the click event of your form submit button to check the validators before submitting. You can also add this if check inside your doSave() method too. whichever you prefer.

if( Validator.validateAll(validators).length==0 ){ doSave() }

<mx:Button
   label="Save"
   click="if( Validator.validateAll(validators).length==0 ){ doSave() }"/>

Suddenly I don't want anything to do with plastic products.

"A vast swath of the Pacific, twice the size of Texas, is full of a plastic stew that is entering the food chain. Scientists say these toxins are causing obesity, infertility...and worse"

There is everything wrong with the fact that this pile of trash exists. And even worse, there is more than one in the world.

I don't even know where to begin with a solution. But cutting back on the use of plastic seems like a good place to start. Everything doesn't need to be made out of plastic, I know I prefer the glass coke bottles to the plastic ones. Maybe some mandatory recycling programs are needed. I just hope something changes other wise the world 20 years from now could be a nasty place to live.

Read article

I want to see this - looks like I need to go to Berlin

"Placed at the lobby of the Radisson SAS Hotel in Berlin, the 25 meters high AquaDom is the largest cylindrical aquarium ever built." http://fogonazos.blogspot.com/2007/01/aquadom-worlds-largest-cylindrical.html

Bye bye -services!

When you are building an application that uses the Flex FDS or ColdFusion servers as a back-end you need to define in your FlexBuilder project properties an additional compiler argument, -services. Why? FlexBuilder needs this argument/path to your services-config.xml file so it can pull just a few pieces of information out of the xml file. In turn, these pieces of information are what allows your flex client application to know what server to talk to and how. However, this has a few drawbacks.

  • You need to be able to access your services-config.xml file. Which can be difficult if you are developing against a remote Flex server. Confusion with the launch url in FlexBuilder.
  • By default endpoint urls in the services-config.xml use wildcards to define the host/port of the url "{server.host} and {server.port}". However, the default for FlexBuilder is to launch flex applications with a file://c:\ absolute path, easily corrected but still the default. Now the problem is that if your movie is launched with a file:// path, Flex can't use the {server.host}/{server.port} wildcards (there is no http url to pull the host and port from)
  • But, you can't hardcode the url in services-config.xml either. Otherwise your .swf will be compiled with a url that points back to your development server. And you don't want to recompile the .swf for production because then the .swf you tested is NOT the same .swf as the one you deploy. (you always want to deploy the same code you test). Context-root problems, if you develop with one context-root and deploy to production under a different context-root - Watch out!
  • Because the context-root needs to be hard coded in the services-config.xml or defined as a compiler argument in FlexBuilder too, it is compiled into the swf as a hard coded value. Which means, you need a different .swf for each platform you run one (a testing nightmare).

Alas, there is a solution! (You knew I was going there didn't you). All of this can be defined at runtime without the -services argument and the services-config.xml. Defining this at runtime also has a few advantages.

  • Your context-root can be defined at runtime as a FlashVar and your .cfm or .jsp can easily set that with a simple variable.
  • You can switch URL's as needed, for instance if the movie is loaded under an http:// url, use the wildcards. If it's loaded under a file:// or c:\.. path use a hard coded development url.
  • Different developer enviroments and configurations don't matter, everyone should be able to drop the code, sorry sync from source control, on their machine and run the application.

There are different ways to do this but how I do it is with 2 files; a ConfigModel class and a standard ServiceLocator class.

ConfigModel.as

package model
{
   import mx.core.Application;
   import mx.controls.Alert;
   import mx.utils.ObjectUtil;
   
   /**
    * Used to store Application config settings, and the
    * FlashRemoting channel and endpoint url settings, with this you
    * won't need define a -services compiler argument for the project.
    *
    * @author: Mike Nimer
    **/
   [Bindable(event="configChange")]
   public class ConfigModel
   {
      public static var TIMEZONEOFFSET:Number; //est=4 or 5, depending on DST       
      // debug setting to switch between live and stub data       public static const USE_STUB_DATA:Boolean = false;

      // Flash remoting config issues       public static const CHANNELID:String = "orca-amf";      
      private static const default_context_root:String = "/"; // adjust as needed for your default server.

      /**
       * pull the context-root out of the flash var, if it's defined in your <object/> or <embed/> tags.
       * ex: contextRoot=/flex
       **/      
      private static function get CONTEXT_ROOT():String
      {
         var app:Application = Application.application as Application;
         if( app.parameters.contextRoot != null )
         {
            //Alert.show( ObjectUtil.toString(app.parameters) );             return    app.parameters.contextRoot;
         }
         return ConfigModel.default_context_root;
      }
      
      
      // return the correct endpoint, if this is server from an HTTP request       // return the default localhost:8500 for development, if FlexBuilder launches       // the application locally with an absolute path (file://c:\...)       public static function get AMFENDPOINT():String
      {
         var app:Application = Application.application as Application;
         if( app.url != null && app.url.indexOf("http:") != -1 )
         {
            return "http://{server.name}:{server.port}" + ConfigModel.CONTEXT_ROOT +"/messagebroker/amf";
            // for ColdFusion users             // return "http://{server.name}:{server.port}" + ConfigModel.CONTEXT_ROOT +"/flex2gateway";          }
         else
         {
            return "http://localhost:8500" + ConfigModel.CONTEXT_ROOT + "/messagebroker/amf";
            // for ColdFusion Users             // return "http://localhost:8500" + ConfigModel.CONTEXT_ROOT + "/flex2gateway";          }
      }

   }
}

ServiceLocator.as

package services
{
   import model.ConfigModel;
   import mx.messaging.Channel;
   import mx.messaging.ChannelSet;
   import mx.rpc.remoting.mxml.RemoteObject;
   import mx.rpc.events.ResultEvent;
   import mx.messaging.channels.AMFChannel;
   import mx.rpc.events.FaultEvent;
   import mx.rpc.AbstractService;
   import mx.messaging.config.ServerConfig;
   
   /**
    * Create the RemoteObject tags used by the application service delegates
    * @author: Mike Nimer
    **/
   public class ServiceLocator
   {
      public var service:AbstractService;
      public var amfChannelSet:ChannelSet;
      public static var serviceLocator:ServiceLocator;
      
      public function ServiceLocator()
      {
         var amfChannel:Channel = new AMFChannel(ConfigModel.CHANNELID, ConfigModel.AMFENDPOINT);
         amfChannelSet = new ChannelSet();
         amfChannelSet.addChannel(amfChannel);
      }      
      
      public static function getInstance():ServiceLocator
      {
         if( ServiceLocator.serviceLocator == null )
         {
            ServiceLocator.serviceLocator = new ServiceLocator();
         }
         return ServiceLocator.serviceLocator;
      }
      
      
      /**
       * Individual Services used by the Application.
       **/            
      public function getSomeService():AbstractService
      {
         if( service != null )
         {
            return service;
         }         
         service = new RemoteObject('someDestination');
         service.channelSet = this.amfChannelSet;
         (service as RemoteObject).showBusyCursor = true;
         
         // service.source = "dot.path.to.cfc" // If you are using ColdFusion      
         //service.setCredentials(username, password); // if you need it    return service;
      }
      
   }
}

Set Context-root FlashVar (ColdFusion)

// You'll find this in the default html flex generates, just make the html page a cfm and add this FlashVar.
// note: Use contextRoot=<%=request.getContextPath()%> for JSP pages.
   AC_FL_RunContent(
         "src", "Orca",
         "width", "100%",
         "height", "100%",
         "align", "middle",
         "id", "Orca",
         "quality", "high",
         "bgcolor", "#869ca7",
         "name", "Orca",
         "flashvars",'contextRoot=#getContextRoot()#&historyUrl=history.htm%3F&lconid=' + lc_id + '',
         "allowScriptAccess","sameDomain",
         "type", "application/x-shockwave-flash",
         "pluginspage", "http://www.adobe.com/go/getflashplayer"
   );

More Entries

BlogCFC was created by Raymond Camden. This blog is running version 5.9.001.