Remove Mac OS / Unix .DS_Store Files
It seems that Ant won’t delete directories with .DS_Store files and you can’t get rid of them in finder (b/c it’ll just replace them when you remove them), so we needed to leverage a quick command in terminal:
sudo find . -name “.DS_Store” -depth -exec rm {} \;
The aforementioned command will recursively remove all of the .DS_Store files from a given directory; we thought someone else mind find this useful.
Swiz Passive View Example :: Part 2
Introduction
After implementing Part 1 of the Swiz + Passive View (PV) Example, I immediately decided that one thing I missed from the original Spring ActionScript (SAS) version was the ability to create services in an XML file that’s loaded at runtime, thus allowing you to take your app from one environment to another and simply change the XML as opposed to recompiling. Some devs don’t seem to care about this, but I find it quite useful and so do many of my clients so I created a simple DynamicServiceLocator (SL) class and “injected” it into my Example.
Tutorial Goal: Create a Dynamic Service Locator that Instantiates Services from an External XML File at Runtime
Assets
Acronyms
- PV = PassiveView
- SAS = Spring ActionScript
- SL = Service Locator
- VM = View Mediator
- CG = Cairngorm
- IoC = Inversion of Control
- DTO = Data Transfer Object
Caveats
Please read the previous posts in this series to get up to speed:
I won’t go into the details of what Swiz is and how it works as I’d like to let the code speak for itself and you can just hit up the Swiz homepage and view their simple examples; that said, I’ll point out several things I really like about Swiz.
I am using Swiz 0.6.4, as I found issues with the 1.0.0 alpha release (that I’m going to bring up with Ben Clinkenbeard).
Getting Started
The idea is simple:
- Create an XML file that defines all of the services leveraged in the app.
- Add the
DynamicServiceLocatorto theBeanLoader(Beans.mxml) and give it the URL to load the services XML file. - Listen to the
DynamicServiceLocator’s complete event, indicating that the services are loaded and parsed, and start the app up. - Inject the SL into the Delegates as opposed to injecting the services directly (that were previously defined and hardcoded in the
BeanLoaderfrom Part 1). - In the Delegate, request a service from the
DynamicServiceLocatorvia an ID that was set in the service’s definition in the XML file. - Use the service.
Let’s take it piece by piece…
Step 1: Create Services XML File
Let’s start by creating an XML file called services.xml and putting it in src/assets/service-locator/. Next, let’s add some services — truth be told, I took the format for the XML that defines a service directly from the idea behind the application context files used in SAS and then created my own Object Factory…it’s very simple mind you b/c I didn’t need a huge object factory taking up a ton of memory when the only objects it would ever create were 8 different services.
<?xml version="1.0" encoding="utf-8"?> <objects> <!-- =================================================================== --> <!-- SERVICE LOCATOR --> <!-- =================================================================== --> <!-- =================================================================== --> <!-- This application context defines multiple test configurations, it can be expanded to include a deployment configuration as well, please see comments below. 1. Local Testing: XML Services 2. Dev Server Testing: XML Services 3. Deployment: XML Services --> <!-- =================================================================== --> <!-- =================================================================== --> <!-- 1. LOCAL TESTING: XML Services --> <!-- =================================================================== --> <object id="loginService" class="mx.rpc.http.mxml.HTTPService"> <property name="url" value="assets/xml/login.xml" /> <property name="resultFormat" value="e4x" /> <property name="method" value="GET" /> </object> <object id="employeeService" class="mx.rpc.http.mxml.HTTPService"> <property name="url" value="assets/xml/employee_list.xml" /> <property name="resultFormat" value="e4x" /> <property name="method" value="GET" /> </object> </objects>
The idea is to create a list of services as object nodes. Start by giving each <object> node a unique id attribute, as this is the key we’ll use to request the service later. The following line defines the loginService:
<object id="loginService" class="mx.rpc.http.mxml.HTTPService">
Next, define the concrete Flex service type in the class attr — right now the service class must be one of the following types:
mx.rpc.http.mxml.HTTPServicemx.rpc.http.HTTPServicemx.rpc.remoting.mxml.RemoteObjectmx.rpc.remoting.RemoteObjectmx.rpc.soap.mxml.WebServicemx.rpc.soap.WebService
Finally, add any additional properties you want to define for the service as <property> nodes with the name and value attrs matching properties that are available for the service type. The following line adds the url property for the HTTPService:
<property name="url" value="assets/xml/login.xml" />
Step 2: Add DynamicServiceLocator to the BeanLoader
We’ll add the SL to the BeanLoader just like we did for all the other objects we want managed by the IoC Container, except we’ll also provide her with the URL to our services.xml file that we just created. When the url property is set on the SL, it will automatically load the services, parse the XML, instantiate a service for each <object> node it finds that matches one of the aforementioned service classes, and then adds that service to it’s hash or Dictionary object’s list of services via the id as it’s key.
<service:DynamicServiceLocator id="serviceLocator" eventDispatcher="{this.dispatcher}" url="assets/service-locator/services.xml" />
The other thing to make note of is that we’re again passing a reference to the BeanLoader’s dispatcher so the SL can broadcast events to other objects in the Swiz IoC Container.
Step 3: Listen to the SL’s Services Load Complete Event
Since this is more of an application level event, we’ll make the ApplicationController object handle this event:
[Mediate( event="serviceLocatorServicesLoadComplete" )]
public function onServiceLocatorLoadComplete():void
{
logger.debug("onServiceLocatorLoadComplete");
this.eventDispatcher.dispatchEvent(new DynamicEvent("showMainView"));
}
Which then in turn broadcasts a “showMainView” event that’s handled by the ApplicationViewMediator and ultimately removes a simple preloader (which is there in case the SL should take any significant amount of time to load and parse — unlikely here, but useful in the future) and adds the MainView to the stage.
[Mediate( event="showMainView" )]
public function showMainView():void
{
logger.debug("showMainView");
this.view.removeChild(this.view.progressBar);
this.view.addChild(new MainView());
}
Now this may seem like overkill for this extremely simple example, as I could have just listened to the “serviceLocatorServicesLoadComplete” in the ApplicationViewMediator, but I wanted to proxy the event through the ApplicationController in case more needed to be done…What if we wanted to update a model level var to indicate that the SL was complete? What if we wanted to tell other objects that the SL was complete?…we wouldn’t want to do that from the ApplicationViewMediator as it’s sole purpose is to lend a hand to the MainView UI component and not to orchestrate application level processing, work, etc. Again, overkill in this example, but I wanted to put it in here as an example of what you might want to do in a much larger application.
Step 4: Inject the SL into the Delegates
Next we’ll want to inject the SL into the Delegates as opposed to injecting the hardcoded services defined in the BeanLoader. First, let’s declare the new serviceLocator property for the Delegate:
[Autowire(bean="serviceLocator")] public var serviceLocator:DynamicServiceLocator;
Next, let’s remove the service var’s declaration and create a simple getter method for it instead:
public function get service():HTTPService
{
return this.serviceLocator.getMXMLHTTPService("loginService");
}
Step 5: Request Service From SL
This allows us to leave the actual use of the service property untouched in our service method calls - this code hasn’t changed from Part 1, but I’m showing it for clarity. We’ll look at the Login Delegate for example:
public function login(dto:LoginDTO):AsyncToken
{
logger.debug("login");
return this.service.send();
}
Wrapping Up
The only other thing that I failed to mention that’s different from Part 1 is the use of a simple ProgressBar component in the Application root to provide the user with some additional feedback while the SL is loading and parsing. If you look at the main application file EmpMgmtConsoleSwizPassiveView you’ll notice that the MainView is now replaced by the ProgressBar component — once the SL is complete the ProgressBar is removed from the stage and the MainView is added (as mentioned in Step 3).
Finally, to test out the dynamic SL, open up the services.xml file in the example source code and comment out the first set of services that point to local, project-level XML files and ucomment the services that point to the WASI server. See, no recompiling.
And that about does it. Any questions?
Swiz Passive View Example :: Part 1
Introduction
If you followed my previous posts on the Employment Management Console application leveraging Spring ActionScript + Cairngorm, then you’ll be familiar with this small example as I simply ported it over from SAS + CG to Swiz using the Passive View (PV) design pattern.
Tutorial Goal: Create an Employee Management Console using Swiz and the Passive View Design Pattern
Assets
Acronyms
- PV = PassiveView
- VM = ViewMediator
- CG = Cairngorm
- IoC = Inversion of Control
- DTO = Data Transfer Object
Caveats
I won’t go into the details of what Swiz is and how it works as I’d like to let the code speak for itself and you can just hit up the Swiz homepage and view their simple examples; that said, I’ll point out several things I really like about Swiz.
I am using Swiz 0.6.4, as I found issues with the 1.0.0 alpha release (that I’m going to bring up with Ben Clinkenbeard).
As an additional side note, I chose the PV because I was always a fan of code-behind — I like separation of concerns so much that I actually detest looking at MXML with ActionScript in it — what a mess!..that and the fact that MXML is declarative and should just perform basic UI layout and not presentation logic. What I love about the PV is that it relies on composition as opposed to inheritance (ie the biggest issue I have with code-behind).
Finally, there are other examples of the PV + Swiz out there, like Ben Clinkenbeard’s example, but I went ahead and created an AbstractViewMediator that takes care of some race conditions when working with Views in a ViewMediator, like setting event handlers and data bindings. And I did some other things that I didn’t see in others that I’ll point out.
Swiz is Noninvasive
Swiz is a noninvasive framework that allows you to provide well organized structure and architecture to your app without writing a ton of boilerplate code that can be overly verbose and time consuming. Remember CG and how you were forced to do the following for service calls:
- Create an
Eventthat extends theCairngormEvent. - Create a
Commandto act as a responder for your service call. - Create a corresponding
Delegatethat actually makes the service call and transforms your data to client-side types before returning it to theCommand. - Don’t forget to map your Custom CG Event to your Command in the
FrontController. - Wash, rinse, repeat…and repeat…and repeat…and…mehhh
With Swiz, you can (and I emphasize can b/c you can still do it the old school way too) just broadcast a DynamicEvent from any object in the IoC Container (those objects that are defined in the Swiz BeanLoader — in my example, it’s in the class Beans.mxml) and then add some metadata to another object in the Container to “Mediate” that event.
Here’s an example — so in my LoginViewMediator I want to broadcast a “login” type event and pass the username and password along with it and I want my LoginController to handle this event:
private function submitBtnClickHandler(evt:MouseEvent):void
{
logger.debug("submitBtnClickHandler");
var dto:LoginDTO;
// create a login dto to contain the required fields for login
dto = new LoginDTO();
dto.userName = this.view.userNameTextInput.text;
dto.password = this.view.passwordTextInput.text;
var dynEvt:DynamicEvent = new DynamicEvent("login");
dynEvt.dto = dto;
this.eventDispatcher.dispatchEvent(dynEvt);
}
And now we handle this event in the LoginController like so:
[Mediate( event="login", properties="dto" )]
public function login( dto:LoginDTO ):void
{
logger.debug("login");
// TODO - make service call -- see in example src code
}
So let’s dig a bit deeper here and note all the cool stuff that’s going on and why I’m psyched about Swiz + PV:
No Custom Events (If You Don’t Want To)
Notice that I didn’t have to create a custom Event — less code — YES! Now, you can by all means create a custom event and Swiz will type check the event object and the event type to make sure they exist — check it out in the Swiz Docs for Event Handling — or you can save yourself some extra code and do what I did. While I’m usually a stickler for strongly typed objects, sometimes you have to ask yourself it it’s not just overkill for something as simple as this…personally preference I suppose, but less code without sacrificing organization and good practices wins that battle in my head.
Event Mediation
Swiz automatically handles the event and passes the meat of the event (the LoginDTO that I packages in my DynamicEvent) for me…uhm, yeah…that’s frigging cool! And you can pass multiple args as well. Again, see Swiz Docs. NOTE: One thing to remember about event mediation is that the handler method must be marked public — I’m used to making event handlers protected (and sometimes even private), but this won’t allow the Swiz event mediation to work it’s magic so make sure event handler methods are marked as public.
No Logic in MXML
My LoginViewMediator grabs the username and password from it’s corresponding LoginView and creates the event and DTO. The actual LoginView is just MXML…nuff said.
Event Dispatching and Handling Thereof in IoC Container Objects
Notice that the LoginViewMediator broadcasts the event from a class member variable called “eventDispatcher”. This next part is important: in order for Swiz to Mediate events, the events need to go through the central event bus using Swiz.dispatch(<eventType>) or by using the event dispatcher in the BeanLoader — I have chosen the latter. Why?…I have 2 reasons:
- I don’t like having a reference of Swiz in my classes — it’s just unnecessary and makes my application that much more coupled to the framework, something Swiz tries to get developers away from to begin with.
- The Swiz.as class is a singleton and singletons are bad…this is too long a topic to get into, but my main reason has to do with the use of Modules in large Flex apps and while this example doesn’t require modules, I’d still rather just stay the hell away from singletons.
I shove a reference of the BeanLoader’s eventDispatched into my IoC Container managed objects like this:
<controller:LoginController id="loginController" eventDispatcher="{this.dispatcher}" />
<mediator:LoginViewMediator id="loginViewMediator" eventDispatcher="{this.dispatcher}" />
Note that they both don’t need it in order for the controller to hear events from the view mediator — just the object broadcasting the event needs to have a reference to it, but I pushed it into the controller as well as since I’m broadcasting other events from it that I’d like other managed objects to listen to via mediation.
AbstractViewMediator
Since all of my views need a reference to their corresponding view, I decided to create a super class for all the mediators called AbstractViewMediator. This bad boy does several things starting with the injection of the view:
[Autowire( view="true" )]
public function set view( value:* ):void
{
logger.debug("AUTOWIRE :: view = " + value);
this._view = value;
// determine if the view has been initialized...
// NO...listen for it;s creation complete event
if(this._view.initialized == false)
{
this._view.addEventListener(FlexEvent.CREATION_COMPLETE, onCreationComplete);
}
// YES...call the init() method to kick off the instation of the view mediator
else
{
this.init();
}
// don't get in GC's way if the view is removed
this._view.addEventListener(Event.REMOVED_FROM_STAGE, cleanup);
}
Again, there’s a couple things to note about this method:
- The argument for the method is untyped, so how does the concrete
ViewMediator(VM) know how to inject the correct view? And then what about code-hinting for the view in the VM? Well, if you look at an actual implementation of a VM, like theLoginViewMediatoryou’ll see the following method:public function get view():LoginView { return this._view as LoginView; }Put this into method into each concrete VM with it’s corresponding view type and you’re good to go! Problem solved.
- We check to see if the view has been initialized, ie, has the creationComplete event fired and can I start to work with children components of this view without getting runtime errors. If it has, then we call the init() method (which can and should be overridden by concrete VMs to initialize themselves); if not, then we listen for the creationComplete event and call the
init()method then and only then. This ensures that when we want to set event handlers and data bindings on the view’s children we know they exist and we don’t hit nulls leading to runtime errors. - Finally, if you look at the
init()method in the AbstractViewMediator, you’ll see that it also calls thesetViewListeners()andsetViewDataBindings()methods — these are placeholder methods where developers can again add concrete event handlers and data bindings in VM subclasses by overriding them.
The last thing the AbstractViewMediator does is provide the event dispatcher class member variable that we discussed earlier: public var eventDispatcher:IEventDispatcher;
Controllers & Delegates
In Swiz, we eliminate the idea of a Command class (from Cairgorm) and kind of replace it with the controller — I say kind of b/c it’s not exact mapping as the Cairngorm Command follows the actual J2EE Command design pattern whereas Swiz uses a controller to handle events from the UI to make service calls, act as a responder for the service calls, and finally to orchestrate what happens in the app after the service call (usually by dispatching an event). Since we already looked at the event mediation of the in the LoginController we won’t discuss that, but we will dig into how the controller leverages a corresponding LoginDelegate to call the service and perform data transformations on the service’s response object. So let’s look at the internals of the actual login event mediation in the LoginController:
[Mediate( event="login", properties="dto" )]
public function login( dto:LoginDTO ):void
{
logger.debug("login");
var call:AsyncToken = this.delegate.login(dto);
// I created 2 ways to handle the login service delegate
// you can either have the result come back to the controller
// or you can catch the result in the delegate and have it perform
// the necessary data transformations (traditional approach) before
// kicking it back to this controller via an event
// APPROACH 1) have the results come back directly to this controller
//this.executeServiceCall(call, onLoginResult, onLoginFault);
// APPROACH 2) have the results come back the delegate for data transformations
// before coming back to this controller
this.executeServiceCall(call, this.delegate.result, onLoginFault);
}
Out of the box, Swiz recommends that the controller handle the actual service response and data transformations before deciding what the app should do next…that’s too much responsibility for one object in my opinion, so as you can see I decided to allow the LoginDelegate to handle the actual service response: this.executeServiceCall(call, this.delegate.result, onLoginFault);. After the delegate finishes with the response, it dispatches an event:
LoginDelegate
public function result(resultEvent:ResultEvent):void
{
logger.debug("result");
var userModel:UserModel;
var xml:XML;
var dynEvt:DynamicEvent;
// get the response typed as desired
userModel = this.getTypedResponse(resultEvent);
// let something know that the login delegate is done
dynEvt = new DynamicEvent("loginDelegateComplete");
dynEvt.userModel = userModel;
this.eventDispatcher.dispatchEvent(dynEvt);
}
And then the event is mediated by the LoginController where it updates the necessary model properties and dispatches an event to signify the end of the login process.
[Mediate( event="loginDelegateComplete", properties="userModel" )]
public function completeLogin(userModel:UserModel):void
{
logger.debug("completeLogin");
var role:String;
// populate the model with data from the response DTO
this.appModel.user = userModel;
// determine of user is an admin
for each ( role in userModel.rolesList )
{
if(role == RolesConstants.ROLE_ADMIN)
{
this.appModel.user.isAdmin = true;
break;
}
}
// set this last as this is what binds the view change
this.appModel.isUserAuthenticated = true;
var evt:DynamicEvent = new DynamicEvent(EVENT_LOGIN_COMPLETE);
this.eventDispatcher.dispatchEvent(evt);
}
I think that about covers it for this edition. Any questions?
More to come on Swiz in the future.
Dragon Dictation iPhone App — Incredible!
Dragon Dictation Recording on iPhone
My partner and I were chatting about this app and how we’ve both used Dragon on a computer back in the late 1990’s and thought it was quite impressive…well kids, this one takes the cake. No longer do you need to hand type text messages (SMS), emails, FaceBook or Twitter updates on your iPone — simply fire up Dragon Dictation, click Record, start talking (as opposed to typing), click Done, and voila! On the screen before you are your spoken words in text. Now just click the button “Send to Clipboard” and then select the app you want to paste it into (like Txt Messaging, Email, etc.) Done.
I played with this thing for about 30 mins last night and it honestly failed to pick up the exact words I said…like…never.
I was truly impressed with this app on the desktop, but having this thing on a hand-held mobile device is amazing!
Oh, and this sucker is FREE!
FlexUnit 4 Testing Services In Flash Player Issue
We’ve created a number of FlexUnit 4 (FU4) tests for our current, large project and the suite of tests that seems to be of the most importance to both us and our client is the one that tests the services. Our client’s back-end services are simple JSPs that return XML payloads for a number of CRUD operations on various objects in the system, so we’d like to test sending good required data as well as bad required data to our delegate before hitting the service directly.
The issue we ran into was quite frustrating and it took me some time to figure it out — I actually had to explain the system of tests to my partner before it dawned on me what was going wrong. In order to actually hit the services and get data back, you need to be logged into our client’s system…except this isn’t done through a Flex login, but rather via the larger application’s HTML login in which our smaller app lives (SSO)…once you’re logged in, a cookie is sent back and forth between the client and server…such is the security design of our client’s application framework and there wasn’t any wiggle room to change this.

Change SWF to Open With Browser
Now think about FU4 and how it actually runs the tests (when using Ant and not building and running with FlexBuilder)…it simply opens up a TestRunner.swf in the Flash Player to execute it’s tests…this means no browser wrapper for our SWF and thus no access to cookies…and ultimately no working services in my tests…grrrr.
So here’s a simple solution (on Mac)…open up Finder and locate your TestRunner.swf, right-click on it and select “Get Info”. Find the section “Open with” and change the application to your browser (I use FireFox), but don’t click the button change for all, as we just want to change this for this file and this file only. Voila! Now your TestRunner.swf will run in thr browser when your Ant buld runs and you will have access t cookies (assuming you’ve already logged into the system you need access to in the same browser session).
Dude, Where’s My Chart Labels?
Posted by joes in actionscript, data visualization, flex, flex builder on November 19th, 2009
Wondering where your Flex Chart labels are? Well, you’re not alone. Turns out it may be related to your use of Embedded Fonts and Modules.
Surfacing a charting component in a Module works just fine when not making use of Embedded Fonts. Embed fonts in your main application or the Module itself and Presto! Your labels will disappear.
A number of bug tickets have been opened and closed with Adobe, i.e. http://bugs.adobe.com/jira/browse/FLEXDMV-1883, indicating that the issue was resolved with DMV 3.3.0. Currently using DMV 3.4.0.9271, however, and the problem seems to have re-emerged.
Opening another bug ticket with Adobe and in the meantime commenting out the use of Embedded Fonts.
More to follow…
Headless Flex Builds on EC2 Using Hudson Against Remote SVN Repo on Assembla with FlexPMD
Posted by admin in assembla, data visualization, ec2, flex, flex builder, flexpmd, hudson, svn, tomcat on November 16th, 2009
We’re doing a current project requiring continuous integration. We also maintain the SVN repo. There’s a lot here and you may/may not need all the pieces. We’re specifically doing headless Flex/DataViz Builds on Amazon EC2 Ubuntu with Hudson against a remote SVN repo on Assembla and have thrown in FlexPMD to see what it can add to our process.
First, some stuff I’ll assume you already have and know how to work with:
- EC2 machine running in the Amazon cloud. We’re using one of the Ubuntu disty’s. I’m going to assume you have all the necessary ports open for things like email and such.
- Hudson. We’re using version 1.326. We’ve used other CI tools but find Hudson to be very user friendly. You’ll need to have a servlet container ie Tomcat and you just pop hudson.war in and you’re ready to rock.
- Remote SVN. You can be using a local one, but. We’re using Assembla since it’s got all the stuff we need to do business in one place and it’s simple to use. Time is money.
- Java installed on your server. We’re using version 1.6.0_07
Stuff you’ll end up downloading/installing/configuring:
- Flex SDK
- Flex Dataviz components
- SVN client
- Ant
- Flex Ant
Step 1, Flex
We’re currently building with the latest stable build of Flex 3.4. Get yourself all logged into your EC2 account and let’s roll. I create a flex/3.4 directory and cd to that directory and then get the latest Flex rev. This is the latest URL:
wget http://download.macromedia.com/pub/flex/sdk/flex_sdk_3.4.zip
Let’s get the dataviz components as well since they’re a separate install
wget http://download.macromedia.com/pub/flex/sdk/datavisualization_sdk_3.4.zip
Oh yeah, and if you’re going to be doing unit testing, might as well get that sucker as well
wget http://download.macromedia.com/pub/flex/sdk/automation_sdk_3.4.zip
Great, so we have all the pieces we need so far. You’ll want to unzip and cp these to wherever you keep your software installs on the server. I’m no unix guru, but, near as I could find out, the common location is /opt.
So, create a /opt/flex directory and unzip the flex_sdk_3.4.zip files there. Then, copy the dataviz zip there and unzip it.
cp datavisualization_sdk3.4.zip /opt/flex
cd /opt/flex
unzip datavisualization_sdk3.4.zip
This will extract the following into the SDK 3 installation
- datavisualization.swc into the frameworkslibs folder
- datavisualization__3.0.9147.swz and datavisualization__3.0.9147.swf into the frameworksrsls folder
- datavisualization_rb.swc into the appropriate frameworkslocale<locale> folder
Let’s make sure we put the Flex compiler on the class path. On our server, the default shell is bash. You’re setup may be different, but essentially, you want to find the properties file for you shell (I’m using /root/.bashrc) and add the following line to the bottom of it:
export PATH=/opt/flex/bin:$PATH
Now let’s test it. You may need to log out and then back into your shell. At the command prompt, enter mxmlc and hit return. You should see something like
Loading configuration file /opt/flex/frameworks/flex-config.xml
Error: a target file must be specified
That’s a good error. It means that the Flex compiler is now accessible on your system. If nothing comes back, you’re just at the command prompt, you may not be using the right shell properties file.
In order to build projects that use the dataviz components without having the watermark on your charts and graphs, you’ll need to apply a Flex license to the installation. You do this in the flex-config.xml file located in /opt/flex/frameworks. Towards the bottom of the file you’ll see some commented out xml for doing so:
<licenses>
<license>
<product>string</product>
<serial-number>number</serial-number>
</license>
</licenses>
Step 2, SVN
We are accessing an SVN repo on our Assembla account. The easiest way to make this happen from the EC2 is to just install SVN. So, from the command prompt:
apt-get install subversion
If you run into any errors, I always find it helpful to refresh the list:
apt-get update
If all went well, you should be able to log into your remote repo:
svn –username <your_username> –password <your_password> –no-auth-cache checkout <some_project_name>
If successful, you’re going to have a checked out version of some_project_name in your current directory.
Step 3, Ant
We’re going to be using Ant as our build process. It will called via a Hudson job. Let’s get and install Ant.
apt-get install ant
Once that completes, you should be able to type ant at a command prompt. If it installed successfully, you should see something similar to (unless there happens to be a build.xml file in your current directory):
Buildfile: build.xml
BUILD FAILED
This is good. We now have Ant installed. The only other Ant specific thing we’ll need to do is copy the FlexTasks.jar from your Flex SDK into your new Ant install.
Let’s find where Ant was installed. At a command prompt:
which ant
(which will most likely return)
/usr/bin/ant
Now, navigate to your Flex SDK Ant lib directory. The Flex SDK now contains the flexTasks.jar we need.
cd /opt/flex/an/lib
Now just copy this to the location of your Ant install’s lib directory (typical):
cp flexTasks.jar /usr/share/ant/lib
If you do not copy this file to the lib directory, you must specify it by using Ant’s -lib
option on the command line when you make a project.
Step 4, Setup Hudson Job
Plugins
I’m assuming you have a working familiarity with Hudson. If not, there’s a ton of info via your install directly and on the web. We have a few extra plugins installed. The Violations plugin is useful for code analysis via PMD files if you structure your ant files to use it. The Email Extension gives you a bit more flexibility than the basic email tool.
Configuration
Here’s a look at few items we needed in the Hudon configuration page to get things to work smoothly
Specify the Ant location on your server.
For the Extended E-mail Notification plugin. We’ve defined an email account on our system called hudson. We also use gmail for our corporate email. We’re essentially relaying to gmail which requires SMTP auth and SSL (note: we haven’t entered anything in the default Hudson E-mail section):
Job Setup
Go the usual steps of creating a new job. Here are the pertinent parts.
In Source Code Management, we’ll need to point to our remote SVN. When you click on the “?” next to the Repository URL, you will see the grey box and be able to provide login credentials to your SVN repo and test the connection:
We’re not going to specify any build triggers. The reason is that Assembla gives the ability to access the post-commit hook in SVN via their “Webhook” plugin. In that tool, all we have to do is specify the Hudson job URL and with each check in of code, the project is checked out, built, and success/failure notification sent to our dev group. This is the key to the ‘continuous integration’ aspect of this whole setup.
We do need to tell Hudson to use Ant to do the builds. We have a target in the build.xml file (that is in the root of our Flex project) called main.hudson. To be on the safe side, I’ve specified the full path to the build file. We specify the ant install we configured in the Hudson configuration page earlier. It would probably be helpful to give it more meaningful name like ‘ant_version_x’.
FlexPMD is another great tool we use that profiles your code based upon a bunch of best practices defined by the Flex group at Adobe. You can also specify your own criteria to use in the analysis. It’s worth checking out. Note the format of the XML filename pattern used. It took a while to figure that part out!
We configure the Editable Email Notification accordingly:
And that’s pretty much it. I’ll be pushing up a blog shortly that will walk through the whole ant build used for this project. It uses modules, all sorts of RSLs, FTP, and so on.
Happy Flexing.
RIA Unleashed Boston
If you’re going to be at the RIA Unleashed event in Boston this Friday, November 13, feel free to hit me and the WASI team up for a chat. And not that I’m not looking forward to see all you speakerz, but definitely psyched to hang with Jesse Warden and Andy Powell. See you kids there!
New Mac Magic Mouse Quick Review
Mac Magic Mouse
I had the Mac Mighty Mouse and I liked it, sans the fact that the scroll ball would get all gunked up with dust and shiz from my desk…I was forced to clean the sucker wkly at first and then daily as time went on in order to get it working and god forbid anything mess up my workflow
So I decided to try out the new Mac Magic Mouse and after 2 wks I really, really like it:
- No moving parts = no cleaning!
- No moving parts = harder to break!
- The pointer is laser sharp and extremely accurate…sounds kind of flakey, but I honestly noticed it almost immediately.
- Clearly defined Right-Click Action — I found that the Mighty Mouse was very flakey and I had to be exact with my right-clicks. It seems to work every time with the new Magic Mouse…huge for me!
- The new scrolling action is synonymous with scrolling on the iPhone, as it’s the same technology. Simple finger swipes anywhere on the surface of the mouse now activate scrolling — both horizontal and vertical are supported.
It also does some other cool zooming stuff with finger swiping + some keys, but I don’t use it that much.
The only thing that I found a bit odd was the setup…so I connected my new mouse with bluetooth through system prefs, but the scrolling didn’t work. The key here is to run a software update after the pairing so it picks up the new Mac OS Patch to work with your new Magic Mouse…and I believe I had to reboot as well…the only reason I call it out is b/c Mac didn’t in the directions and they seem to insinuate that it’ll just pair and work.
Overall, one of the better mouses I’ve ever used.







