Frameworks

May 05, 2008

The Smashed Apples Open Source Development Platform

Smashedapples2

The Smashed Apples Development Platform is an open source development platform that aims to help flex developers easily and quickly develop flex applications on cloud services, like Amazon Web Services, Google App Engine, the Google Web Api’s.

Many Clouds, 1 App.

Flex is perfect for leveraging cloud services. It was designed to have multiple sources of data. Your data can be in an xml file, a web service, or come from remoting directly into backend code. You can use Google App Engine to host your database, store your images in Amazon S3 and deploy the messaging through BlazeDS running on an Ec2 instance.

Smashedapples1

Why not all, and more.

 

V 099 Beta

We’re still currently in version 099 beta. But we decided to go ahead and solicit help and feedback from the flex community. We have ideas about what other flex developers might want, but it’ll be better if you just tell us.

More than a swc

Smashed Apples is more than a swc. It’s a development platform. The SmashedApplesSDK is just one piece of a much bigger puzzle. For example on Amazon we created a public Amazon Ec2 ami  ( ami-5640a53f -) that starts up an apache web server that deploys blazeDS and a java project that allows you to access the Amazon SimpleDB from within flex. The swc just ties it all together from within flex. Also, with that image you can open up messaging ports and do push pulls off of Amazon Web Services.

Besides being a swc to leverage cloud services, I’ve also been incorporating enterprise-level dynamic flex computing components that will help you create flex apps faster. Forms that know how to submit themselves. DataQuery objects that allow you to consistently create dynamic queries on backend resources.

Harnessing Cloud Services as Needed

Last August at Flex 360 Seattle I had the simple idea of using flex with Amazon Web Services to build a photo viewer using Amazon S3. The problem was I knew nothing about using Amazon Web Services. I wasn’t a linux administrator and every time I tried to use Amazon Web Services from within flex I just got frustrated. (What’s up with that freaking SSH KeyPair!!) I mentioned it to long time friend Jeremy Mooer and it turns out he knew everything about using linux on amazon web services that I didn’t. That simple idea turned into a full blown open source project. As I started looking into Cloud Services, I found there were alot more out there than I suspected. Jeremy Got busy creating Ec2 ami’s and I went about creating the flex sdk, and the smashed apples java ec2 java api. BlazeDS went Open Source, Google came out with AppEngine and it became very apparent to me that the applications of tomorrow are going to be built off of cloud services. ( Get ready to dump your RDBMS btw ). Businesses are going to create thier own mini cloud services. Relational Database Management Systems are going to give way to Object Persistent Systems. Words like Hadoop, MapReduce, Erlang and Mnesia are going to be found on more and more resumes. Smashed Apples has turned into my goto for being able to harness cloud services from within flex applications. Pay for what you use, right?

 

 

Future Development

We’ve already been looking into ways to incorporate Google App Engine, and more code will be coming soon. 

But in the future, we’d also like to support:

 

Learn More

Site: http://www.smashedapples.com/

Code: http://smashedapples.googlecode.com/

 User Group: http://groups.google.com/group/smashedapples

Simple Explorer: http://www.smashedapples.com/samples/explorer/SmashedExplorerApp.html

It currently runs off of the public smashed apples ami, it use blazeds for remoting, to the smashed apples java api that stores data in SimpleDB.

Help is Welcome

We are an open source project! If you’re a flex developer with some free time and would like to get involved please email me. There’s plenty to do. We’re easy to get along with, like to joke around and doing an open source project is a great way to get your name out there. We give credit where credit is due. 

Corporate Sponsors

Finding corporate sponsors has not been our goal when we created this project. That being said, I have received several inquiries about whether or not we have corporate sponsors for the project and we are open to the idea of having a corporate sponsor(s). If you would like to become a corporate sponsor please contact me.

 

 

 

February 11, 2008

Boo! I'm an Event Manager

For a contextual meaning of the following you’ll probably want to check out this post by Jesse Warden.

While in the course of building flex applications there almost always comes a time when events just don’t line up properly for whatever reason. For example Global Event Listeners that listen for events that reside in modules that may or may not ever get loaded. Renderers that are use in repeater/list/grid controls that may don’t define our events in their metadata. And also, events that are fired from NonVisual Components that may or may not reside in the Display List.

In all these cases, the difficulty resides in the fact that as a developer you may not have / know about the specific instance of the object you want to add your listener to. In most cases this is OK, because as long as the component is a visual component you can still capture that event by adding your listener above it and using capturing/bubbling. The backstop in this scenario is always the SystemManager where you can add listeners to. However, you have to make sure you bubble or useCapture.

In the case of Global Listeners using the SystemManager is fine. But if we’re nested in three or four screens and we want to have specific instance code run and no more, because we may have two or more instances of the same object on the screen at one time, we don’t want the event getting all the way to the SystemManager, ( and we need to remember to stop the event) A better solution would be to confine our event to specific context. A localized SystemManager of sorts. In the case of using a DataGrid custom renderer and dispatching the event we want to listen for the the event in the document that houses the DataGrid. The document object gives an instance level where we can dispatch and listen for events safely. The document object also makes sense from a coder’s point of view. If I create a Panel called MyPanel and stick a button in it that dispatches an event, and then create two or more instances of MyPanel, what we get is objects named like MyPanel0, MyPanel1, MyPanel2, etc.

To get to the basics of how and where we dispatch our events there are only a few things we need to worry about. First, there is always a point up the Application tree where our events can be captured. Thus, the listener is the only one that needs to know about where the rendezvous point is. The object doing the dispatching doesn’t need to care. The way I think about this is:

Listeners, need a rendezvous point from which they can capture the event. Dispatchers must know how to define their target.

To help me remember how to set these two events properly I created an EventManager class that hides the implementation of dispatching these events from me. I also created an AppEvent class from which I can extend my AppEvent classes. An AppEvent might be something like a UserEvent.LOGIN that is global, or might be specific to different sets of code in my app, like a ProjectEvent.PROJECT_ITEM_CHANGE event. All classes in my app can then import my EventManager class to make sure they can dispatch and subscribe to events in the context they need to.

The Signature on my Event Manager class looks like

public static function addEventListener( type:String, listener:Function, rendezvous:EventDispatcher = null, priority:int=0, useWeakReference:Boolean=true ) : void

public static function dispatchEvent(event : AppEvent, target:EventDispatcher = null ) : void

Some noticeable things about these two methods because at first look they look pretty harmless, in fact almost useless, and duplicated. First with my addEventListener, the noticeable thing is the rendezvous object that you can pass in and that defaults to Application.application. This allows you to look up and down the object chain to find the exact point where you want to add your listener. The addEventListener always uses useCapture, and the AppEvent class always bubbles so we don’t need to worry about whether the event will be caught or not. ( This is especially good for team scenarios where there’s always a fat fingered member that fancies himself a proctologist )

Second on the dispatchEvent method you’ll see that a target is allowed to get passed in ( it defaults to Application.application, which means Global) , which creates some interesting side effects and a lot of flexibility. Essentially passing in a target allows me to set the target of the event in scenarios where an event might not originate on the target. This is real handy when dispatching events that are defined off data as in ValueObjects, a good example might be when I want to dispatch that UserEvent.LOGIN event and I want my target to be a UserVO object. The actual login event might originate when the data arrives from the server with our user info. I can then propagate the UserVO throughout my system and anybody who cares can do something. Our UserVO might contain permissions and we might need to change our layout, or it might contain user preferences, etc.. 

The ability to set the target of an event is also a handy technique when using NonVisual components.  I pointed out in this article how to create a non visual component that is implemented in mxml. Jesse pointed out in his article that he’s changing his mind about using IMXMLObject, which is a fair argument, but when you think about events as Listener : Rendezvous, Event : Target and then realize you can switch out the rendezvous and target, it doesn’t take Tom Sawyer to paint the white fence white. Using our IMXMLObject and the dispatch event technique that I described above gives us the perfect vehicle to dispatch our events. IMXMLObject interface defines the following method

public function initialized(document:Object, id:String):void

We can then use the document object to dispatch our event into the proper context of where we want to dispatch it. Like I mentioned above, the document object comes in instances of objects we defined. From my previous MyPanel example, a non visual component that is implemented in mxml would get a document named something like MyPanel0 or MyPanel1. As long as we have an instance of MyPanel we can add our listeners to it.

In most cases, I just use the EventManager class to dispatch to the proper context. Rarely do I actually listen through it, but it’s there and can be handy.

I’d like to point out that this is by no means a substitute for the built in event lifecycle. It’s important to use this technique only when is necessary. And be very afraid of global events. Like most things global, Global Variables, Global Constants, Global Singletons, Global Warming, they can be very bad, if you don’t believe me, just ask him.

I’ve included a sample application demonstrating some of these techniques with links below. There’s also some more of my value object techniques I’ve been demonstrating, like setting a value object by passing in a form or xml and some other techniques that make app building simple, but I won’t get into detail on them unless someone asks or I run into one of these.

Here’s the demo:  I left traces everywhere so you can download the app and run it.

demo

source

 

 

September 25, 2007

The need for smarter flex controls.

If you saw some of the junk I have to deal with in our database you’d probably laugh, and if you didn’t it’d because you’re in the same boat as me. I constantly have to deal relational mapping or database compatiblity issues. It seems over the years, whether out of need or some sort of creative insight I apparently lack, my database forefathers have come up with the following list of things that represent a boolean.

True : 1,”A”,”YES”,”Y”,”Active”

False: 0,”I”,”No”,”N”,”Inactive”

Now, of course all those strings are not case sensitive, and are stored as such things as “Active” and “active” depending on which way the wind was blowing when the developer wrote it those many years ago. Almost always I display a boolean value as a checkbox. And so I’d like my checkbox to take all of those values, display it as either checked or unchecked and then spit out a corresponding value when I submit a form. So, if the value went in as “Y” and the user unchecked the box, I should get a “N” when I inspect the value.

 

1. I extended CheckBox

2. Created a variable called values that will house the two options that get returned  

3. Because I want to pass in something other than a boolean, I can’t override the public selected setter found in the mx.controls.checkbox. ( overloaded methods would be nice ). Instead I created a setter called checked that takes type Object, does a switch on the value and sets whether it’s selected or not and also the values array.

4. Finally I create a getter called value from which i can read the correct type. It reads from the values array, where the first index is returned on true else the second index is returned.

 

Overall, the code is fairly simple and extensible. The only reason I’m blogging about this is because I’d like this kind of functionality out of the box from the flex framework. We do alot of bait n’ switch with data. We support a huge legacy Oracle database and we don’t have much of a choice. Flex is all about the ui, should that include making it easier on the developer to create the ui.

 

I’d love to see how other people are handling these types of situations. Just as a note, before this I was running my values through a function.

 

 

// default to use 1,0

public var values : Array = [1,0];

public function set checked(value:Object):void

{

switch(value)

{

case "Y":

case "N":

this.values = ["Y","N"];

this.selected = (value == "Y") ? this.selected = true : this.selected = false;

break;

case "A":

case "I":

this.values = ["A","I"];

this.selected = (value == "A") ? this.selected = true : this.selected = false;

break;

case "Yes":

case "No":

this.values = ["Y","N"];

this.selected = (value == "Yes") ? this.selected = true : this.selected = false;

break;

case "Active":

case "InActive":

this.values = ["Active","InActive"];

this.selected = (value == "Active") ? this.selected = true : this.selected = false;

break;

case "true":

case "false":

this.values = ["true","false"];

this.selected = (value == "true") ? this.selected = true : this.selected = false;

break;

default:

this.values = [1,0];

this.selected = (value == "1") ? this.selected = true : this.selected = false;

break

}

}

public function get value():*

{

if( this.selected == true)

return values[0];

return values[1];

}