Growl at the Devel: Using notifications to smooth workflow.

In these times of Agile development, super tight deadlines, and personal multitasking responsibilities that would make the latest Cray Supercomputer weep, every little tool that helps manage your workload is a blessing. Even more so if implementing and using said tool is simple and intuitive.

If you are more than just a casual user of MacOS X, then most likely you have heard of Growl. If you haven't, it is a highly configurable, unobtrusive notification system that gives application developers access to a simple API that they can tie into, instantly enabling notification functionality. For instance, there are add-ons for Firefox and Thunderbird that inform you when your download is finished or you have new email, plugins for iTunes that easily display current track info when the song changes, and even a plugin that updates you what is going on with your character and friends in Second Life.

You may think "This is all well and good, but how does it help me at work?" Well, there is a little known extra that is included with the Growl package (in the Extras folder of all places) called growlnotify. It is a fairly simple and straight forward command line interface for sending Growl notifications. After installing and configuring Growl in your System Preferences, then building and installing growlnotify, open a terminal and try the following:

growlnotify -t "Hello from Growl" -m "Nice to meet you"

If everything is set up correctly, you should see something like this:

(the style and position will depend on how you set your preferences, but you get the idea)

So how is this useful? Well, I was looking for a quick and simple way to get notified whenever a developer made a commit to the Subversion server. Setting up SVN to email me would be a bulky task, and either checking the web interface, GUI front ends, or using the SVN command line tools would have to be an interactive step on my part.

That's when I remembered growlnotify. After a read through of the man page, a quick and dirty shell script, and a little help from my old friend cron, I had pretty much what I needed:


#!/bin/bash

localrep=`dirname $BASH_SOURCE`
URL=`svn info $localrep 2>/dev/null | sed -ne 's#^URL: ##p'`
there=`svn info $URL 2>/dev/null | sed -ne 's#^Last Changed Rev: ##p'`
here=`svn info $localrep 2>/dev/null | sed -ne 's#^Revision: ##p'`
blame=`svn info $URL 2>/dev/null | sed -ne 's#^Last Changed Author: ##p'`

if [ $there -gt $here ] ; then
growlnotify -t "SVN Commit by $blame" -m "Local: $here - Remote: $there"
fi


Elated with the success of my elegantly simple solution, I started thinking up other uses for my new found favorite tool. After a few neat but overall useless and unproductive ideas, it dawned on me.

Builds!

So now that Growl has informed me that there is new code waiting, it's time to update my local source tree, build, and deploy for testing. Depending on what part of the project I'm working on, this process could take anywhere from 5 to 20+ minutes and include a any number of steps and scripts. Sure, I could just keep switching back and forth to the terminal to check if the build is done, but why? I can just end all of my build scripts with one simple line:



growlnotify -t "Build is done" -m "Get to testing"


And with that one line,  I no longer have to babysit a terminal of scrolling text. Now I'm free to spend that time reading the relevant design documents, check the bug tracker, catching up on the progress of other developers, *cough*check Slashdot*cough*, et cetera. When the computer is done doing it's thing, it will inform me without any intervention on my part.

Conclusion

Growl and growlnotify are not huge software packages of paradigm shifting, buzzword bingo winning, manager wowing life changers. They are a pair of simple tools to make your development life just a little bit easier, and are easy to grok with a simple one time read through of the man page. These two examples are just quick and easy ways for you to start working with notifications, there are many more possible ways to utilize these tools in your workflow.

Happy hacking!

Comment

Flex 4: Skinning a Button, Spark Style

Some major changes have been implemented with the introduction of Flex 4. The new framework introduces new methods for skinning, states, layouts and declaring non-visual elements in MXML. There's also a new component set called Spark, which will change the way you think about developing modular components. For this article, we will be designing one of the simplest Flex components: a Button. Through this, I'll be implementing some of the major changes so that you can see how it's applied.

Beginning the Button

To start, pop open Flash Builder 4 and create a new Application, making sure you're using the new Flex 4.0 framework.  I named my project SparkButtonDemo.  Once the project has been created, you'll be presented with your Application's MXML file.  You may already notice some differences; Your main Application tag is no longer mx:Application, but s:Application, and there is a new child tag called fx:Declarations.  The simple change in namespace for the Application tag is to indicate that we're no longer using the mx component set, while the fx:Declarations tag is used for any non-visual children (data providers, FileReference objects, services...anything you cannot see).

To start creating our new Button, let's create a new MXML Component called SparkButton.  The component should extend spark.components.Button.

Skinning the Button

The new Spark component set was designed from the ground up to make skinning components easier and more modular.  To start skinning your button, you must create another MXML Component that extends from the spark Skin component (spark.skins.SparkSkin).  Once this class is created, you can start adding some skin elements to it.  The first thing that needs to be added to your skin is a metadata declaration describing the type of component we are skinning.  This looks a little something like this:

<fx:Metadata>
[HostComponent("spark.components.Button")]
</fx:Metadata>

After adding this code, you will see 4 errors pop up in your Problems window.  Flash Builder is trying to tell you that you haven't defined the required states for a Button.  So let's add 4 states: up, over, down, and disabled.  You should have something that looks like this so far:

<?xml version="1.0" encoding="utf-8"?>
<s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx">
  <fx:Metadata>
    [HostComponent("spark.components.Button")]
  </fx:Metadata>
  <s:states>
    <s:State name="up"/>
    <s:State name="over"/>
    <s:State name="down"/>
    <s:State name="disabled"/>
  </s:states>
</s:SparkSkin>

Next, we will add some graphics to our Button.  For this example we're going to keep it simple, and add a rectangle with a 2 pixel border, and a label control for the button's text.  First, let's add the rectangle:

<s:Rect width="100%" height="100%">
	<s:stroke>
		<s:SolidColorStroke color="0x000000" weight="2"/>
	</s:stroke>
	<s:fill>
		<s:SolidColor color="0xCCCCCC"/>
	</s:fill>
</s:Rect>

Graphics are defined using the new FXG format.  It is similar to SVG, in that it is defined entirely in XML.  This new format is what allows the interchange between Flash Catalyst and Flash Builder 4 (and presumably Flash CS5).

Next, let's add the label control to display the Button's text.  The label must have an id of "labelDisplay" for this to work properly.  This is because the Button classes default skin expects a label control called labelDisplay (http://help.adobe.com/en_US/FlashPlatform//reference/actionscript/3/spark/skins/spark/ButtonSkin.html).  It should be noted that every skinnable component within the Spark framework has a default skin.  To replace this skin, you must implement all of the required properties.  Leaving the label control out, or not naming the label control correctly, does not cause any errors.  You simply won't see the text on the Button.  With that said, here's our label control:

<s:Label id="labelDisplay" width="100%" height="100%" textAlign="center" verticalAlign="middle" fontSize="12"/>

Assigning the label's width and height to 100%, while setting textAlign and verticalAlign both to their center values, will make sure the label is centered within our button.

Viewing the Button

In your Button's MXML code, you must define the skinClass it is going to use.  This looks something like this:

<?xml version="1.0" encoding="utf-8"?>
<s:Button xmlns:fx="http://ns.adobe.com/mxml/2009" 
		  xmlns:s="library://ns.adobe.com/flex/spark" 
		  xmlns:mx="library://ns.adobe.com/flex/mx"
		  skinClass="com.ninem.SparkButtonSkin">
</s:Button>

Place your newly created button on your main application, set the width/height and label properties, and hit go.  Your code should look something like this:

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
			   xmlns:s="library://ns.adobe.com/flex/spark" 
			   xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600" xmlns:ninem="com.ninem.*">
	<ninem:SparkButton width="100" height="50" label="Hello"/>
</s:Application>

You should see your label control in the upper left hand corner of your screen.  It works, but it has no states at the moment.  Let's work on that:

Reacting to Mouse Events

Let's define some simple styling to react to the mouse events a common button expects.  When we roll over, we'll make the text get a little larger.  And when the button's enabled property is set to false, let's make the whole button's alpha property drop to 0.5.

To make the text get a little larger when we rollover, it's as easy as adding one more property to our label in the skin.

<s:Label id="labelDisplay" width="100%" height="100%" textAlign="center" verticalAlign="middle" fontSize="12" fontSize.over="16"/>

You'll see that I added fontSize.over="16."  This will override the fontSize whenever the button is in it's over state.

To set the button's alpha to 0.5 when it's disabled, we add a property to the root of the skin tag.  "alpha.disabled" will set the alpha of the whole button when it enter it's disabled state.

At this point, your skin should look something like this:

<?xml version="1.0" encoding="utf-8"?>
<s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009" 
			 xmlns:s="library://ns.adobe.com/flex/spark" 
			 xmlns:mx="library://ns.adobe.com/flex/mx"
			 minWidth="60" minHeight="20" alpha.disabled="0.5">
	<fx:Metadata>
		[HostComponent("spark.components.Button")]
	</fx:Metadata>
	<s:states>		
		<s:State name="up"/>
		<s:State name="over"/>
		<s:State name="down"/>
		<s:State name="disabled"/>
	</s:states>
	<s:Rect width="100%" height="100%">
		<s:stroke>
			<s:SolidColorStroke color="0x000000" weight="2"/>
		</s:stroke>
		<s:fill>
			<s:SolidColor color="0xCCCCCC"/>
		</s:fill>
	</s:Rect>
	<s:Label id="labelDisplay" width="100%" height="100%" textAlign="center" verticalAlign="middle" fontSize="12" fontSize.over="16"/>
</s:SparkSkin>

So as you can see, skinning has drastically changed in Flex 4.  It may take some time getting used to, but it appears that the changes are for the better.  Your skins are now more modular, and more separated from your "business logic."

To get all of the code associated with this article, point your svn client here: https://code.9mmedia.com/svn/public/SparkButtonDemo/trunk/

Comments

Asynchronous Networking on iPhone, Thanks NSOperation!

With the convenience of NSURLConnection, it is rarely difficult for an app to load data from somewhere on the Internet, especially using simple GET requests. Loading large amounts of data efficiently, however, can be quite challenging. Although there are a number of solutions available to keep the application responsive while some data is downloaded, today we’ll discuss how using simple asynchronous network operations can make your app much more responsive and efficient.

An example of a very bad way to do this would be to use the sendSynchronousRequest method:

  // process some stuff and we need to download an image
  NSData* imageData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
  // process the image data

While certainly easy, this approach has the important and massive limitation that it will completely block the UI while the image data is downloading. If the image is large, or the network is slow, this may lead users to believe that their application has crashed or frozen.

This leads us to individual threads for our network operations. Since this article is aimed at developing for the iPhone, which is currently limited to a single processor with a single core, we don’t see very much gain. In fact, depending on what these background threads are doing, and how you’re managing them, they may even be very detrimental to the performance of your application! Since we are not going to be using background threads, there is much less context switching that will have to be done and we will already see a performance gain.

The other option we have for managing our URLConnections is to use the connection in an asynchronous manner. This is the default type of request when we create a new NSURLConnection:

  NSURLConnection* newConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self];

When we do this, the network connection automatically schedules the downloading of all the data with the runloop and will send callbacks to a delegate as the download progresses. These callbacks signal us when the connection gets a response from the server, when new data is available and when the download has completed. It also lets us know if there was any error establishing the connection. Using asynchronous operations mitigates all our concerns with either blocking the UI and with creating lots of threads and all the issues that come with multiple threads. However, there is a downfall—managing all these network connections!

That brings us to NSOperation and NSOperationQueue—these classes make it very easy to separate and manage tasks (for example, the downloading of images from a central server). Since network-downloads are high-latency tasks, they make great candidates for migration back to the main thread. However, we still don’t want to block the application UI while images are downloading, so we have to make sure that all our network operations run asynchronously. Also, since we’re using an operation queue, it is very easy to cancel operations in progress and to adjust the number of operations we allow to execute in parallel when the user’s bandwidth changes (e.g., when the WiFi becomes available on the device).

So now for some code. The first thing we need is a subclass of NSOperation. Since we are going to run the operation on the main thread, we have to make this a concurrent operation. That signals the NSOperationQueue to start the operation on the same thread that added it to the queue. For non-concurrent operations, NSOperationQueue will spawn a new thread and run the operation in that thread context (which we definitely want to avoid on the phone).

For this example, we will call our operation PictureDownloadOperation and define a few properties. We will create an error property that we can query later if the operation fails for some reason and a UIImage property that will be set when the operation completes. I’ll also add a new designated initializer that takes the URL, making using the operation simple and versatile.

Here is the full interface for the new operation:

@interface PictureDownloadOperation : NSOperation
{
  // New properties
  NSError* error;
  UIImage* image;
 
  // In concurrent operations, we have to manage the operation’s state
  BOOL executing_;
  BOOL finished_;
 
  // The actual NSURLConnection so that we can cancel if it we need to
  NSURL* connectionURL_;
  NSURLConnection* connection_;
  NSMutableData* data_;
}
 
@property(nonatomic, readonly, retain) NSError* error;
@property(nonatomic, readonly, retain) UIImage* image;
 
- (id)initWithURL:(NSURL*)url;

When creating non-concurrent operations (the ones that run in their own thread), all we have to do is override NSOperation’s main method. Concurrent operations aren’t really any harder, but we do have to do a little more set-up work. Instead of overriding main, we will override start and a few other methods.

So the methods we must implement for our concurrent operation to work are:
- start
- isConcurrent
- isExecuting
- isFinished

For the isConcurrent method, all we have to do is simply return YES and we’re done:

- (BOOL)isConcurrent
{
  return YES;
}

The other two state methods, isExecuting and isFinished are just as simple to write, basically they will just return the values of executing_ and finished respectively. It’s important to remember, however, that these two methods must be key-value-observing compliant, so when we change either variable, we must send the appropriate willChangeValueForKey: and didChangeValueForKey: messages.

The meat of the operation happens in the start method, where we kick-off the asynchronous download of the image data. The most important thing here is that we check to make sure that the operation has not been cancelled before we start. If it has, there is nothing for us to do. For convenience, I have created another method named done that cleans up the URL connection and sets the operation to finished and not executing.

Here is the start method:

- (void)start
{
  // Ensure this operation is not being restarted and that it has not been cancelled
  if( finished_ || [self isCancelled] ) { [self done]; return; }
 
  // From this point on, the operation is officially executing--remember, isExecuting
  // needs to be KVO compliant!
  [self willChangeValueForKey:@“isExecuting”];
  executing_ = YES;
  [self didChangeValueForKey:@“isExecuting”];
 
  // Create the NSURLConnection--this could have been done in init, but we delayed
  // until no in case the operation was never enqueued or was cancelled before starting
  connection_ = [[NSURLConnection alloc] initWithRequest:[NSURLRequest requestWithURL:connectionURL_]
                                                                                          delegate:self];
}

The operation should also implement all the necessary NSURLConnectionDelegate methods. If we encounter an error, we will set the error property. If all the data loads successfully, we can just set the image property. Anyone interested in knowing when the images have loaded can simply observe isFinished on the operation and all of this can be easily managed with a network queue.

Once set up, the loads will be much more efficient than using a separate thread, simple to manage, and still won’t block or interrupt the UI. For the full source code and a simple example using the operation, see our SVN repository at http://code.9mmedia.com/svn/public/iphone/async-network-example/.

Comments

Managing Multiple Databases with Spring and Hibernate

We recently had the need to use a couple different databases in the same web app.  These are completely separate databases, not shards with matching schemas.  What I thought would be a simple task turned into a really annoying day.  There's not a ton of (working) documentation around, so I thought I'd take a few minutes to explain how we pulled this off.  Just because I care.

Quick disclaimer though -- we haven't used this in production yet, but it seems to be working fine during development and load testing.  I welcome any suggestions from people who have done this differently.  As for versions, we're using Spring 2.5.6, Hibernate 3.3.1 and Atomikos 3.5.8.  You can download the latest version of Atomikos Transaction Essentials from their site, or use their maven repository at http://repo.atomikos.com.

The basic idea here is pretty simple.  You define multiple datasources, wire them into the correct DAOs, and then use whatever DAOs are necessary in your service layer.  The thing that makes this difficult is transaction management.  In order to do this in a transactional manner, we discovered that we had to use JTA.  We're not using an application server that supports JTA, so that meant looking into a standalone JTA solution.  There are a couple that pop up when searching for this, JTOM and Atomikos.  Out of the two, we chose Atomikos for various scientific reasons which I won't bore you with (we flipped a coin), so that's what I'll be focusing on here.

Once we started down the JTA path, we realized that we also needed a XA datasource, so there were a lot of changes compared to our previously basic set-up of datasource + transaction manager.  So let's get down to business and take a look at some of that pretty and succinct Spring configuration we've all come to know and love.  We created a Spring application context file for our persistence layer to house all of this loveliness.

First, let's look at the datasource configs:

<bean id="dataSourceOne" class="com.atomikos.jdbc.AtomikosDataSourceBean">
        <property name="uniqueResourceName"><value>dataSourceOne</value></property>
        <property name="xaDataSourceClassName"><value>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</value></property>
        <property name="xaProperties">
                <props>
                        <prop key="user">${ds1.jdbc.username}</prop>
                        <prop key="password">${ds1.jdbc.password}</prop>
                        <prop key="url">${ds1.jdbc.url}</prop>
                        <prop key="allowMultiQueries">true</prop>
                        <prop key="pinGlobalTxToPhysicalConnection">true</prop>
                        <prop key="autoReconnect">true</prop>
                        <prop key="autoReconnectForConnectionPools">true</prop>
                        <prop key="autoReconnectForPools">true</prop>
                </props>
        </property>
        <property name="maxPoolSize" value="${ds1.pool.max.size}" />
        <property name="minPoolSize" value="${ds1.pool.min.size}" />
        <property name="maxIdleTime" value="${ds1.pool.max.idle.time}" />
        <property name="testQuery" value="${ds1.pool.preferred.test.query}" />
        <property name="reapTimeout" value="0" />
</bean>
 
<bean id="dataSourceTwo" class="com.atomikos.jdbc.AtomikosDataSourceBean">
        <property name="uniqueResourceName"><value>dataSourceTwo</value></property>
        <property name="xaDataSourceClassName"><value>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</value></property>
        <property name="xaProperties">
                <props>
                        <prop key="user">${ds2.jdbc.username}</prop>
                        <prop key="password">${ds2.jdbc.password}</prop>
                        <prop key="url">${ds2.jdbc.url}</prop>
                        <prop key="allowMultiQueries">true</prop>
                        <prop key="pinGlobalTxToPhysicalConnection">true</prop>
                        <prop key="autoReconnect">true</prop>
                        <prop key="autoReconnectForConnectionPools">true</prop>
                        <prop key="autoReconnectForPools">true</prop>
                </props>
        </property>
        <property name="maxPoolSize" value="${ds2.pool.max.size}" />
        <property name="minPoolSize" value="${ds2.pool.min.size}" />
        <property name="maxIdleTime" value="${ds2.pool.max.idle.time}" />
        <property name="testQuery" value="${ds2.pool.preferred.test.query}" />
        <property name="reapTimeout" value="0" />
</bean>

As you see, we have two nearly identical datasources, each with a different bean id, uniqueResourceName, and property placeholder names. The uniqueResourceName property is important in this case, as you'll need a unique name for all of the datasources that are going to be a part of this JTA transaction manager. The property placeholders are filled in the usual way, using Spring's PropertyPlaceholderConfigurer.

Also, if you look at the properties of the AtomikosDataSourceBean, you'll notice that there is another property called poolSize. We did a bit of testing with this and discovered that it's used to set a fixed sized pool, and when set the min/max pool size settings will be ignored. Unfortunately with Atomikos this doesn't seem to be documented anywhere, so it's all trial and error.

For each JDBC datasource, we need a matching hibernate SessionFactory, like so:

<bean id="sessionFactoryOne" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        <property name="dataSource">
                <ref bean="dataSourceOne" />
        </property>
        <property name="annotatedClasses">
                <list>
                        ...
                </list>
        </property>
        <property name="hibernateProperties">
                <props>
                        ...
                        <!-- atomikos -->
                        <prop key="hibernate.current_session_context_class">jta</prop>
                        <prop key="hibernate.transaction.factory_class">
                            com.atomikos.icatch.jta.hibernate3.AtomikosJTATransactionFactory
                        </prop>
                        <prop key="hibernate.transaction.manager_lookup_class">
                                com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup
                        </prop>
                </props>
        </property>
...
</bean>
 
<bean id="sessionFactoryTwo" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        <property name="dataSource">
                <ref bean="dataSourceTwo" />
        </property>
        <property name="annotatedClasses">
                <list>
                        ...
                </list>
        </property>
        <property name="hibernateProperties">
                <props>
                        ...
                        <!-- atomikos -->
                        <prop key="hibernate.current_session_context_class">jta</prop>
                        <prop key="hibernate.transaction.factory_class">
                            com.atomikos.icatch.jta.hibernate3.AtomikosJTATransactionFactory
                        </prop>
                        <prop key="hibernate.transaction.manager_lookup_class">
                                com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup
                        </prop>
                </props>
        </property>
...
</bean>

Note the the only thing that changes across those configs is the bean id and the dataSource property, which should refer to the correct datasource bean.

Now, we create HibernateTemplates for each SessionFactory.

<bean id="hibernateTemplateOne" class="org.springframework.orm.hibernate3.HibernateTemplate">
        <property name="sessionFactory" ref="sessionFactoryOne"/>
</bean>
 
<bean id="hibernateTemplateTwo" class="org.springframework.orm.hibernate3.HibernateTemplate">
        <property name="sessionFactory" ref="sessionFactoryTwo"/>
</bean>

Again, the only thing that changes across those two is the bean id and the sessionFactory property.

And now for the Atomikos transaction management. This is pretty much straight from their documentation. Note that transactionTimeout is in seconds here, not milliseconds.

<bean id="AtomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method="close">
        <property name="forceShutdown" value="true" />
<!-- this prop is in seconds -->
        <property name="transactionTimeout" value="300"/>
</bean>
 
<bean id="AtomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">
<!-- this prop is in seconds -->
        <property name="transactionTimeout" value="300" />
</bean>
 
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
        <property name="transactionManager" ref="AtomikosTransactionManager" />
        <property name="userTransaction" ref="AtomikosUserTransaction" />
        <property name="transactionSynchronizationName" value="SYNCHRONIZATION_ON_ACTUAL_TRANSACTION" />
</bean>

This seems to work with all the flavors of Spring's transaction management, but we use the handy annotations, so our context file also specifies:

<tx:annotation-driven />

Finally, by default (at least in our version), Atomikos expects a conf file for some other settings. It is called jta.properties, and it needs to be at the root of your classpath. Ours looks like this:

## Props for Atomikos JTA
com.atomikos.icatch.service = com.atomikos.icatch.standalone.UserTransactionServiceFactory
 
# max active transactions
com.atomikos.icatch.max_actives = 100
 
# tx logs
com.atomikos.icatch.log_base_dir = /var/log/tx/
 
# output logs
com.atomikos.icatch.output_dir = /var/log/
com.atomikos.icatch.console_log_level = WARN
 
com.atomikos.icatch.automatic_resource_registration=true
 
com.atomikos.icatch.serial_jta_transactions=false

These are described in the Atomikos docs, but max_actives is the max number of open transactions allowed, so you may want to tweak this value. Also, the log_base_dir is important as it is where Atomikos writes transactions in case of system failure. Their site mentions setting that to a reliable SAN or RAID storage, so you can read more about that if you'd like.

And that's about it. We have an AbstractDAO for each of our HibernateTemplates, and we just wire the correct one in. You can either Autowire by name, or by manually defining those beans in your Spring config and injecting the necessary bean.

I hope that helps anybody looking to do this, and I'll be sure to write another post if we need to tune/tweak/run away from using this once we pound on it a bit more.

Comments

Handling circular dependencies in Swiz Framework

Swiz is an amazing framework. I was playing around with it this weekend converting a simple Cairngorm project. Swiz handled all autowiring without any problems, until I had to access autowired bean from getter of another autowired bean, that's where I ran into the notorious TypeError: Error #1009: Cannot access a property or method of a null object reference. The problem is that in this case there is no way that Swiz could know that injected property is using another autowired bean in its getter. Note that I was using version 0.6.4-flex3, in latter versions this issue can be fixed or better work around found.

Here are snippets from my classes:

When swiz autowires beans in BeanLoader, LoginPresentationModel comes before ApplicationModel, and when it tries to set up binding between LoginPresentationModel.languageToTranslate and ApplicationModel.languageToTranslate flex throws NPE, as a result of ApplicationModel.so being null at this point. If ApplicationModel came first in the list of candidates for autowiring then I wouldn't get this NPE.

There are couple solutions for this problem:

The first one is to add a condition to the property getter that returns some default value if "so" is null. That would leave the binding to be created.

This solution just doesn't look right.

Another way, which I'm using at least for now, is to manually specify the bean to inject.

In Beans.mxml

You can also implement IInitializingBean and let the controller initialize SO persisted data in the IInitializingBean initialize method.
It will be called after dependencies have been injected. This is much cleaner anyway and keeps the model lightweight.

Comment