Chapter 7. Cairngorm in Action: SocialStalkr (Twitter + Yahoo! Maps)

In this chapter, you’ll learn how to build larger Flex applications using a framework called Cairngorm. This is a topic that can only be learned by experience, and it’s best done iteratively. Doing so properly, though, would consume over a hundred pages: in early versions of this book I built this example iteratively over five chapters, explaining Flex as I went. But this approach didn’t fit with the format of the “Hello” series, so I rewrote the book and added the stand-alone examples instead. So, since this chapter covers what used to be explained in five chapters, it will be very code heavy. Instead of building it iteratively, I’m going to show the screenshots of the app, explain the design choices, and then present the end result—explaining the code as I go.

This chapter covers the following topics:

  • Using Cairngorm to structure Flex applications
  • Separating a Flex application into multiple components
  • Using HTTPService to talk to RESTful web services,[1] specifically the Twitter API

    1 REST (Representational State Transfer) is a way of building web services that focuses on simplicity and an architecture style that is “of the web.” This can be described as a resource-oriented architecture (ROA); see RESTful Web Services (O’Reilly 2007) for details. As you can probably infer from its $20-word full title, REST grew out of a PhD thesis—Roy Fielding’s, to be precise. However, unlike most PhD theses, it has grown into something revolutionary.

  • Using the Yahoo! Maps API

As you can see, it’s an ambitious chapter. By the end of it you’ll have a much better handle on how to build real-world Flex applications, not just apps that are the size of the toy examples we’ve been building so far in this book.

So, let’s get started.

Creating the SocialStalkr project

The application we are going to build in this chapter is called SocialStalkr: a mashup of Yahoo! Maps and Twitter that lets you “stalk” your friends who use specially formatted Twitter “tweets” on a Yahoo! map. At the end of this chapter, the app will have the following screenshots:

First, when the app starts, a login screen appears. You’ll log in with your Twitter credentials, and then see the main app. The left side of the app shows a Yahoo! map; in the right side the “You” view shows your tweets (and lets you post new tweets). Also, in the right side, you can switch from the “You” view to the “Following” view, which shows your friends, who you can select to view their tweets. As shown in the figure showing the Following view, the itemRenderer grows larger and shows for the selected friend the web-standard “followed link” purple color, and for the friend you’re mousing over the web-standard “click this link” blue link color.

So we’re building a Twitter client. But why is there a map anyway, and what does this app have to do with “stalking” your friends? And why would your friends want you to do this?

Well, for example, regular users of Twitter often use @replies to people and #hashtags. Sometimes, people also say that they’re going to #somewhere to do something, for example “off to #ChillWinston for a pint.” So, if we took this one step further and got people to adopt some conventions (which, if we were being pretentious, we could call a “microformat”), they could use Twitter and SocialStalkr to become a location-aware and time-sensitive spontaneous event planner.

For example, the following screen shows me tweeting that I just spent some time at WorkSpace in Vancouver working on this chapter of the book. Say Scott Patten, my partner in Ruboss, saw that tweet—if he was downtown he could come visit me and we could go for a pint. Or, if you were a friend who didn’t know where WorkSpace was, my tweet would be showing right there on top of its location on the map, as shown in the figure.

Finally, a cynical reason: microblogging services such as Twitter are an exercise in narcissism as much as an attempt at real communication, so what better Twitter client than one that sticks your own avatar all over a map?

Yeah, it’s a bit contrived. But it will be fun to build—and there are many location-based social network startups that are doing a similar thing (but with automatic location detection based on your smartphone). So, you can imagine taking this app further and making it useful. Furthermore, since I’m not using any server-side technology in this book (this isn’t a book about Java, Ruby on Rails, or ColdFusion after all), I’m basically limited to mashups of existing web services for examples.

So, now that we have the requirements and visual design out of the way, let’s create the project. In Flash Builder 4, choose File > New > Flex Project to trigger the New Flex Project dialog. Enter the name SocialStalkr for the project in the Project Name field and click Finish.


Tip

If you name a project in the same case as what you want your main application to be—that is, SocialStalkr instead of socialstalkr—you can skip the rest of the New Project dialog and you won’t need to rename the application. It’s good practice to CamelCase your application name: since it’s a class like any other class in your app, it would be confusing to be called socialstalkr since it would look like a variable and not a class.


With this accomplished, let’s get started with Twitter and Yahoo! Maps.

Getting started with Twitter

If you don’t already have a Twitter account, you need to go to www.twitter.com and create one. This way, you can enter specially formatted tweets that will show up on the Yahoo! map we’ll be integrating later in this chapter. When you sign up with Twitter, you’ll get a unique login ID and a unique screen name; for example, my screen name is peterarmstrong so on Twitter I’m http://twitter.com/peterarmstrong.


Web services can be unreliable

Before we continue, a cautionary note: at any time during the process of following along with this book, your application may stop working for no apparent reason. This is always a danger when working with web services, but with Twitter it has historically been, shall we say, more of a danger than normal. If this happens, try running the app in the debugger. If you see something like the following, chances are it’s Twitter’s fault:

[RPC Fault faultString="HTTP request error" faultCode="Server.Er-
ror.Request" faultDetail="Error: [IOErrorEvent type="ioError" bub-
bles=false cancelable=false eventPhase=2 text="Error #2032: Stream
Error. URL: http://twitter.com/statuses/friends/peterarmstrong.xml"].
URL: http://twitter.com/statuses/friends/peterarmstrong.xml"]

If you see this, try checking your friends’ statuses by going to http://twitter.com/statuses/friends/YOUR_SCREEN_NAME.xml (for example, I go to http://twitter.com/statuses/friends/peterarmstrong.xml). If you can see your friends’ statuses via XML, then Twitter is fine and you should try your app again. However, if you see the image of the now infamous Twitter “Fail Whale,”[a] you should just go grab a coffee and come back and try again. (Twitter’s reliability has gotten a lot better in 2009 than it was in 2008, so this hopefully shouldn’t be a problem. However, the scaling problems they had in 2008 were the comedy gift that kept on giving: my favorite mean-spirited TechCrunch headline of all time was “Twitter Suffers Minor Period of Uptime.”[b])

ahttp://en.wikipedia.org/wiki/Fail_Whale

bwww.techcrunch.com/2008/06/06/twitter-suffers-minor-period-of-uptime-overnight/



Tip

Another reason your service can fail is that you may have exceeded your API quota, which is something like 100 requests per hour. So, if you do lot of debugging involving clicking on your friends to view their tweets, you may need to take a forced coffee break every so often.


Anyway, with this out of the way, we’re almost ready to talk to Twitter. First, let’s make sure that you have some data to play with. Post some “tweets” (messages that are fewer than 140 characters) and “follow” some people. You don’t have to know them, but it’s more interesting if you do. If you have no friends on Twitter, you can always follow me (@peterarmstrong) and my Ruboss partner Scott Patten (scott_patten)—the app we are building in this chapter is more interesting with at least two friends. (Note that I’m saying “friends” even though the following relationship is unidirectional, unlike the bidirectional “friend” relationship on services like Facebook. This is just because the phrase “people the user is following” is a mouthful.)

Now that we’re ready to talk to Twitter, we need to get ready to talk to Yahoo! Maps.

Getting started with Yahoo! Maps

Next, we’ll sign up for Yahoo! to use Yahoo! Maps. Why would I choose Yahoo! instead of Google? There’s a practical reason: at the time of this writing, the terms of service for Yahoo! Maps were nicer. (Also, Ryan Stewart has posted an excellent blog post[2] on how to use FXG assets and the ActionScript API with Google Maps, so there’s no need to duplicate his work.)

2http://blog.digitalbackcountry.com/2009/05/using-fxg-assets-as-custom-markers-in-google-maps/

Let’s start by signing up for the Yahoo! Developer Network at http://developer.yahoo.com. You’ll need to get a Yahoo! ID if you don’t already have one. Next, go to http://developer.yahoo.com/maps/ and click the Get an App ID button on the page to get an application ID. You’ll see a screen like the following. Enter information specific to you and your own organization, but leave the “Generic, No user authentication required” setting chosen so that the example in this chapter works. (Since URLs change, if that URL doesn’t work, go to http://developer.yahoo.com/wsregapp or just http://developer.yahoo.com/ and follow your nose.)

Click Continue. You’ll see something like this:

Copy this application ID and save it into a text file somewhere—you’ll need to paste it into your Flex code. (The “application entrypoint” is unimportant for our purposes, so we’re ignoring it.)


Yahoo! Maps Documentation

This book is certainly not trying to be a comprehensive Yahoo! Maps tutorial; it’s just an example that we’re using. The Yahoo! Developer Network page for the maps component (http://developer.yahoo.com/flash/maps/examples.html) as well as the API documentation (http://developer.yahoo.com/flash/maps/classreference/index.html) are the best places to start learning more about Yahoo! Maps.


Now that we have an application ID, we can download the Yahoo! Maps AS3 Component from http://developer.yahoo.com/flash/maps/. This book is using version 0.9.3 of this component; chances are you’ll use a newer version. (If a newer version doesn’t work for you, just grab the version I used from the code zip file for the book.) Once you’ve downloaded it, you’ll have a file like yahoo-maps-as3-api-0.9.3-beta.zip saved somewhere. Unzip it and copy the YahooMap.swc file from the Build/Flex directory into your libs directory of SocialStalkr. SWC files are compiled libraries, and any SWC files you put in your libs directory in a Flex project are automatically included when compiling.

Now that we’ve signed up for Twitter and gotten set up with Yahoo!, we can get down to work. First, we need to learn how to architect our application. While there are many newer application frameworks like Swiz, Mate, and PureMVC that have very vocal adherents, we’ll use Cairngorm. Cairngorm is currently the de facto standard application framework for Flex, and it’s not clear which of the challengers will emerge as the best alternative. So, I’m going to teach the standard. Whether or not you’ll use it, every Flex developer needs to know Cairngorm—if only to understand what the other frameworks are reacting to.

Cairngorm

We’re building the SocialStalkr application using Cairngorm. However, we’ll use Cairngorm in a slightly nonstandard way, in order to be slightly less verbose and to make the use of HTTPService easier. Specifically, we’ll use a couple of utility classes from my Flexible Rails book (Manning, 2008) to this effect. (These classes have nothing to do with Ruby on Rails; they’re just focused on making Cairngorm + HTTPService less verbose.)

Since Cairngorm has so many moving parts that work together, it’s very difficult to build this example iteratively—and as discussed at the beginning of the chapter, it would take too long. So, I’m just going to explain the finished result. As you see more and more of the code, you’ll grasp how it all fits together—so don’t worry if why we’re doing something isn’t 100 percent apparent at the time. By the end of the chapter, it will be.

Above all, keep in mind that Cairngorm is a Model-View-Controller (MVC) framework. As we create the various files, think about where they fit in the MVC pattern.


Flexible Rails, Cairngorm, and this book

The way that Cairngorm is used is based on section 8.1 of my Flexible Rails book. Even though we aren’t using Ruby on Rails in this book, the way that Flex uses HTTPService is essentially the same regardless of what is on the server side. So, since I already spent a whole book writing about how Flex should talk to Rails, it would be dishonest of me to pretend Flexible Rails didn’t exist and to ignore the approaches I used in it. Because of this, I’m feeling free to borrow a couple of utility classes from Flexible Rails for this section—and, while I’m at it, to make this section of this chapter a condensed version of sections 8.1 and 8.2 of Flexible Rails. If you have already read Flexible Rails, please feel free to skim until you get to the code.


Cairngorm history and motivation

One of the biggest problems with Flex is that it makes writing code almost too easy. How can this be a problem? Well, as we’ve seen, it’s possible to get a lot done without giving any thought to your application’s design. This can be dangerous: if other people (such as your client or marketing department) see a prototype running, they may get confused into thinking you have a fully functional app instead of an elaborate mock-up. Another problem is that if we develop iteratively without any refactoring (or thinking), we can end up with Rube Goldberg–like contraptions in our MXML:

...this variable gets set, which triggers this binding, which updates this model element, which in turn updates this model element, which triggers this function, which dispatches this event, which...

Because Flex is so easy, it’s possible to have somewhat working code even with a terrible muddle. All the Flex application frameworks try to solve this problem; as discussed, Cairngorm is what we’re going to pick for this chapter.

Cairngorm was created by Steven Webster and Alistair McLeod, the two cofounders of a consulting firm called iteration::two, which was based in Scotland. They were acquired by Macromedia, which was then acquired by Adobe. (Steven and Alistair are famous in Flex circles for having written the definitive book on Flex 1.0, Developing Rich Clients with Macromedia Flex.) Cairngorm embodies many of Steven’s and McLeod’s opinions about how to write Flex applications. Because their book helped many developers (myself included) to learn Flex, these opinions have a lot of clout. And because Steven and Alistair are now at Adobe (and Cairngorm is at Adobe Labs), Cairngorm has gained even more mindshare among Flex developers because of its somewhat “official” status.

That said, you certainly don’t need to use Cairngorm. Steven Webster wrote a blog post titled “Why I think you shouldn’t use Cairngorm,” (http://blogs.adobe.com/swebster/archives/2006/08/why_i_think_you.html), which lists some prerequisites for using Cairngorm. Essentially, Cairngorm can be overkill for small, single-developer applications (such as this one), and it can be confusing if you’ve never built a complete Flex application before. (We’re up for the challenge, though—we’re not “dummies” after all.) If, at the end of this chapter, you decide that you don’t like Cairngorm, don’t worry: you can develop complete, innovative Flex applications without using Cairngorm. For example, I currently spend most of my time developing Flex applications using RestfulX. (Of course, the RestfulX framework was formerly known as the Ruboss Framework, so I’m more than a little biased here.)

If you want to learn more about Cairngorm, the site www.cairngormdocs.org/ is devoted to collecting links to Cairngorm documentation and examples. In terms of tutorial documentation, the best starting place is the six-part article series that Steven Webster wrote for the Flex Developer Center. Part 1 is at www.adobe.com/devnet/flex/articles/cairngorm_pt1_print.html, and each part links to the next one. The articles develop an application called CairngormStore, which is a simple online store. These articles are rather outdated: at the time of this writing, Cairngorm is at version 2.2.1; the articles refer to version 0.99. However, they’re a good way to learn the theory of Cairngorm, even if many of the details have changed.

I’m going to assume that if you’re interested in using Cairngorm, you’ve read these articles or will read them; as such, I won’t duplicate their content. This book won’t include a 5–10 page “theory of Cairngorm” section. Instead, we’ll learn Cairngorm by doing, building the SocialStalkr application from scratch using Cairngorm 2.2.1. If at the end of this chapter you want to look through more Cairngorm-using code, take a look at the updated version of Chen Bekor’s ModifiedCairngormStore at www.brightworks.com/flex_ability/?p=61.

Downloading and installing Cairngorm 2.2.1

We’ll start by downloading Cairngorm 2.2.1. It’s currently found at http://opensource.adobe.com/wiki/display/cairngorm/Downloads. Download the binary, source, and documentation zip files from the three separate links.


Note

Download Cairngorm 2.2.1, not Cairngorm Enterprise 2.2.1. (Cairngorm Enterprise is for LiveCycle Data Services.)


Unzip these files into their own folders. Next, we’ll import the Cairngorm project into Flex Builder so that we can easily browse it. (The zip file includes a Flex Builder .project file.) In Flex Builder, choose File > Import > Other. Choose Existing Projects into Workspace, and click Next. In the Import dialog, browse to the Cairngorm2_2_1-src directory that was created when we unzipped the Cairngorm 2.2.1 sources. You’ll know you found it when you see the Cairngorm project highlighted in the Projects list. Click Finish to import the project. Once the project is imported, you can browse the source code, starting by expanding the com folder.

There isn’t much code in Cairngorm, so you should read it all at some point.

Now that we’ve downloaded Cairngorm, let’s add it to SocialStalkr. Copy the Cairngorm.swc file from the Cairngorm 2.2.1 binary download into the libs directory of the SocialStalkr project. (This is the same directory that we put the YahooMap.swc library into in chapter 2.)

That’s it; Cairngorm is now usable in SocialStalkr.

Before continuing, the last setup task we’ll do is to create most of the standard directories that are used in Cairngorm applications. Create an src/com/socialstalkr directory, and inside that directory create the following directories: business, command, control, model and util. (All but the util directory are standard Cairngorm.)


Q. Didn’t you forgot the event and vo packages?



A. No, I didn’t forget them—I’m omitting them. We aren’t going to create custom event subclasses of CairngormEvent—instead, we’ll go against the officially recommended Cairngorm convention and dispatch plain CairngormEvents every time. We’ll set the data property to an anonymous object containing whatever we need. To me, the reduction in the amount of code is preferable to more type safety (especially on a smaller project such as this). On a larger project with lots of developers, the balance may be different.



Regarding creating a vo package for Value Objects, we’re just using XML for now so we don’t have any value objects yet. Adding value objects at this point would be packing too much into the refactoring, so we’re not going to do it yet.




Cairngorm event sequence overview

Before we begin, I’ll present a brief overview of the typical sequence of events in which we’ll use Cairngorm. It refers to a bunch of classes we haven’t created yet but you should be able to understand what follows. (If it doesn’t make sense now, don’t worry—the goal isn’t for it to completely make sense, but for it to make future sections make more sense when you read them):

  1. A component (for example, the FollowingGroup component we’ll create for the Twitter users we’re following) calls CairngormUtils.dispatchEvent with an event type (for example, EventNames.SHOW_FRIEND_TWEETS) specified in the EventNames class (which is a bunch of String constants).
  2. Because of the SocialStalkrController having called addCommand with that event type from EventNames, a command (for example, com.socialstalkr.command.ShowFriendTweets) has its execute method called.
  3. This command creates a new business delegate (for example, com.socialstalkr.business.TwitterDelegate), which contains functions related to a given web service. It passes itself in as the IResponder so that when the business delegate is done, the command’s result or fault function will be invoked.
  4. In typical Cairngorm applications, the business delegate retrieves services from a Services.mxml file and uses them. We don’t do this. Instead, our business delegates themselves delegate all their work (a very businesslike thing to do) to the ServiceUtils.send() public static method. This method invokes a URL that invokes the appropriate HTTP service. It also attaches the responder to the service call, so that its result or fault handler will be triggered accordingly.
  5. When the service call returns, the result or fault handler of the command is invoked accordingly. It does what it needs to do, such as making a state change in the SocialStalkrModelLocator, dispatching another CairngormEvent with CairngormUtils.dispatchEvent, and so on. That’s about as much explanation up front as is useful. Let’s see some code! (The rest of this chapter is full of code, so grab a coffee.)

Creating the main application

Now that we have a new Flex project, a Twitter account with some friends and some tweets of our own, and a Yahoo! developer account, the first bit of actual work we’ll do is fill in the main SocialStalkr application file that was created for us. Paste the following code (selecting the text in Adobe Reader shouldn’t select the cueballs, so you should be fine) into the src/SocialStalkr.mxml file, or grab the code from manning.com/armstrong3:

ch07/src/SocialStalkr.mxml

We use the new Declarations element in Flex 4 for nonvisual children, in this case the SocialStalkrController.

We create two states, a login state and a main state, for the SocialStalkr app. The state determines which of the LoginPanel or MainApp are visible, since both use includeIn to only be in one state.

All Cairngorm apps have a FrontController. Ours is the SocialStalkrController, which we’ll see soon. You need to remember to actually instantiate it by putting it in the fx:Declarations, or your app won’t function properly. (By this, I mean that your events won’t work.) Also, note how we use view states and includeIn to simulate the way a ViewStack would operate: to show only one child component at a time. View states are much more flexible, however.

Creating the ModelLocator

Next, let’s start by creating the SocialStalkrModelLocator. A standard Cairngorm application has one ModelLocator, which is a “single place where the application state is held.”[3] The app will then bind to the variables in this file directly. This will save us from passing around a bunch of variables.

3www.adobe.com/devnet/flex/articles/cairngorm_pt2_print.html.

ch07/src/com/socialstalkr/model/SocialStalkrModelLocator.as

All variables are Bindable.

We implement the IModelLocator interface.

The formatTweet function formats a tweet using the dateFormatter instance variable.

The dateFromTwitterDate encapsulates parsing Twitter’s date format.

We ensure no other class can construct a SocialStalkrModelLocator. (This is explained further below.)

DateFormatter lets us easily format dates based on a configurable formatString.

This is the getter for a shared instance.

This is the internal SingletonEnforcer class.

The [Bindable] annotation on the class means that every public variable is bindable. The public variables in this class represent the shared state in our Flex application. Note that the SocialStalkrModelLocator class implements com.adobe.cairngorm.model.IModelLocator . IModelLocator is a marker interface: it has no methods. (It does, however, have a comment explaining that classes implementing it should be Singletons.) The SocialStalkrModelLocator is a Singleton, and we accomplish this by making the constructor take as a parameter an object whose type is SingletonEnforcer , which is a private class that’s not visible to any other class. (This is a trick I learned from Dima Berastau, creator and lead developer of the RestfulX framework for Flex.) The shared instance is lazily constructed and retrieved with the instance getter . The constructor also sets up the dateFormatter .

The SocialStalkrModelLocator has all the shared state in the app, as well as some utility functions that use this shared state. The formatTweet function formats a tweet , which uses a dateFromTwitterDate function that’s heavily based on the makeDate function of the TwitterStatus class in the Twitterscript API (not covered in this book).


There’s an API? Why are You Doing Everything Manually?

Frankly, I’m doing everything manually since the API is an extremely thin wrapper, and since I’m not trying to teach how to use an API—I’m trying to teach the basics of Flex. If you use the API you never create HTTPServices, for example, and you get a strongly typed object instead of XML. I feel you’ll learn more if we just use what’s provided by Flex as much as possible. (This won’t be true with Yahoo! maps—in that case, we’ll use their API.)


If you want to learn more about Twitterscript, see http://code.google.com/p/twitterscript/ for the original version of it. Note that I’ve forked it on GitHub (www.github.com/peterarmstrong/twitterscript) to make some small fixes to it, and Tony Hillerson has in turn forked my fork to fix authentication with AIR (www.github.com/thillerson/twitterscript). Tony’s version will probably be more advanced when you read this, so I recommend looking at both of them.

Creating the control package

Next, we create the control package. It will contain two classes: EventNames and SocialStalkrController.

EventNames.as

First, we create EventNames.as. This isn’t a standard Cairngorm class; instead, it’s particular to our “no CairngormEvent subclasses” approach.

ch07/src/com/socialstalkr/control/EventNames.as
package com.socialstalkr.control {
public final class EventNames {
public static const SHOW_USER_TWEETS:String =
"showUserTweets";
public static const SHOW_USER_FRIENDS:String =
"showUserFriends";
public static const SHOW_FRIEND_TWEETS:String =
"showFriendTweets";
public static const POST_TWEET:String = "postTweet";
public static const VERIFY_CREDENTIALS:String =
"verifyCredentials";
}
}

This class lists all the event names, defining constants for each name. This ensures that we won’t let a typo give us strange runtime behavior. I prefer this to using Strings everywhere for another reason, too: it makes it easier to check that we aren’t using an event name that’s already being used.


Safe and Verbose or Fast and Loose?

We can pass Strings around without using constants—it’s a question of “how much do you hate verbosity?” versus “how much do you value safety?” If we’re totally concerned about safety, we create custom events for each event; if we totally hate verbosity, we skip this file. This approach is my compromise.


These event names will be associated with commands, as we’ll see next.

SocialStalkrController.as

After creating the EventNames, we create the SocialStalkrController. This class extends FrontController. A standard Cairngorm application has one FrontController subclass, whose responsibility is to hook up the event names with the commands (which we’ll see later). Typically, these event names come from the custom event subclasses; in our case, they come from EventNames.

ch07/src/com/socialstalkr/control/SocialStalkrController.as

We extend FrontController and call the inherited addCommand method for each EventNames.SOME_NAME_CONSTANT and command combination. We’ll see the commands soon.

Having created the standard Cairngorm FrontController subclass, let’s now add two nonstandard classes to make our lives easier. After this, we’ll go back to adding code that follows the standard Cairngorm patterns.

Creating CairngormUtils and ServiceUtils

Next, we’ll add two nonstandard classes from Flexible Rails that will simplify how we use Cairngorm: CairngormUtils and ServiceUtils.

CairngormUtils.as

First, we’ll create the CairngormUtils class. Its sole purpose is to save some typing, since we dispatch so many events.

ch07/src/com/socialstalkr/util/CairngormUtils.as
package com.socialstalkr.util {
import com.adobe.cairngorm.control.CairngormEvent;
import com.adobe.cairngorm.control.CairngormEventDispatcher;

public class CairngormUtils {
public static function dispatchEvent(
eventName:String, data:Object = null):void {
var event:CairngormEvent = new CairngormEvent(eventName);
event.data = data;
event.dispatch();
}
}
}

This class defines one public static function, dispatchEvent. It takes a required eventName parameter and an optional data parameter that defaults to null if omitted. It creates a new CairngormEvent with the type set to the eventName. It then sets the untyped data property to the data provided (or null if omitted). Finally, it calls the event’s dispatch method, a CairngormEvent method that does the work of getting the shared instance of the CairngormEventDispatcher for us.

ServiceUtils.as

Next, we create a nonstandard class called ServiceUtils, which contains one public static method called send, which we’ll use to talk to web services via HTTP. As you’ll see, the way that you do this is via a class called HTTPService.

ch07/src/com/socialstalkr/util/ServiceUtils.as

We create a send function , which has a bunch of parameters. All but the url parameter have defaults, so only the url parameter (which specifies the URL of the HTTPService) is required. Inside the send function we construct a new HTTPService , set its properties, and call its send method. The optional parameters specify service properties like the contentType and method that have sensible defaults if omitted. The responder is added to the AsyncToken returned by the send() call so the responder methods can be invoked.

This is the first time in this book that we’ve seen HTTPService, which is pretty remarkable (and frankly a bit odd) when you think about it—Flex applications are all about talking to servers, and this is the first place we’ve seen how to do this. However, Flex is a very large topic with lots to cover, as shown by the fact that we could spend most of a book before we got to the point—talking to one or more servers over HTTP. The important thing to note about HTTPService is that invoking its send() method is an asynchronous call, so nothing happens immediately in the UI after the send() method is called. (If it was synchronous, the UI would block until the call returned.)


Integrating Flex with Servers

HTTPService is just one way that Flex applications can talk to servers. Flex can also use WebService and RemoteObject components to talk to servers. In this book, we’re sticking with HTTPService, since it’s the most flexible: HTTPService lets you integrate with any server-side technology, whether that’s Java, PHP, .NET, Ruby on Rails, or whatever. Furthermore, these servers can use “RESTful” APIs to support multiple clients other than Flex, such as HTML and iPhone. If you like RESTful services, I recommend looking into the MIT-licensed RestfulX framework—again, I’m totally biased in favor of RestfulX, however. Finally, a word about HTTPService being asynchronous: Flex programming, when done correctly, involves making a ton of asynchronous service calls and handling their results. Don’t try to fight this; just accept that this is fundamental to how Flex code is written and embrace it.


Anyway, back to the ServiceUtils#send() method. You may be wondering why we’re doing all this. The answer is that this approach lets us avoid using the standard Cairngorm approach of using a Services.mxml file that defines all the services. That approach is problematic when we use HTTPService a lot, because hardly any properties of a given HTTPService remain constant between service invocations. Worse, if we don’t explicitly set the properties to the values we want (even those where we want the default value), we can have unexpected behavior because the properties that a previous use of the HTTPService set will remain set that way. For example, we can have the wrong contentType, resultFormat, and so on if we (or some maintenance programmer) are careless. The disposable HTTPService approach we use here is a lot less bug-prone.

Now that we have the building blocks in place, we can move on to the higher-level classes that use ServiceUtils. First up, since it’s next lowest on the food chain, is the TwitterDelegate business delegate. Business delegates are a layer between the low-level plumbing code (in ServiceUtils) and the commands, which we’ll describe after the TwitterDelegate.

Creating the TwitterDelegate

In this section, we’ll create the TwitterDelegate business delegate that will use the ServiceUtils class we’ve just seen. This class will be used in the commands (which we’ll create next).

ch07/src/com/socialstalkr/business/TwitterDelegate.as

We create a reference to the shared SocialStalkrModelLocator.

The _responder variable stores a reference to the IResponder, which will be passed to the ServiceUtils.send method, and end up responding to the service call.

The verifyCredentials method logs into Twitter with a username and password combination. Note the http://name:[email protected]/ URL syntax, which my Ruboss partner Scott Patten showed me.

The showUserFriends method shows the friends of a Twitter user.

The showUserTweets method shows all the recent tweets of a Twitter user.

The postTweet method uses the http://name:[email protected]/ URL syntax to POST a new tweet to Twitter.

The endSession logs out from Twitter and redirects you to a very self-serving URL.

The TwitterDelegate contains the functions that do the real work for talking to Twitter. These functions all use the very handy ServiceUtils.send() method, invoked with the appropriate URLs.

Having created the business delegate, we’ll now create the commands—including the commands that use this business delegate.

Creating the commands

The first command that we’ll create will be the ShowFriendTweets command, which shows the tweets of one of the Twitter users you’re following.

ch07/src/com/socialstalkr/command/ShowFriendTweets.as

Here we’re creating a ShowFriendTweets command that implements ICommand and IResponder . Its execute method creates a new TwitterDelegate , which calls its showUserTweets method. When this returns, an XMLListCollection is constructed and assigned to the selectedFriendTweets in the shared SocialStalkrModelLocator .

(At this point, you may begin to see how Cairngorm fits together.)

Next, we create a similar command, ShowUserFriends, to list a user’s friends.

ch07/src/com/socialstalkr/command/ShowUserFriends.as

This is very similar to what we just did in ShowFriendTweets. We create a ShowUserFriends command, which creates a new TwitterDelegate and calls its showUserFriends method. The ShowUserFriends command then constructs an XMLListCollection out of the result and assigns it to the shared SocialStalkrModelLocator twitterUserFriends.

If you think that was easy, it gets even easier to show the tweets of the selected user.

ch07/src/com/socialstalkr/command/ShowUserTweets.as

We call showUserTweets again and just assign the result to a different variable in the SocialStalkrModelLocator: the twitterUserTweets . We also check if we have any tweets, and if so, we set the XML of the current twitterUser based on the first tweet. Yes, this is cheesy, but it’s necessary since there’s currently no Twitter API call to get this directly. (Worse, if a user has no tweets, this code will break.)

Next, we create a VerifyCredentials command, which logs into Twitter. Again, this uses the TwitterDelegate.

ch07/src/com/socialstalkr/command/VerifyCredentials.as

We store the twitterName and twitterPassword in the userName and userPassword variables in the _model, for use when posting tweets.

We then call the verifyCredentials method.

When the service call returns, we dispatch events that trigger the ShowUserTweets and ShowUserFriends commands.

Note how the result handler (which is called on successful return) triggers the execution of two other commands: ShowUserTweets and ShowUserFriends . Recall that this association was defined with the addCommand calls in the SocialStalkrController.

Next up is the PostTweet command, which posts a new tweet to Twitter.

ch07/src/com/socialstalkr/command/PostTweet.as

We create a new TwitterDelegate with this command as the responder.

Once the new tweet is posted, we list the user tweets again.

When the postTweet call returns, we just dispatch an event to trigger the ShowUserTweets command. This is a simple way of ensuring our list is accurate (and that it includes tweets made from other Twitter clients). It’s inefficient, though, and it will increase the speed that we use up our number of tweets per hour API limit. If we were building a real Twitter client we wouldn’t do this.

Creating the visual components

Now that we’ve created so much of the plumbing, we turn to creating the visual components that use it. First, the LoginPanel—recall that it’s shown in the login state of the main SocialStalkr application.

ch07/src/com/socialstalkr/components/LoginPanel.mxml

Trigger the VerifyCredentials command, and pass the name and password along in an anonymous object.

Use a vertical layout, which includes padding to make the controls look nicely spaced inside the Panel.

Trigger the loadTwitterUser function on the Enter key being pressed in the twitterPasswordTextInput or the loginButton being clicked.

Now, with the past few pages demonstrating the verbosity of Cairngorm, we can start to see its benefits. Simply put, the business logic of logging in is nicely encapsulated from the UI controls that trigger it.

Next, after the login succeeds, the SocialStalkr app switches to the main state and shows the MainApp. Before we continue, I’m going to show the MainApp again, since this is what we’re creating in the rest of the chapter.

Let’s look at the code for the MainApp now.

ch07/src/com/socialstalkr/components/MainApp.mxml

The MapPanel and TwitterGroup components are in an HGroup, which lays them out horizontally.

The BitmapImage only supports embedded images (unlike an mx:Image, which can load URLs), so we embed Yahoo!’s image.

We show the copyright notice in a Label. Note how the text attribute can span multiple lines without creating any extra spaces or newlines in the resulting string.

There’s not much to the MainApp—it’s just layout, really.

Next, we look at the components contained in the MainApp. First we have the MapPanel.

ch07/src/com/socialstalkr/components/MapPanel.mxml

Be sure to use your own Yahoo! App ID, not this. (That’s why it’s in strikethrough.)

This is the YahooMap we’re displaying.

BindingUtils.bindSetter listens to the data binding events to trigger the locateTweet function call. This saves us from having to try to call locateTweet from a Cairngorm command, which is brittle.

We initialize the YahooMap. Note how we create the component, initialize it, attach listeners, and then add it to the containment hierarchy—this ensures it (and its parents) are ready for the events that will get fired.

So far, we have added a const (meaning it doesn’t change) for our YAHOO_APP_ID . Do not use this one: use the one you got when you signed up with Yahoo!. Next, we add a variable called _map for the YahooMap , and in the onCreationComplete event handler function we set a bunch of fairly self-explanatory properties, including initializing the _map . Let’s look at the rest of the code in this file now.

ch07/src/com/socialstalkr/components/MapPanel.mxml (continued)

Let’s take a tour of the rest of this code.

We start by creating a function called locateTweet , which gets called whenever the _model.selectedTweet changes because of the use of the BindingUtils.bindSetter function . (BindingUtils let you set up binding expressions in ActionScript code.) Note that the removeAllMarkers() library function call got broken by Flex 4 Beta 2. It may be working by the time you read this, so I’m leaving this line in but commented out. (The app will work either way.)

The approach in locateTweet is a bit subtle: it checks to see if the text of the tweet contains text that matches the regular expression /@{(.*)}/, which means that text like “I’m at @{21 Water St, Vancouver} writing the book” will match but text like “I’m at 21 Water Street, Vancouver writing the book” will not. Specifically, the text “I’m at @{21 Water St, Vancouver} writing the book” will produce a points Array whose 0th element is “@{21 Water St, Vancouver}” and whose 1st element is “21 Water St, Vancouver”. So, we then check if we have a non-null points Array with a length of greater than 0, meaning if we have a match. If we do have a match, we create a new TwitterMarker with the profileImageUrl and with the text. Note that we replace the points Array’s 0th element, such as “@{21 Water St, Vancouver}”, with the points Array’s 1st element, such as “21 Water St, Vancouver”, in order to make the marker text look nicer. We also set the address with the points Array’s 1st element and then set the address of the marker to the address. We then add the marker to the _map’s markerManager, and then call our geocodeAddress function , which geocodes the address and centers the map on that latitude and longitude on a successful result .

Next, we add a function called onMapResize , which ensures the map is correctly sized when the map is resized (say, if its parent UIComponent grows if the application grows if the user makes the browser window larger).

We then add an onMapInitialize function, which sets the map to an arbitrary, fairly zoomed in zoom level of 3, an appropriate zoom level for “stalking” our friends who are embedding their special location tags in their tweets. We also start with an arbitrary Address. I’d have liked to have used your IP address as a basis for geocoding, but I don’t think this is possible to be done in pure client-side Flex code.

Having created the map, we turn to the task of creating a marker class that shows the user’s avatar and tweet. We’ll use this class for tweets that have location tags and that can be shown on the map. (Thanks to Dima Berastau for this code and help with the explanation!)

ch07/src/com/socialstalkr/components/TwitterMarker.as

We are creating a component called TwitterMarker, which extends the Marker class provided by Yahoo!. The Marker is not a Flex component like TextInput, List, or VBox—instead, it’s a direct subclass of flash.display.Sprite (more about this in the accompanying sidebar). In this class’s constructor , we store the URL of an image to display, as well as the text to display.

This class shows that if you want to, you can use lower-level components from the flash packages.

To achieve our objective and display a friend’s tweet as a marker on our Yahoo! map, we’ll have to create a few native Flash objects and use their programmatic graphics API directly. In our case we’ll start by creating a Shape , define its lineStyle to be 1 pixel wide, and make it use a nice gray (0x666666). (The Shape class creates lightweight shapes using the AS3 drawing API, and includes a graphics property so you can call Graphics methods. A Shape is lighter weight than a Sprite, since it can’t contain display objects or handle mouse events.)

Next we’ll specify that our shape should have a white background. Note that we still haven’t indicated what shape we actually want. Should it be a circle, a line, or something else? We call the drawRoundRect() method to use a rounded rectangle with a height of 51 pixels and a width of 250 pixels. Finally, we call the endFill() method to finish the creation of the shape. Now that our shape is ready, we need to add it as a child to the TwitterMarker object (using the addChild(_shape) method, which is equivalent to calling this.addChild(_shape)). All we’re accomplishing with this is adding our newly created shape to the Flash object graph. Until we added the shape somewhere, Flash wouldn’t know what all this drawing should happen relative to. (We add this Shape instance to draw a background shape for our marker, since Marker by default has no shape.)

Now that we have a rounded box drawn on the map at the exact location we specified when creating the TwitterMarker instance, let’s tackle our next challenge, which is loading the user image specified as a url argument in the TwitterMarker constructor. Since this is going to be an asynchronous operation, we have to use Flash Loader object, which will go out and fetch the image bytes from the URL we specified and load them into the Flash runtime. Again, we add the Loader as a child of the TwitterMarker instance. Last but not least, we’ll create a Flash TextField to display the actual tweet. TextField is a low-level object that’s used to render text. We set its properties, such as the font type, and add it as a child to the current TwitterMarker instance.

Anyway, that said, all this class does is draw the text and image for the marker with the avatar and tweet; we don’t need to get bogged down in the advanced details about mixing and matching Flash and Flex components.


No fair! I’m an experienced developer! I want the advanced details!

OK, fine. Here’s what Dima Berastau has to say about this:

When you first encounter Flex, your primary activities will mostly revolve around developing MXML components and self-contained AS3 objects. Seasoned Java developers might think, “Awesome! This is easy. AS3 is almost like Java and MXML is just a domain-specific language for laying out the UI declaratively. Nothing new here.” The Flash platform will be simply a runtime that your compiled code runs on. After all, you don’t go around messing with JVM byte code in Java.

Not true. Fortunately or unfortunately, the Flash platform is not just a runtime detail. In some advanced situations, you’ll be in a position where you’ll need to write code that uses Flash constructs directly, bypassing all the Flex component machinery. Integrating with third-party components such as Yahoo! Maps is a great example of this: we want to display your friends’ tweets as markers on a Yahoo! map embedded in your Flex application. However, the YahooMap and the Marker classes aren’t Flex components—they just both directly subclass flash.display.Sprite.

Although you might be tempted to try to add a new marker to the map by doing something like calling addChild(new TextInput()), this won’t have the desired effect of displaying a TextInput element over some location on the map. Flex components have a much more complex lifecycle compared to basic Flash objects and, as such, don’t play well together.


Next, we create the TwitterGroup class, which displays the content to the right of the map.

ch07/src/com/socialstalkr/components/TwitterGroup.mxml

The _buttonData ArrayCollection is used as the dataProvider of the ButtonBar.

The changeSelection function sets the state of the component to the data property of the object in the _buttonData Array at the event.newIndex, which will be either you or following.

These are the states that the TwitterGroup can be in. This use of view states, along with the use of the ButtonBar, is essentially what a TabNavigator would’ve been used for in Flex 3.

The ButtonBar specifies a labelField of label, meaning that the buttons will show either You or Following, which are the label properties of the anonymous objects in the _buttonData ArrayCollection.

Create a Logout button that just calls the endSession function directly, as we didn’t bother to create a command for logout.

The YouGroup and FollowingGroup components are in only one view state each.

Note that I did not use a TabNavigator since it can only contain Halo children, and I’m trying to use Spark components wherever possible in this app.

Next up, we create the YouGroup and FollowingGroup components contained in the TwitterGroup component.

ch07/src/com/socialstalkr/components/YouGroup.mxml

Posting a tweet just triggers the PostTweet command. People like to pick on it, but hooray for Cairngorm!

The Halo Image class is used here because the Spark BitmapImage class can’t handle nonembedded images.

We bind to the _model for various shared properties, like the name.

Data binding also works nicely to calculate things like the number of characters left in a tweet. Note how XML’s restrictions against < and > inside attribute values forces the use of &lt;= for <=.

We use the Halo List class since the Spark List class is terrible at word wrapping.

As this example shows, Flex 4 apps can still use help from the old Halo components. It also shows how the shared state in the Model Locator pattern is used by Cairngorm. Depending on your taste and on the size of apps you typically build, this is either nice and simple or else a distasteful, thinly disguised use of global state.

Next up, we create a FollowingGroup class for the Twitter users we’re following. Recall that this app shows a List of them at the top and the tweets of the selected friend at the bottom.

ch07/src/com/socialstalkr/components/FollowingGroup.mxml

Get a reference to the SocialStalkrModelLocator singleton.

When a user is selected, we assign the shared selectedFriend variable and show that friend’s tweets. Note how I’m using the fully qualified class name of the Spark List (spark.components.List) since both Halo and Spark List classes are used here.

The locateTweet function just sets the shared selectedTweet variable, which triggers the binding in the MapPanel.

We use a Spark List here with a custom itemRenderer.

We use a Halo List here since we need word wrapping.

Again, here we’re being negligent about caching, and we’re just showing the friend’s tweets every time we select them. This repeated use will often hit the Twitter rate cap, so don’t do this if you’re building a real Twitter client!

One more component left! Finally, we need to build the custom ItemRenderer for the Spark List of the Twitter users we’re following.

ch07/src/com/socialstalkr/components/UserListItemRenderer.mxml

We override the data setter and getter, and store the _value as XML. The component that’s using this as its itemRenderer sets the data property, which is what this set function in the ItemRenderer subclass takes advantage of.

We create the required states for a Spark ItemRenderer. Note the use of the stateGroups attribute: we’re creating a “big” StateGroup to refer to both the hovered and selected states. Note that the normal, hovered, and selected states are required state names for Spark ItemRenderers to have!

We use a Halo Image here since its source isn’t embedded.

The includeIn attribute can take StateGroups as well as just States.


Caution

Flex 3 programmers take note: if you don’t define the required normal, hovered, and selected states for your Spark ItemRenderers, your app will explode!


That’s it! Click Play to compile and run the application. Log in with your Twitter ID; you’ll see the app shown in the beginning of the chapter. If you then post a tweet with a location coded like @{some address that Yahoo can parse}, you should be able to click on that tweet and see a nice marker displayed on the map, centered over your location. When you click on tweets with no @{location} tags, no marker is shown on the map.

Key points

  • For an application of this size, Cairngorm is probably overkill. However, this is an introductory book, so we don’t have the space to build an application that’s large enough to demonstrate the benefits.
  • Cairngorm is a useful way of structuring large Flex applications. With the switch to Flex 4, it will be interesting to see whether Mate, Swiz, or PureMVC can dethrone it.
  • Despite its benefits, Cairngorm is verbose. You can tell that it owes its origin to a bunch of J2EE patterns—a fact that deserves some discussion. Flex is only possible because of the evolution of the Flash platform, and in many ways it’s the future of the Flash platform. However, there’s some tension here—some of the changes haven’t been welcomed universally. Colin Moock wrote about this in his article “The Charges Against ActionScript 3.0,” at www.insideria.com/2008/07/the-charges-against-actionscri.html. At a very high level, it’s as though Flash has grown up from being a punk rock teenager to a mortgage broker—some of the people who knew it “back in the day” may wonder if it’s forgetting its past. However, the roots are still there: Flex does compile to Flash, which means that much more is possible than traditional desktop or web UI developers are used to. Besides, Flex and Flash are being a lot more unified with Flex 4—so much so that Flex Builder has been renamed to Flash Builder 4. So Flash is Flex, and Flex is Flash, and they were all rebranded happily ever after.
  • Flex is great at talking to web services, and HTTPService makes it easy to talk to RESTful services. (You can find out more about this in Flexible Rails, and also explore the RestfulX framework to see the ideas that began with Flexible Rails taken to the next level.)

What’s next?

That’s it for this book. I really hope you enjoyed it, and that the cartoons gave you a couple of laughs as you learned the basics of Flex. Please email me at [email protected] with your feedback—good, bad, or both. If you’d like to share your comments with other readers, please post them to Manning’s Author Online forum at www.manning.com/HelloFlex4.

Finally, I hope you build something cool using Flex 4. You’re definitely way past the “Hello World” level as a Flex developer now...

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.137.183.10