« April 2006 | Main | June 2006 »

May 31, 2006

Architecting a Flex App

Web developers who take Flex for a spin may initially be confused by the user interface model.  Although a typical, servlet-style, request-response model will work in Flex, There Is A Better Way.  Thanks to the "[Binding]" tag in the Actionscript language, you can bind your view to your model data so that changes to the model are automatically reflected in the view.  The Cairngorm microarchitecture formalizes this approach, and is a great starting point for developers who want to figure out how to "make it all work together".  In this post I'll describe how variable binding, feature-driven development, and Cairngorm all work together for NoteTag.

Here's how a typical, non-trivial Flex app might be architected:

Domain

  • The classes that make up the domain model.  In NoteTag, this includes Notes, Tasks, and Subscriptions.  (A Subscription is a collection of related Notes or Tasks.)

Model

  • A Singleton that holds bindable instances of the domain model.  In NoteTag, the ModelLocator Singleton holds the user's list of Subscriptions, the user's Connections, the current Subscription, the current Note, etc.

View

  • The UI components (generally, though not always, MXML files).  The UI components that are state-dependent are bound to instance variables in the ModelLocator.  Any changes to data in the ModelLocator will cause the UI to automatically update, provided that that data is marked as "[Bindable]".  An example in NoteTag is the NoteListView, which presents the list of Notes in the current Subscription.  If the current Subscription or any of its Notes change then the NoteListView will automatically update to reflect the changes.

Controller

  • Infrastructure for implementing features as event-driven Commands.  Examples in NoteTag include GetSubscriptionCommand, GetNoteCommand, etc.

Business

  • Business logic classes perform operations on Domain objects, often making calls to remote services and returning the results asynchronously.  The SubscriptionManager class is the entry point for most of NoteTag's business logic.

Service

  • The services layer, which holds all classes that are used to make remote service (HTTPService, RemoteService, and WebService) calls.  NoteTag uses a set of service factory classes, which decouple the configuration of specific HTTP services from the components that make calls to HTTP services.

Most application features touch on some or all of these components.  Here's the workflow for a typical feature:

  1. The View broadcasts an event.
  2. The singleton Controller receives the event, maps it to its corresponding Command, and executes the Command.
  3. The Command delegates to the appropriate Business object to perform the business logic.
  4. The Business object performs the business logic, possibly making one or more asynchronous calls to various Services, and returns the result by dispatching a new event to the Command.
  5. The Command assigns the result to the singleton Model.
  6. Any Views that are bound to the data in the singleton Model are automatically updated.

So how would this work for a specific feature?  When the user selects a Note from the list of Notes (at the top of the screen, below), the Note is loaded from the appropriate repository (Blogger or TypePad) and displayed in the editor (at the bottom of the screen, below):

 

1. Broadcasting the Event

When the user clicks on the first Note in the list, NoteListView dispatches an event, as follows:

// NoteListView.mxml
private function getSelectedEntry(event:ListEvent) : void
{
  var selectedEntry:TagBasedEntry =
    TagBasedEntry(currentFeed.entries[event.rowIndex-1]);

  Application.application.dispatchEvent(
    new GetNoteEvent(selectedEntry.metadata,true));
}

2. Responding to the Event

Because NoteTag's Front Controller has registered itself to listen for all Command Events, it will be notified when GetNoteEvent is dispatched:
// NoteTagController.as
public class NoteTagController extends FrontController
{
  public function NoteTagController()
  {
    addCommand(LoginEvent.EVENT_LOGIN, LoginCommand);
    addCommand(GetNoteEvent.EVENT_GET_NOTE, GetNoteCommand);
    addCommand(GetTaskEvent.EVENT_GET_TASK, GetTaskCommand);
    addCommand(PostNoteEvent.EVENT_POST_NOTE, PostNoteCommand);
    // more commands...
  }
}

Cairngorm's FrontController provides the infrastructure for listening for events and responding to them by executing the appropriate command.

3. Executing the Command

To retrieve the Note, NoteTag needs to make a call to the blog server that stores the user's notes.  The GetNoteCommand, which implements Cairngorm's Command interface, takes care of this:

// GetNoteCommand.as
internal class GetNoteCommand extends ChainedCommand
{
  public override function execute(event:CairngormEvent):void
  {
    var initialEvent:GetNoteEvent = GetNoteEvent(event);

    var subscriptionManager:SubscriptionManager =
      ModelLocator.getInstance().subscriptionManager;

    setNextEventHandler(subscriptionManager,
      handleLoadNote,
      LoadNoteEvent.EVENT_LOAD_NOTE,
      onSubscriptionFault,
      SubscriptionFaultEvent.EVENT_SUBSCRIPTION_FAULT);

    subscriptionManager.loadNote(initialEvent.metadata);
  }

  private function handleLoadNote(event:LoadNoteEvent):void
  {
    // handle result here...
  }

  // ...
}

(You may have noticed that GetNoteCommand extends ChainedCommand -- this class chains asynchronous calls together using the setNextEventHandler method.  In a future post, I'll go into greater detail on ChainedCommand, and asynchronous responders in general.)

4. Performing the Business Logic

The SubscriptionManager handles the loading of the Note by executing a series of HTTP service calls to the tag server and the blog server.  When the note has been loaded, the SubscriptionManager will dispatch a LoadNoteEvent, which will be handled by GetNoteCommand.handleLoadNote (see the next item).

5. Updating the Model

GetNoteCommand responds to the event by assigning the loaded Note to the appropriate data member on the ModelLocator:

// GetNoteCommand.as
internal class GetNoteCommand extends ChainedCommand
{
  // ...


  private function handleLoadNote(event:LoadNoteEvent):void
  {
    ModelLocator.getInstance().currentNote = event.note;
  }

  // ...
}

6. Updating the View

Any views that are bound to the ModelLocator's currentNote member will automatically update themselves to reflect the new data.  NoteView, the component that's responsible for displaying the Note in an editor, is one such view:

// NoteView.mxml
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml"
    xmlns:view="com.adobe.kiwi.notetag.view.*"
    xmlns="*">
  <mx:Script>
  <![CDATA[
    import com.adobe.kiwi.notetag.model.*;
    [Bindable] private var model:ModelLocator = ModelLocator.getInstance();
  ]]>
  </mx:Script>

  <view:NoteEdit id="noteEditor" width="100%" height="100%"
    note="{model.currentNote}" />


</mx:VBox>

 

Every other feature -- publishing a Note, fetching a Subscription, updating a Task -- is implemented with the same Event-to-Command-to-Model-to-View approach.  Command-specific Events can be dispatched from multiple contexts, without knowing which Views will be affected.  Views can bind to Model changes without knowing where the originating Event was dispatched from.  Loose coupling leads to cleaner, more maintainable code.

May 30, 2006

NoteTag Installation: Tips From the Field

Here are some "tips from the field" to help with the NoteTag installation process. If you have any problems (or suggestions!), add them to the comments for this thread.

1) There are a few references to "C:\Dev\workspace" in the installation guide. This is the suggested workspace folder location, but feel free to use any path.

2) With regard to the SSL keystore file, be sure that the name you use with keytool.exe is the same as the element in jrun.xml. For example, if the command to generate the keystore file is:

keytool -genkey -alias localhost -validity 9999 -keyalg RSA -keystore c:\notetag.keystore -keypass mypass -storepass mypass

then the SSL service in jrun.xml should look like this:

<service class="jrun.servlet.http.SSLService" name="SSLService">
    <attribute name="port">9100</attribute>
    <attribute name="keyStore">{jrun.rootdir}/lib/notetag.keystore</attribute>
    <attribute name="keyStorePassword">mypass</attribute>
    <attribute name="trustStore">{jrun.rootdir}/lib/trustStore</attribute>
    <attribute name="socketFactoryName">jrun.servlet.http.JRunSSLServerSocketFactory</attribute>
    <attribute name="deactivated">false</attribute>
    <attribute name="bindAddress">*</attribute>
    <attribute name="interface">*</attribute>
    <attribute name="clientAuth">false</attribute>
</service>

May 27, 2006

AS3 programming 101 for C/C++ coders

In my previous article, I covered ActionScript 3 languange syntax and constructs that may be of interest to C/C++ coders starting out on ActionScript 3. This article covers areas of AS3 that are different from C/C++ in regards to functional issues that may be interesting to people with C/C++ experience. ActionScript 3 is a powerful language with some very nice features. However, as a long time C/C++ coder I found ActionScript lacking things I was used to having.

 

No control over application message loop

In a standard C/C++ application, your application has full control of the message loop. In Flash/ActionScript, this is not the case. The main application message loop is controlled by the application that is hosting the Flash player. This is either the browser, the stand alone flash player, or some other custom application. Flash is purely event driven. Your Flash application receives callbacks for every type of notification. This includes things like user events, application commands, and network responses. This means that ActionScript cannot block for any reason. If your Flash application blocks in a loop (or just just taking a long time computing something), the entire player and perhaps even the host application will block as well. Flash must handle everything via asynchronous callbacks.

In a typical desktop application written in C/C++, modal dialogs manage the message loop. This allows a modal dialog function to block and then return when the user is finished without causing the entire application to freeze. This is not the case in ActionScript. In ActionScript, you must display the modal dialog then return and wait for a callback that indicates what the user chose. This also means that using "alert" dialogs in ActionScript for debugging purposes is not entirely useful since the alert will display and the application will continue running.

Sho Kuwamoto from the Flex Builder team has a running series of articles covering the issues of "Dealing with asynchronous events". So far, he has Part 1, Part 2, and Part 3 available. I strongly recommend reading these articles. They provide a lot of good information for dealing with asynchronous nature of AS3.

 

No threads

In Flash/Flex, your application executes in a single thread. If you are used to using threads in your applications, this can feel somewhat constraining. However, since all AS3 applications are event driven and must handle everything asynchronously, AS3 has some nice language features that allows you to make asynchronous calls. Granted, asynchronous function calls are no where near a replacement for true threading, but asynchronous calls can provide for a similar user experience if you architect your application with this design pattern in mind.

The Timer class is very useful in this area. The Timer class allows you to schedule a function to be called by the framework at a later time on fixed intervals via "timer" event notifications. You can think of these timer events as time slices in which your asynchronous logic can execute. Since all Flash applications run in a single thread, you never need to worry about locking, mutexes, or semaphores, but you do need to be careful that any asynchronous function call does not take too long or the application will appear to hang or freeze.

 

No enum

AS3 has no enum. This can make porting C/C++ code to ActionScript a little more work. The lack of an enum may also disrupt how someone versed in C/C++ would approach a problem. Some people have come up with dynamic runtime solutions. For example, Darron Schall's EnumeratedType class provides a single class that allows you to declare a new "enum" where ever needed. This is a nice, simple design that solves the runtime issues related to enums. It however does not catch errors at compile time (mismatched assignments or comparisons, etc.), because the AS3 language only has primative types for us to use which can accept any assignment.

Another approach could be as simple as defining a class with statics:

public class MyEnum
{
	static public const FIRST:MyEnum = new MyEnum();
	static public const SECOND:MyEnum = new MyEnum();
	static public const THIRD:MyEnum = new MyEnum();

}

This class then could be used similar to enum definitions when assigning or comparing variables as such:

public function getValue() : MyEnum

{
    return MyEnum.SECOND;
}

This way requires you to create a new file/class for each enum, but it enforces type safety because you are passing the data around as a custom type.

 

Public class constructors and singleton objects

In AS3, all class constructors must be public. This limitation is mainly due to the fact that ECMAscript 4 is not final and AS3 has chosen to abstain from protected/private constructors until it is resolved. But this limitation means is that AS3 does not have a straight forward way of implementing singleton classes. If the constructor must be public, anyone can create an instance of your class. However, there is a little trick you can use to implement a singleton class in AS3 that will ensure that is one and only one instance of your class.

In my previous AS3/C++ article, the section "Only one packaged class per file" touched on an interesting nuance of AS3 that allows you to declare a class outside the package declaration. This class is only accessable to code within that file. We can use this to create an implementation of a singleton class. The following code represents the contents of a file named "Singleton.as":

package my.package
{
    public class Singleton
    {
         public function Singleton(blocker:SingletonBlocker)
         {
             if (blocker == null)
                 throw new Error("Public construction not allowed.  Use getInstance()");
         }
		 
         public static function getInstance() : Singleton
         {
             return instance;
         }
		 
         private var instance:Singleton = new Singleton(new SingletonBlocker());
    }
}

// Outside the package, declare the blocker class
class SingletonBlocker
{
}

Since the "SingletonBlocker" class is outside the package declaration, other classes do not have access to it. The public constructor of the Singleton class requires the "blocker" parameter, otherwise it throws an exception. The combination of these two controls prevents any code from outside this file from ever constructing a new "Singleton" object instance. The only way to obtain a valid instance is to call the static function "getInstance()".

 

May 26, 2006

Dissecting a Mashup: NoteTag's Reusable Flex Components

Whenever I come across a new Flex 2.0 project, my first two questions are:

  • "How do I try it out?"
  • "Can I see the source?"

(Short answers: "Go to the NoteTag Labs page!" and "Yes, go to the NoteTag Labs page!")  After that, my next question is usually:

  • Is there anything here I can reuse?

In NoteTag's case, the answer is a resounding "Yes!"  Interested in publishing to a blog server that supports the Atom Publishing Protocol?  Take a look at our AtomProtocol library.  Interested in working with a read/write Feed object model that supports the various flavors of RSS and Atom?  Try the Feeds library.  In this post I'll give a brief overview of each reusable library that's included with NoteTag.

Below is a rough diagram of the NoteTag architecture.  In future posts I'll talk about the NoteTag specific components, but today I'll focus on the lower part of the diagram.


notetag arch.jpg

 

From bottom to top:

corelib

The corelib library is an ActionScript 3.0 library developed by the Adobe Developer Relations team, and made available on the Adobe Labs site.  The Kiwi team didn't develop this library, but we use it heavily (for URI support, date parsing,and WSSE authentication), and I expect that most Flex developers will want to add it to their arsenal of tools.

Connections

The Connections library provides basic support for connection management. Read/write web applications typically make calls to multiple web services, often authenticating with different credentials for each service -- NoteTag is a good example of this, using del.icio.us to store metadata relating to notes and tasks, and Blogger or TypePad to store the note content.  The Connections library provides an object model for user-specific Connections to an Endpoint (e.g. Blogger) that supports a specific Protocol (e.g. the Atom Publishing Protocol).

Feeds

The Feeds library provides a format-independent Feed object model for Atom 0.3, Atom 1.0, RSS 1.0, and RSS 2.0.  The Feeds library is similar in spirit to the existing RSS and Atom libraries, but provides a few key additions:

  • support for Atom 0.3 (required by Blogger and TypePad)
  • support for reading from and writing to Feed objects
  • support for feed extensions

Let's take a look at the second bullet point.  Here's how you might create a new Atom 1.0 entry from scratch:

// Create an empty entry.

var factory:IFeedElementFactory = new Atom10FeedFactory();

var entry:IEntry = factory.createEntry();

 

// Assign a title to the entry.

var title:IContent = factory.createTitle();

title.value = "My Latest Entry"; // assign the content to the title

entry.title = title; // assign the title to the entry

 

// Assign an id to the entry.

entry.id = "id:1234567890";

 

// The entry is being published "right now".

entry.published = new Date();

 

// Display the XML for the entry.

trace(entry.xml);

What's nice about this approach is that you only have to change one of line of code if you're working with a different feed format:

var factory:IFeedElementFactory = new RSS20FeedFactory(); // switch to RSS2.0!

TagServerProtocol

The TagServerProtocol library provides a generic interface for a tag server protocol, and one specific implementation: del.icio.us.  There are a variety of tag servers (more commonly referred to as social bookmarking services) out in the wild, most of which provide different flavors of the same API.  The ITagServerProtocol interface is a "least-common denominator" interface that should work for most of these services.  We'd love to see someone try to implement it for Simpy or Shadows and then plug it in to NoteTag...

AtomProtocol

The AtomProtocol library provides a generic interface for the Atom Publishing Protocol, and two specific implementations: Blogger and TypePad.  The protocol interface  and introspection document object model conform as closely as possible to the current draft (08) of the APP specification, though there are some features (such as collection paging and media collections) which we punted on.  Still, it ought to be possible to create a plugin for Google's GData

May 25, 2006

AS3 language 101 for C/C++ coders

This article covers aspects of ActionScript 3 that would be helpful to C/C++ application engineers transitioning to application development in Flex and Flash.

I've used C/C++ through most of my educational and professional career. I've also done a respectable share of Javascript and Perl. ActionScript 3 could be viewed as an interesting blend of features from all of these languages. Actionscript 3 conforms to the ECMAscript 4 spec. So, it is a standard languange. In addition to the standard language syntax, AS3 contains a custom class framework for working with Flex/Flash.

The following are areas in the AS3 language that I personally found interesting.


Type declarations

Compared to C/C++, the first syntax oddity that you'll notice is how AS3 declares it's variable types. All type declarations are in post-fix notation. For example, in C you would define a function like:

int myFunction(char *str);

In AS3 this same function declaration looks like:

function myFunction(str:String) : int

 

Typecasting

In AS3, think of typecasting like calling the constructor of the type. Functionally, this isn't what happens, but the syntax is what it appears to be doing.

In C:int i = (int)somefloat;
In AS3:   var i:int = int(somefloat);

If you see what appears to be something calling the constructor of a class or type but it does not use "new", it's not calling a constructor. It's performing a typecast. For example:

var foo:SomeClass = SomeClass(someObject);
var bar:SomeClass = new SomeClass(someObject);

The first line is typecasting "someObject" into SomeClass. The second line is creating a new SomeClass object, passing "someObject" as a parameter to the constructor. This subtle difference can have wide ranging effects (new object vs. reusing an existing object, etc.).  Depending on what the class constructor takes as a parameter, it is possible that both the typecast and the constructor would compile with no errors/warnings in all situations.  So, be careful.  The difference between a typecast and a new object is just the "new" keyword.

 

Variable scope

Variables are scoped to the function. ActionScript employs a system called "variable hoisting", which implicitly pulls all variable declarations in the function (even ones in nested blocks) to the top of the function at compile time.  For example:

public function doSomething() : void
{
    var foo:int = 4;
    
    if (foo)
    {
        var bar:int = 2;
    }
}

With viable hoisting, all declared variables in a function are moved to the top of the function block at compile time. In the above example, the compile time result looks like:

public function doSomething() : void
{
    var foo:int;
    var bar:int;

    foo = 4;
    
    if (foo)
    {
        bar = 2;
    }
}

Note that the "bar" variable is now in scope for the entire function.  This subtle variable handling in AS3 may lead to unintended situations since any use of the "bar" variable before the "if(foo)" block is now valid, even though it is not declared until inside the if() block.  AS3 will complain if you declare the same variable more than once in the same function, but it won't complain if you use a variable before it's declared.


void *

In AS3, you can use the wild card type to mimic the "void *" type.  For example, say you have a factory object that can return objects of many types.  This can be implemented as such:

public function wildcard() : void
{
    var anything:* = ObjectFactory.getData();
}


Run time type checking

Since you can pass things around as anything using the wildcard type (void *), you need a way to check the type of the object at runtime. To do this, you can use the "is" directive:

public function doSomething() : void
{
    var something:* = getData();

    if (something is String)
    {
        // handle string logic
    }
    else
    {
       // do something else
    }
}

This allows for runtime type checking which allows your application to perform different logic depending on what the given object is.


No function overloading

There is no function overloading in AS3. However, you can implement a system that mimics function overloading. For example, in C++ you might have some function definitions like:

int doSomething(int i);
int doSomething(char *str);

In AS3, you can't overload a function, but the language allows you to make use of the type wildcard "*" and use the "is" directive as a way of performing runtime checks and branching based on what was passed in. For example:

function doSomething(obj:*) : int
{
    if (obj is int)
        // do int stuff
    else if (obj is String)
        // do string stuff
    else
        // what type did you give me?
}


No operator overloading

AS3 has no way to override the meaning of "+", "=", or any other operator. The closest functionality is the get/set member accessors that you can declare to handle the getting and assignment of class members.


Everything is an object

All types within AS3 are derived classes of the base class "Object". Even if a class does not "extend Object", it still does. This means when you pass anything to a function, you are passing that data by reference (pointer) in all cases. If the called function modifies the object you passed, your version of the data will be modified as well.

However, there are some exceptions. Basic types like int, Number, and String are objects as well, but their implementation performs reference counting to make them behave like stack objects. If the called function simply assigns new values to variables of these basic types, the data in the caller function does not get modified.


Only one packaged class per file

When implementing AS3 classes, you can only have one class definition per package declaration per AS file. For example:

MyClass.as

package my.class.package
{
    public class MyClass
    {
        public function MyClass()
        {
             ...
        }
    }
}

Fig. 1

MyClass.as

package my.class.package
{
    public class MyClass
    {
        public function MyClass()
        {
             ...
        }
    }
}

class MyPrivateClass
{
    public function MyPrivateClass()
    {
         ...
    }
}

Fig. 2

MyClass.as

package my.class.package
{
    public class MyClass
    {
        public function MyClass()
        {
             ...
        }
    }

    public class AnotherClass
    {
        public function AnotherClass
        {
              ...
        }
    }
}

Fig. 3

Fig. 1 and 2 are valid in AS3. Fig. 3 is not valid. AS3 does not allow you to have more than one class inside a package declaration and you can only have one package declaration per file. The interesting thing to note is that the "PrivateClass" in Fig. 2 is only accessable to code inside that file. Outside that file, the "PrivateClass" is an unknown type. You can use the construct in Fig. 2 to hide implementation classes from the rest of the world.

Being limited to one public class per file may not be a huge problem, but it may come as a logistical hurdle if you are expecting to define multiple classes within the same file. Plan your file structure accordingly.


virtual functions

The major difference between AS3 and C++ when it comes to inherited functions is the fact that the functions in a derived class do not override the base class functions unless you declare a method as "override". Without this declaration, the base class version of the function will be called in all cases.

You can think of this as almost the opposite of C++'s "virtual" declaration. In C++, once a function is declared virtual, that function is automatically virtual for all derived classes regardless if the derived class declares it as virtual. In AS3, the derived class controls what functions are "virtual" (overridden).


dynamic_cast

In AS3, you will find yourself dealing with interfaces. These are similar in concept to abstract base classes in C++. Objects that implement an interface will be passed around as instances of that interface. So, given an object of a specific interface, how do you get the object as an instance of its subclass? You use the "as" functionality. For example:

var someInterface:ISomeInterface = factory.getSomeInterface();
var someClass:SomeClass = (someInterface as SomeClass);

If "someInterface" is actually an instance of "SomeClass" or a derived class of "SomeClass", the variable "someClass" will be a reference to that object.  If "someInterface" is an instance of some other class, the "someClass" variable will be null.


Raw character strings

AS3 has a primative string type named "String". You can access the characters of the string and do things with them, but what if you want access to the raw ASCII or UTF8 bytes? The easiest way to do this is via the ByteArray() class. You can write a string into a ByteArray object and then pull it back out as raw bytes.

 

Well, I hope this is useful to anyone making the transition to Flex/ActionScript from C/C++. If you have any questions, found an error in my assessment, or just want to say something, please leave a comment. We're trying to make Flex development as easy as possible for everyone and any feedback is much appreciated.

Thanks!

An Overview of NoteTag

The Kiwi team is focused on enabling developers to build read/write web components in Flex and Apollo. NoteTag is a proof-of-concept Flex 2.0 application which offers a solution to a common problem: how to keep track of tasks while taking notes for a meeting.

Let's jump straight into the user experience. I'm in a meeting with my Kiwi cohorts, and I'm in charge of note-taking duties. I launch my browser, navigate to the NoteTag URL, and immediately start taking notes.

After the usual status round-robin, Darrick points out that there's a bug which he needs to investigate further. Aha! We have our first task! I highlight the text of the task ("Need to locate RichTextEditor source") and click the "Tag as Task" button on the control bar. The task's text now changes to red, and the property inspector at the bottom of the screen is pre-populated with values. I set the owner to "darrick" and continue taking notes.

When the meeting ends I click "Publish", and the note and tasks are posted to our backend. (More on that later.) If I want, I can browse through the previously-posted meeting notes in an RSS aggregator-like view...

.. but most likely, I'm done. Darrick, on the other hand, has some work to do. He connects to NoteTag and clicks on "My Tasks" to see his aggregated list of tasks. If the text of the task alone doesn't provide the context he needs, he can click on the task to see the enclosing note.

After Darrick has finished his investigation, he needs to mark the task as completed. He checks the box next to the Task, and the task instantly turns from red to green in the note.

This is more than just a local change: anyone who views either the note or Darrick's list of tasks will see that the task has been finished.

At this point you might be thinking, "I've seen plenty of applications that help people keep track of tasks. What's unique about NoteTag?" Two things...

First, NoteTag is a completely free, completely open-source Flex 2.0 application. Want to figure out how we're aggregating tasks? Just dive in to the source code. Want to see how we're publishing notes to the web? It's all there. Want to use our source code in your application? Help yourself! NoteTag should be a great resource for developers who are ramping up on Flex, and who want to understand how to build an app that involves more than a handful of classes.

The other unique thing about NoteTag is the backend: there is none! (Well, none that we wrote, at least.) Here's where the notes are stored:

Blogger! (NoteTag also supports TypePad, and theoretically could use any service that supports the Atom Publishing Protocol.)

And here's where we store references to the notes and tasks:

Delicious! Every note and task is tagged with information about the author, owner, status, etc., and points to the URL of the note on the blog server.

What this means is that NoteTag doesn't replace existing workflows and services, it complements them. You can view your tasks in NoteTag, or you can log into your delicious account and use delicious's support for filters, related tags, and tag clouds to view them in new and interesting ways.

All that being said -- we on the Kiwi project think NoteTag will be less interesting as an end-user product and more interesting as an application that developers can use to learn how to build their own read/write web applications in Flex. In the next post, I'll talk about the overall design and architecture of NoteTag, as well as the reusable components that we've developed.

May 24, 2006

Introductions

File under: ,,,,,,,

Hello everyone, and welcome to the Kiwi Project blog. As our tag line says, the Kiwi Project is focused on creating read/write web components for Flex. What does this mean? 

Over the last year or so the Web 2.0 meme has grown phenomenally.  While the definition of Web 2.0 has been hotly debated, people are starting to focus on a fundamental attribute…

Hal Stern: The Morning Snowman : Weblog

Everything that Tim O'Reilly posits as Web 2.0 examples is distinguished from a Web 1.0 counterpoint as being writeable. Three words: read-write web.

We couldn't agree more.  In fact, from (the "new") Adobe's perspective, we've been promoting the read/write web for years thru our Contribute product, which is both an HTML browser and a WYSIWYG HTML editor all in one application.

With the rising interest in AJAX and RIAs, it became important for us to understand how to empower our Flex environment to create read/write web applications. This means developing Flex components that understand specific Web 2.0 technologies such as RSS, blogging, tagging, and microformats. And with hints of Apollo emerging, this means understanding how to build Flex components that work both in the browser and on the desktop.

Thus the Kiwi Project was born.  The team is comprised of engineers who have been involved with the development of both Dreamweaver and Contribute, who are intimitely familiar with the challenges of read/write web applications.   The team also has experience in both desktop and web development, but like many of us at this time, is new to Flex development.  This blog will chronicle our experiences in mastering Flex and our progress in exploring and developing that set of read/write web components for Flex developers.

Our first proof-of-concept release is just around the corner…