tag:blogger.com,1999:blog-4091084264489408322024-03-13T04:50:27.475+00:00Flex in the CityRoadershttp://www.blogger.com/profile/15030429903672650150noreply@blogger.comBlogger49125tag:blogger.com,1999:blog-409108426448940832.post-42640664287480404732014-02-22T09:28:00.000+00:002014-02-22T09:28:12.713+00:00Layout ExperimentsI was digging through my SVN repository and found some old code I was working a long time ago.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://giles.roadnight.name/flex/LayoutExperiments/LayoutExperiments.html" target="_blank"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhGDnDy10CaK-XGMdLHd6MXKiQde57vxIUnry6RhZQ_BcIoj4g_3d2ydHbmYQuVjIwlUJPo5onF6AyBbatubWBLLz70YSrcIfmN0RwAL-BJMhORSsQ6qLgCDz5-q8RjpqT2nJcLQ2Lf76s/s1600/Capture.JPG" height="459" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
This was a project I was working on to create some cool layout effect but without having to re-write them for each different layout that you wanted to use.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
In this app there is a DataGroup with a load of renderers. The DataGroup has a TweenLayout. The TweenLayout then has it's own layout that does the actual laying out.</div>
<div class="separator" style="clear: both; text-align: left;">
If you switch the layouts this changes the layout used by TweenLayout and it tweens between them using the duration and easing function that you select. A tween also occurs if you resize your browser.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
The really nice thing about this approach is that it will work with any layout - even the ones that you write yourself. The layouts I use here are just the standard flex ones with no changes made at all.</div>
<br />
I was also working on a DragLayout which would allow you to drag items around the layout. The idea was that the DataGroup would have a TweenLayout containing a DragLayout containing a TileLayout (or whatever you want).<br />
As you drag an item around the layout of the other items would be adjusted on the fly by the DragLayout and the TweenLayout would then tween the panels to their new position. The end result would work as it does on iOS when dragging icons around your home screen.<br />
Again the nice thing is that you can use the DragLayout and TweenLayout or just one and use them with whatever root layout you want. Composition over inheritance all the way!<br />
I never got the DragLayout finished which is a shame, maybe I'll have another look at it at some point.<br />
<br />
You can have a play <a href="http://giles.roadnight.name/flex/LayoutExperiments/LayoutExperiments.html" target="_blank">here</a>.<br />
<br />Roadershttp://www.blogger.com/profile/15030429903672650150noreply@blogger.com0tag:blogger.com,1999:blog-409108426448940832.post-78476811440694635412011-07-16T11:34:00.001+01:002011-07-16T11:34:04.356+01:00Preventing browser from closing your Flex Application<p>At work recently a bug came my way saying that if a user closed the browser mid way through a certain process it would corrupt the database and not allow the user to re-open that task.</p> <p>Now obviously there are a few issues here:</p> <ul> <li>closing the browser did nothing to the database, it just meant that the flex application was not given the opportunity to clean up and the data on the server was left in a state that could not be re-loaded</li> <li>whatever calls a client makes to the server the database should never get corrupted and should always be in a re-loadable state!</li> </ul> <p>Easy then, just pass the bug to the java team!</p> <p>There has been a long standing nice to have task though that we prompt a user when they try to close the browser when they have unsaved data. This bug made it seem like a good idea to look into this.</p> <p>I knew the basics behind this (use JavaScript to call a flex function) but have never actually done it. I also knew that there was a way of having the flex app inject the JavaScript into the HTML page. I did a bit of googleing and found these 2 bog posts:</p> <ul> <li><a href="http://flexblog.faratasystems.com/2006/12/17/prompting-user-on-close-of-application-flex-way" target="_blank">Prompting User on Close of Application: Flex Way</a></li> <li><a href="http://cookbooks.adobe.com/post_Inject_JavaScript_code_in_html_wrapper_from_Flex_A-17157.html" target="_blank">Inject JavaScript code in html wrapper from Flex/ActionScript</a></li> </ul> <p>And from what I learnt I came up with this:</p> <ul> <li><a href="http://giles.roadnight.name/flex/JavascriptInjection/index.html" target="_blank">JavascriptInjection</a> <br />(view source enabled)</li> </ul> <p>The way this works is that when you try to close the browser the onbeforeunload event is fired. This calls the JavaScript function confirmClose which in turn calls the ActionScript function getCloseConfirmMessage. We allow JavaScript to call this function by calling </p> <p>ExternalInterface.addCallback( "getCloseConfirmMessage", closeConfirmMessage )</p> <p>within our flex app. This flex function either returns a message to display in the browser dialogue box (the reason why you can’t close the browser for example) or null if you are allowed to close the browser – in which case the browser just closes with no confirm box.</p> <p>I really like the fact that all this code is inside the swf. I don’t have to make sure that I am deploying the correct html file along side my swf. Any html file will work.</p> <p>The app I link to above is just an example of how to get it to work. In the real application I have put all of this in a parsley managed class. Parsley is used to dispatch a cancellable event. Any area of the app that has unsaved data for example can cancel the event and provide a message. This message is then returned to JavaScript to be displayed.</p> <p>I have also added a function call that gets fired when the browser is actually closed. Again this fires a Parsley message and anything that is interested can use this to tidy up – for example close streams that the app is subscribed to.</p> <p>Thanks to the 2 guys who wrote the 2 blog posts above.</p> Roadershttp://www.blogger.com/profile/15030429903672650150noreply@blogger.com3tag:blogger.com,1999:blog-409108426448940832.post-648810764419343582011-07-02T08:27:00.001+01:002011-07-02T08:27:43.670+01:00Spark DataGrid slow?<p>I am currently in the process of writing a little Air app for myself. I doubt it will be any use to anyone else but I am enjoying writing it and it will be useful for me.</p> <p>The app collects data (ok, my weight!) and displays it in a graph over time. I can also add targets and plots the target weight against actual – you get the idea.</p> <p>The app uses charts and a DataGrid for this.</p> <p>I want to also build the app for mobile so that I use it on my phone and this gives me a bit of a problem. Adobe recommend not to use the spark <a href="http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/spark/components/DataGrid.html" target="_blank">DataGrid</a> in mobile apps and does the same for the charts.</p> <p>In the desktop app that I am working on at the moment the line chart is super fast but I have been very disappointed in the performance of the DataGrid. At the moment I have ONE row in the DataGrid with 5 columns.</p> <p>It takes 300 ms to create this!</p> <p>What’s even worse is that after it’s created it still takes 150 ms to show the grid again after the view is hidden.</p> <p>How can the performance be SO bad? Any suggestions about what else I can use? Has anyone else found this?</p> <p>This is on Flex 4.5.0 build 20967 running in debug mode.</p> Roadershttp://www.blogger.com/profile/15030429903672650150noreply@blogger.com1tag:blogger.com,1999:blog-409108426448940832.post-23495557079229608552011-01-30T19:16:00.001+00:002011-01-30T19:20:30.512+00:00A Guide to Test Driven Development in Flex – Part 3: Implementing the Class<p>At the end of <a href="http://blog.giles.roadnight.name/2011/01/guide-to-tdd-in-flex-step-2-writing.html" target="_blank">part 2</a> we had completed all of our unit tests and most of them were failing:</p> <p><img style="display: block; float: none; margin-left: auto; margin-right: auto" src="http://lh6.ggpht.com/_Ac-KtmUjGx8/TUVa7pEmyhI/AAAAAAACrcQ/BPYhHvb7BQ4/s400/failingCompletedTests.JPG" /></p> <p>We can now go ahead and complete the class implementation and make sure all these tests pass. Lets concentrate on the first test we wrote that is failing – popupOpensOnStartSymbol. <br />This test asserts that when the user types the startSymbol the PM opens the popup. At the moment this test is failing:</p> <p><img style="display: block; float: none; margin-left: auto; margin-right: auto" src="http://lh6.ggpht.com/_Ac-KtmUjGx8/TUWMGSDn9GI/AAAAAAACrcc/NYhJfDwYVs8/s400/popupOpensOnStartSymbol1.JPG" /></p> <p>To fix this we add the minimum amount of code to the SUT to make this test pass:</p> <script type="syntaxhighlighter" class="brush:as3"><![CDATA[public function textEntryHandler( enteredText : String ) : void<br />{<br /> _showAutoCompletePopup = true;<br />}]]></script> <p>We now run the test again and find that it is still failing:</p> <p><img style="display: block; float: none; margin-left: auto; margin-right: auto" src="http://lh5.ggpht.com/_Ac-KtmUjGx8/TUWMGiXpuzI/AAAAAAACrcg/EzU5d7l-Zoc/s400/popupOpensOnStartSymbol2.JPG" /></p> <p>So we add a bit more code to the SUT:</p> <script type="syntaxhighlighter" class="brush:as3"><![CDATA[public function textEntryHandler( enteredText : String ) : void<br />{<br /> _showAutoCompletePopup = true;<br /> <br /> dispatchEvent( new Event( SHOW_AUTO_COMPLETE_POPUP_CHANGE ) );<br />}]]></script> <p>And now when we run the test it passes:</p> <p><img style="display: block; float: none; margin-left: auto; margin-right: auto" src="http://lh5.ggpht.com/_Ac-KtmUjGx8/TUWNVLjL-dI/AAAAAAACrcs/tqwPe8I5DXE/s400/popupOpensOnStartSymbolPass.JPG" /></p> <p>However one of the tests that was previously passing is now failing – popupRemainsClosedNonStartSymbol:</p> <p><img style="display: block; float: none; margin-left: auto; margin-right: auto" src="http://lh4.ggpht.com/_Ac-KtmUjGx8/TUWN_Gfu-LI/AAAAAAACrc0/BFytj28Og6I/popupRemainsClosedNonStartSymbol.JPG" /></p> <p>We are now getting the binding event firing even we don’t type the startSymbol. This is easily fixed:</p> <script type="syntaxhighlighter" class="brush:as3"><![CDATA[public function textEntryHandler( enteredText : String ) : void<br />{<br /> if( enteredText == startSymbol )<br /> {<br /> _showAutoCompletePopup = true;<br /> <br /> dispatchEvent( new Event( SHOW_AUTO_COMPLETE_POPUP_CHANGE ) );<br /> }<br />}]]></script> <p>And we can see that popupOpensOnStartSymbol still passes and now popupRemainsClosedNonStartSymbol passes as well.</p> <p><img style="display: block; float: none; margin-left: auto; margin-right: auto" src="http://lh5.ggpht.com/_Ac-KtmUjGx8/TUWO1QR2B7I/AAAAAAACrdA/RRwE3kXcM7o/popupTestsFixed.JPG" /></p> <p>It is important to fix the tests in this way. It would certainly be possible to just implement that one method in one go and have both tests pass straight away. Had we done that however we would not know if we had written our tests correctly. Having gone through this process we have now verified that if the SUT does not dispatch a binding event the test fails. We have have also verified that if the model dispatches a binding event when it is not supposed to the popupRemainsClosedNonStartSymbol test fails. Implementing the class in this way tests our tests.</p> <p>Using this process I will implement the rest of the functionality for the model. When complete you end up with <a href="http://giles.roadnight.name/flex/AutoCompletePopup/viewsrc/srcview-step3/index.html" target="_blank">this</a>.</p> <p>That’s the end of my guide to Test Driven Development. It’s not as strict nor has quite as many steps as some of the other methods I have seen but it works for me. I believe that developing in this way produces much better code that is easily maintainable any much less fragile and can be quicker.</p> <p>If you have any feedback please let me know in the comments.</p> Roadershttp://www.blogger.com/profile/15030429903672650150noreply@blogger.com0tag:blogger.com,1999:blog-409108426448940832.post-6441332568921026052011-01-30T11:05:00.001+00:002011-01-30T19:17:21.662+00:00A Guide to Test Driven Development in Flex – Part 2: Writing The Unit Tests<p>In <a href="http://blog.giles.roadnight.name/2011/01/guide-to-tdd-in-flex-step-1-defining.html" target="_blank">part 1</a> of this series we defined the public properties on the class we’re testing (referred to as the System Under Test or SUT) and wrote some empty unit tests. You can see the code <a href="http://giles.roadnight.name/flex/AutoCompletePopup/viewsrc/srcview-step1/index.html" target="_blank">here</a>. <br />When we run these empty unit tests un-surprisingly they all fail:</p> <p><img style="display: block; float: none; margin-left: auto; margin-right: auto" src="http://lh5.ggpht.com/_Ac-KtmUjGx8/TUU4WyyU4-I/AAAAAAACrbk/T6uPTGt7A20/failingTests.JPG" /></p> <p>And they all give the same failure trace:</p> <p><img style="display: block; float: none; margin-left: auto; margin-right: auto" src="http://lh6.ggpht.com/_Ac-KtmUjGx8/TUU6OlIqwgI/AAAAAAACrb8/8oQ1A7gnqyg/failureTrace.JPG" /></p> <p>It is now time to start implementing these test methods but before we do that we need to do a bit of setup. For example rather than creating a new model to test in each test we can just have a private variable that will always be available for all the tests:</p> <p><script type="syntaxhighlighter" class="brush:as3"><![CDATA[private var _model : AutoCompletePM = new AutoCompletePM();]]></script> <br />(I use an underscore to signify a private variable)</p> <p>Now that we have an instance of the model to test we can start defining what each test will check for. The first test – testAutoCompletePM simply tests that the model is in the state that we expect after construction. All we need to do for this test is assert that the showAutoCompletePopup property is false:</p> <script type="syntaxhighlighter" class="brush:as3"><![CDATA[[Test]<br />public function testAutoCompletePM() : void<br />{<br /> assertFalse( "showAutoCompletePopup", _model.showAutoCompletePopup );<br />}]]></script> <p>The string in quotes is just the message that will displayed in the error. It lets us know what property we are expecting to be false.</p> <p>The next test popupOpensOnStartSymbol is a bit more involved. We want to check that when the user types the start symbol that the showAutoCompletePopup is set to true and that the binding fires. We’ll probably want to use the same starting symbol in all these tests. So that we don’t have to set it each time we can do this in a setup function:</p> <script type="syntaxhighlighter" class="brush:as3"><![CDATA[private static const START_SYMBOL : String = "@";<br /><br />[Before]<br />public function setup() : void<br />{<br /> _model.startSymbol = START_SYMBOL;<br />}]]></script> <p>The static constant means that we are not using magic strings in our tests. We can use the same static when we test the functionality of the class as we do here in the second test – popupOpensOnStartSymbol:</p> <script type="syntaxhighlighter" class="brush:as3"><![CDATA[[Test]<br />public function popupOpensOnStartSymbol() : void<br />{ <br /> _model.textEntryHandler( START_SYMBOL );<br /> <br /> assertTrue( "showAutoCompletePopup", _model.showAutoCompletePopup );<br />}]]></script> <p>This test is nearly complete but we need to test that the binding event is dispatched as well. As this is a read only property we will use a named bindable and dispatch a custom event type. Event types should always be constants so that we don’t use magic strings. We can define this constant in the SUT but as it is just for binding we don’t want to make it public. Nothing will ever add an event listener for this type. If it is private though the test will not be able to assert that the event is dispatched. <br />Because of this I use the internal namespace for these binding event constants. This means that most classes can’t see it but that tests that are in the same package will be able to see it:</p> <script type="syntaxhighlighter" class="brush:as3"><![CDATA[internal static const SHOW_AUTO_COMPLETE_POPUP_CHANGE : String = "showAutoCompletePopupChange";]]></script> <p>We can then update our test to make sure that this event is dispatched when the popup is supposed to open:</p> <script type="syntaxhighlighter" class="brush:as3"><![CDATA[[Test( async )]<br />public function popupOpensOnStartSymbol() : void<br />{ <br /> Async.proceedOnEvent( this, _model, AutoCompletePM.SHOW_AUTO_COMPLETE_POPUP_CHANGE, 50 );<br /> <br /> _model.textEntryHandler( START_SYMBOL );<br /> <br /> assertTrue( "showAutoCompletePopup", _model.showAutoCompletePopup );<br />}]]></script> <p>In the next test – popupRemainsClosedNonStartSymbol we need to make sure that showAutoCompletePopup remains false and that the binding event is not dispatched:</p> <script type="syntaxhighlighter" class="brush:as3"><![CDATA[[Test( async )]<br />public function popupRemainsClosedNonStartSymbol() : void<br />{<br /> Async.failOnEvent( this, _model, AutoCompletePM.SHOW_AUTO_COMPLETE_POPUP_CHANGE, 50 );<br /> <br /> //any text that is not the start symbol<br /> _model.textEntryHandler( "a" );<br /> _model.textEntryHandler( "1" );<br /> _model.textEntryHandler( "!" );<br /> <br /> assertFalse( "showAutoCompletePopup", _model.showAutoCompletePopup );<br />}]]></script> <p>We follow a similar process for the other tests as well. I also added a couple of extra tests for testing selecting an item to test for different labelField values.I also had to create a CloseAutoCompletePopupEvent that we expect to fired when we finish editing. Once finished you’ll end up with something like <a href="http://giles.roadnight.name/flex/AutoCompletePopup/viewsrc/srcview-step2/index.html" target="_blank">this</a>.</p> <p>When we run these tests we get the following:</p> <p><img style="display: block; float: none; margin-left: auto; margin-right: auto" src="http://lh6.ggpht.com/_Ac-KtmUjGx8/TUVa7pEmyhI/AAAAAAACrcQ/BPYhHvb7BQ4/s400/failingCompletedTests.JPG" /></p> <p>We can see that most of the tests fail. Only 2 pass, the test verifying the initial start-up state of the class and the test that verifies that nothing happens when we type anything other than the startSymbol.</p> <p>In the next part we’ll be <a href="http://blog.giles.roadnight.name/2011/01/guide-to-test-driven-development-in.html">implementing the class</a> to make these tests pass.</p> Roadershttp://www.blogger.com/profile/15030429903672650150noreply@blogger.com1tag:blogger.com,1999:blog-409108426448940832.post-76458819595521873502011-01-29T11:25:00.003+00:002011-01-30T15:54:25.752+00:00A Guide to Test Driven Development in Flex – Part 1: Defining What The SUT Does<p>In the <a href="http://blog.giles.roadnight.name/2011/01/guide-to-tdd-in-flex-introduction.html" target="_blank">Introduction</a> to this series of tutorial blog posts I described why I use unit testing and why I think that TDD is an especially good way to write both unit tests and the actual classes you’re testing – which I refer to as the SUT or System Under Test.</p> <p>Before we write any code for either the SUT or the unit tests we need to think about what the class needs to do. For this we need some requirements for the application or component that we are building.</p> <p>I have decided to write a reusable component that will popup when writing in a text field and allow you to select an entry to insert into your text. An example of where this would be used is in a twitter client. You would provide the component with a list of user names and tell it that the initial symbol is an @ symbol. You would then bind the component to a given text field. When typing in the text field if I typed @ my component would popup and display your list of usernames. As you type the list would filter and when you select an item from the list the username would be added to the text that you were typing.</p> <p>So now we have a basic and not very well written requirement we can start to define what the component will do and what we need to test. I will be writing the component following the <a href="http://blogs.adobe.com/paulw/archives/2007/10/presentation_pa_3.html" target="_blank">Presentation Model pattern</a> so all of the logic for the view component will reside in the presentation model so that it’s easily testable.</p> <p>First off we probably need to think of a name for the component. I thank that AutoCompletePopup is a pretty good name that goes some way towards describing what the class does. AutoCompletePopup will probably extend PopupAnchor and will have inside it an AutoCompleteComboBox which will extend ComboBox. <br />This compositional approach will enable us to re-use the components in other ways in the future more easily. Amongst these view components we’ll also need our presentation model which we’ll call AutoCompletePM. Our test will be called AutoCompletePMTest.</p> <p>We can create these two classes now. Usually they will both be in the same package but I usually have them in different source folders. Alongside the default src folder I create a test folder:</p> <a href="http://picasaweb.google.com/lh/photo/gdxn6VeqjpTBlTmIngGwIvF8q2PQ-_5T4RzXWTFqBN8?feat=embedwebsite" target="_blank"><img style="display: block; float: none; margin-left: auto; margin-right: auto" src="http://lh6.ggpht.com/_Ac-KtmUjGx8/TUQEgUTsWqI/AAAAAAACrbQ/MC2zDsXxXE8/s400/autoCompletePackages.JPG" width="408" height="269" /></a>  <p>So far we just have 2 empty classes:</p> <script type="syntaxhighlighter" class="brush:as3"><![CDATA[package com.pricklythistle.autocomplete.model<br />{<br /> public class AutoCompletePM<br /> {<br /> }<br />}]]></script><script type="syntaxhighlighter" class="brush:as3"><![CDATA[package com.pricklythistle.autocomplete.model<br />{<br /> public class AutoCompletePMTest<br /> { <br /> }<br />}]]></script> <p>We now need to start defining what functions the SUT will perform and then create at least one test for each of these functions.</p> <p>The SUT will perform the following actions:</p> <ul> <li>open the popup when auto-completion is required </li> <li>filter the list of available items based on text input </li> <li>when an item is selected dispatch an event to insert that text into the text field </li> <li>if the Escape button is pressed close the popup without inserting any text </li> </ul> <p>As we can see this is going to be a fairly simple class. From this list we can start to define our tests. Each test should ideally test 1 function call or property update on the class and test that we get the response that we expect. We may well test the same function call multiple times for different situations and each of these calls should be made in a different test.</p> <p>Lets start with the first function:</p> <ul> <li>open the popup when autocompletion is required </li> </ul> <p>This is still a slightly unclear requirement. What it means is that when the user types the startSymbol (for example an @) we want to open the popup. <br />Let’s add an empty test that will test this situation:</p> <script type="syntaxhighlighter" class="brush:as3"><![CDATA[[Test]<br />public function popupOpensOnStartSymbol() : void<br />{<br /> fail( "Test method Not yet implemented" ); <br />}]]></script> <p>This isn’t quite enough though. We also need to test that if we type anything other than the startSymbol the popup won’t open:</p> <script type="syntaxhighlighter" class="brush:as3"><![CDATA[[Test]<br />public function popupRemainsClosedNonStartSymbol() : void<br />{<br /> fail( "Test method Not yet implemented" ); <br />}]]></script> <p>At the moment we’ve assumed that the popup will start off closed but we should make sure by testing the initial state of the PM after construction:</p> <script type="syntaxhighlighter" class="brush:as3"><![CDATA[[Test]<br />public function testAutoCompletePM() : void<br />{<br /> fail( "Test method Not yet implemented" ); <br />}]]></script> <p>We’ve now got some initial empty tests but we still don’t have anything defined on the SUT. For the SUT to open a popup when a user types a certain symbol the SUT is going to need some properties and functions so that other classes can communicate with it. </p> <p>To open the popup we can have a bindable Boolean showAutoCompletePopup  property. The class also needs to know what the startSymbol is so we can define that as another property. It needs to know what is being typed in the text field so we can create a textEntryHandler method and it needs to know what is being typed in the popup so we can create another property called filterText:</p> <script type="syntaxhighlighter" class="brush:as3"><![CDATA[public class AutoCompletePM<br />{<br /> <br /> //--------------------------------<br /> // Properties<br /> //--------------------------------<br /> <br /> [Bindable]<br /> public var showAutoCompletePopup : Boolean;<br /> <br /> public var startSymbol : String;<br /><br /> public var filterText : String;<br /> <br /> //--------------------------------<br /> // Public Methods<br /> //--------------------------------<br /> <br /> public function textEntryHandler( enteredText : String ) : void<br /> {<br /> }<br />}]]></script> <p>We then follow these steps for the other requirements as well. When you finish you’ll end up with something like the code <a href="http://giles.roadnight.name/flex/AutoCompletePopup/viewsrc/srcview-step1/index.html" target="_blank">here</a>. </p> <p>By following this process we have now defined a small clean public interface for our class. We have our public properties and methods defined. A developer looking at these properties and methods should find it fairly easy to work out what the class does and how to use it.</p> <p>The only thing that we have not defined yet is the events that the class will dispatch. You could do this now if you like but I usually do this later.</p> <p>In the next part we <a href="http://blog.giles.roadnight.name/2011/01/guide-to-tdd-in-flex-step-2-writing.html">complete the unit tests</a>.</p> Roadershttp://www.blogger.com/profile/15030429903672650150noreply@blogger.com0tag:blogger.com,1999:blog-409108426448940832.post-8251795130251255382011-01-29T09:00:00.000+00:002011-01-31T09:04:36.057+00:00A Guide to Test Driven Development (TDD) in Flex – Introduction<p>TDD (Test Driven Development) is a method of writing code that starts with creating tests then goes on to writing the classes afterwards. <br />I am a big fan and use it whenever I can. It is not appropriate for all types of development but if you organise your code using the <a href="http://en.wikipedia.org/wiki/Model%E2%80%93View%E2%80%93Controller" target="_blank">model view controller pattern</a> or by using <a href="http://blogs.adobe.com/paulw/archives/2007/10/presentation_pa_3.html" target="_blank">presentation models</a> you can make good use of this technique.</p> <p>Unit testing in general is a very good habit to get into. Not only does it test the code that you have written but it also demonstrates to other developers what the class is supposed to do and how it supposed to be used. If you combine unit tests with a good Continuous Integration set up then you ensure that other developers don’t accidentally break your code. <br />Unit tests also help when bug fixing. When I get a bug to fix hopefully the code will have unit tests. If it does I add a test that demonstrates the bug and fails. I then modify the class and make sure that my new test and all the existing tests pass.</p> <p>TDD goes beyond this and encourages us to write better code. By following the steps that I outline it forces you to think about what the class will do before you start to write it. If the class is doing too much or is too complicated then split it up into more than one class and delegate some of the responsibility to other classes.</p> <p>TDD forces you to think about the public interface that the class presents to other classes. This helps you think about encapsulation. Classes should NOT make things public just so that you can test them.</p> <p>All of this leads to writing smaller simpler classes with simple public interfaces that are easier to test. If you write the tests first then you are going to write easily testable code. You should also end up with just enough code. When implementing your class you will write just enough code to make the tests pass and no more.</p> <p>A common reason for not using unit tests or TDD is that the developer doesn’t have time. I disagree with this. Most of the projects I work on are large and compiling the application and running it takes a long time. Doing this every time you want to test every small code change is slow. I find it much quicker to make sure the logic is correct before I have to run the whole application. Compiling and running a test runner is MUCH quicker than running the whole app. <br />Unit testing also allows you test edge cases or race conditions that would be hard to re-create in a running application. <br />On top of these savings tests save a lot of time in the long run. They reduced the number of bugs and encourage you to write code that makes maintenance easier and quicker as well.</p> <p>During this series of tutorials I will use TDD to help me create a fairly simple component. I will step through how I write code using TDD. This doesn’t necessarily follow all the steps that you are supposed to follow if you are strictly following TDD but it works for me.</p> <p>During these tutorials I will be referring to the SUT – the System Under Test. This is basically the class that you are testing.</p> <p>The tutorials will be broken up into the following sections:</p> <ul> <li><a href="http://blog.giles.roadnight.name/2011/01/guide-to-tdd-in-flex-step-1-defining.html">Defining what the SUT does</a> </li> <li><a href="http://blog.giles.roadnight.name/2011/01/guide-to-tdd-in-flex-step-2-writing.html">Writing our unit tests</a> </li> <li><a href="http://blog.giles.roadnight.name/2011/01/guide-to-test-driven-development-in.html">implementing the class</a> </li> </ul> <p>To get started we need to define <a href="http://blog.giles.roadnight.name/2011/01/guide-to-tdd-in-flex-step-1-defining.html">what our SUT will do</a>.</p> Roadershttp://www.blogger.com/profile/15030429903672650150noreply@blogger.com1tag:blogger.com,1999:blog-409108426448940832.post-13836086137575078862011-01-17T07:52:00.001+00:002011-01-17T07:52:23.422+00:00Google AuthSub for Actionscript<p>I was very pleased to find this webpage from Google:</p> <blockquote> <p><a href="http://code.google.com/apis/gdata/docs/as-authsub.html" target="_blank">Using AuthSub in Actionscript</a></p> </blockquote> <p>For a long time I have though about the apps you could build in flex if you could access Google Docs. This would make it really easy to write flex apps without having to worry about a server side component. You just store everything in Google Docs.</p> <p>Previously you have been unable to access docs for a number of reasons. The first one was that you could not authenticate from a flex app as there was no crossdomain.xml on the authentication server. <br />At the moment there is still no crossdomain.xml on the docs server but if we can authenticate we can access the picasa APIs which would work well with my <a href="http://blog.giles.roadnight.name/2010/01/picasa-api-implementation-v-01.html" target="_blank">picasa API work</a>.</p> <p>I followed the instructions above and created an app based on the code samples. I was able to get to the Google log in page and got the first single use token. However trying to get a long lived token never worked. Each time I tried I got a 403 error.</p> <p>I have posted for help about this on <a href="http://stackoverflow.com/questions/4634708/403-error-when-trying-to-access-google-authsub-from-flash-application-authsub-fo" target="_blank">StackOverflow.com</a> and on Google’s <a href="http://www.google.com/support/forum/p/apps-apis/thread?tid=039c807db255dc68&hl=en" target="_blank">API help forum</a> but have so far had no responses.</p> <p>Has anyone else had issues with this or has anyone else got this working? If you have any tips please let me know in the comments.</p> Roadershttp://www.blogger.com/profile/15030429903672650150noreply@blogger.com1tag:blogger.com,1999:blog-409108426448940832.post-7261878351708376962010-08-16T18:33:00.001+01:002010-08-16T19:07:17.214+01:00Cairngorm 3 Module Library<p>At work recently I have been looking at the Cairngorm 3 Module Library. It does some pretty cool things for example:</p> <ul> <li>Skinnable ModuleLoader that displays loading and error states for a module </li> <li>Lazy loads modules when parsley events are dispatched </li> <li>Passes events to modules when they have loaded </li> </ul> <p>The last item is what I was trying to get to work. We wanted to dispatch a loadSomeData event. The services that would load that data however are not initially available and need to be loaded in a module. Using a lazy load policy this module would be loaded and the event would then be passed to the module so that the loadSomeData Command would fire. Our CommandResult handler in the main application would then fire when the data had loaded.</p> <p>To set this you need to set a few things up. You need a ParsleyModuleDescriptor in your application context:</p> <p><cairngorm:parsleymoduledescriptor <br />    url="SampleModule.swf" <br />    objectid="sampleModule" <br />    /></p> <p>A lazy load policy in your context:</p> <p><cairngorm:LazyModuleLoadPolicy <br />    objectId="lazyLoadPolicy" <br />    type="{ ModuleInitialisationEvent }" <br />    /></p> <p>And a ModuleViewLoader in your application:</p> <p><module:ModuleViewLoader <br />    moduleManager="{ moduleManager }" <br />    skinClass="{ ModuleViewLoaderSkin }" <br />    loadPolicy="{ lazyLoadPolicy }" <br />    /></p> <p>This is enough to load the module when the ModuleInitialisationEvent is dispatched but the event will not be passed to the module as when the event is dispatched the module context is not yet initialised.</p> <p>To solve this problem we need a ModuleMessageInterceptor tag, again in our application context:</p> <p><cairngorm:ModuleMessageInterceptor <br />    type="{ ModuleInitialisationEvent }" <br />    moduleRef="sampleModule" <br />    /></p> <p>Now this should all work but as you can see from the sample app <a href="http://giles.roadnight.name/flex/ModuleDemo_unpatched/CairngormModuleDemo.html" target="_blank">here</a> it doesn’t. The module loads but the event does not get passed to the module (a working version of the sample app is <a href="http://giles.roadnight.name/flex/ModuleDemo_patched/CairngormModuleDemo.html" target="_blank">here</a>).</p> <p>To fix this I had to patch the Cairngorm Module Library. There are actually 2 separate problems that I have reported in the 2 bugs listed <a href="https://bugs.adobe.com/jira/browse/CGM-34" target="_blank">here</a> and <a href="https://bugs.adobe.com/jira/browse/CGM-35" target="_blank">here</a>.</p> <p>If you want to get your lazy loading modules to work correctly without patching Cairngorm then you need to make sure that your messageHandler or Command in the module is locally scoped. This does however mean that global CommandResult handlers won’t work for any results from the call.</p> <p>You also need to make sure that your ModuleViewLoader has a moduleID and that your initialisation event has the same moduleId in and has the ModuleId Meta Data Tag.</p> <p>I hope that my 2 patches for these fixes will be incorporated into trunk soon so that they will be available without patches.</p> Roadershttp://www.blogger.com/profile/15030429903672650150noreply@blogger.com2tag:blogger.com,1999:blog-409108426448940832.post-24099954642927908422010-05-22T08:10:00.001+01:002010-05-22T08:10:48.237+01:00Google IO Announcements<p>Over the past few days there have been a lot of announcements from Google at their IO event. There has been a lot of good news for the flash community and good news for android phone owners. As I am a Flex developer and have an android phone this has been exciting times!</p> <p>The most exciting announcement for me was the fact that the AIR pre-release for android is now open:</p> <p><a href="http://blogs.adobe.com/air/2010/05/air_android_prerelease.html">http://blogs.adobe.com/air/2010/05/air_android_prerelease.html</a></p> <p>A while ago I tried a bit of android development and started to think about writing a cycle computer application for my android phone. Now that we get AIR on Android though I can write this application much quicker in Flex. I can still get the geo-location and accelerometer data which is all I need. <br />The other advantage of course is that the application will work on any other device that supports AIR.</p> <p>I am also very excited by all the cool <a href="http://phandroid.com/2010/05/20/android-2-2-froyo-officially-announced-with-ground-breaking-new-features/" target="_blank">new features</a> coming in the next version of Android. I just hope it’s not too long before it’s released.</p> Roadershttp://www.blogger.com/profile/15030429903672650150noreply@blogger.com0tag:blogger.com,1999:blog-409108426448940832.post-25303014573466890952010-02-18T19:28:00.001+00:002010-02-18T19:30:06.388+00:00Setting up Apache and IIS on the same machine<p>Just a quick note to myself more than anything so I remember in the future.</p> <p>I am currently trying to get both IIS and Apache running on my web server. The reason for this is because I want to move my SVN server from my home server to my remote server. This will mean that my SVN server can have it’s own static IP and run with apache on port 80 as a http server.</p> <p>The problem was that by default IIS binds to all the IP addresses available to the server so that Apache was not able to bind to any.</p> <p>I found <a href="http://blogs.ebusinessware.com/2009/05/03/how-to-run-iis-and-apache-on-same-machine-on-port-80-here-is-the-solution/" target="_blank">this blog post</a> very helpful.</p> <p>To summarise:</p> <ul> <li>Make sure httpcfg is installed – you might need to download the <a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=96a35011-fd83-419d-939b-9a772ea2df90&displaylang=en" target="_blank">support tools</a></li> <li>type the following command for each IP address that you want IIS to listen on: <br />httpcfg set iplisten –i XXX.XXX.XXX.XXX</li> <li>confirm the IP list you have created with: <br />httpcfg query iplisten</li> <li>restart http service: <br />net stop http /y <br />net start w3svc</li> </ul> <p>That’s it. I now have Apache and IIS running on my server, both on port 80 but on different IPs. Now all I have to do is link Apache up to SVN and copy my dump of my local repository across.</p> Roadershttp://www.blogger.com/profile/15030429903672650150noreply@blogger.com1tag:blogger.com,1999:blog-409108426448940832.post-55789599305420825072010-02-11T21:39:00.001+00:002010-02-11T21:39:32.883+00:00SWCInspector v 0.2<p>I’ve uploaded a new version of SWCInspector. People at work, including myself, are already finding this pretty useful even with this early set of features.</p> <p>The new version is <a href="http://giles.roadnight.name/flex/SwcInspector/SWCInspector.html" target="_blank">here</a>. I’ll update this html page to point at new versions as I upload them.</p> <p>New features / fixes:</p> <ul> <li>Big improvements to the renderers – they were very dodgy on scrolling before</li> <li>Added a label to the selected asset indicating class name and swc that it came from</li> <li>Added the ability to draw a box to display the asset bounds</li> <li>Display bounds in the property pane so you can check 0,0 registration</li> <li>Improved the width and height adjustment</li> <li>Improvements to model wiring – more parsley based</li> </ul> <p>If you find this useful let me know. I’ve got a lot more features that I want to implement but if you have any suggestions let me know.</p> <p>The wife is away this weekend so hopefully there’ll be another version before Monday!</p> Roadershttp://www.blogger.com/profile/15030429903672650150noreply@blogger.com0tag:blogger.com,1999:blog-409108426448940832.post-53314639651195859072010-02-07T19:08:00.001+00:002010-02-07T19:17:16.425+00:00SwcInspector<p>At work all the assets that we use to create the applications are contained in swcs. These swcs are created in Flash and are used like any other library in Flex.</p> <p>There can be a lot of assets and it can be hard to find the one that you are looking for. It is also handy to be able to test the asset before it actually gets into the application – see what states are defined and how it looks when it is re-sized to make sure the slice-9 is set up properly.</p> <p>As we’re just getting to a point on my current project where we’re getting lots of assets delivered I put SwcInspector together this weekend. It is not finished yet but there is already quite a bit of useful functionality in there:</p> <ul> <li>The ability to load multiple swcs into the application </li> <li>Filtering of loaded asset list </li> <li>Visibility of states defined for each asset </li> <li>Resizing of assets to test slice-9 </li> <li>Adjustment of background color for white / light assets </li> </ul> <p>As I said it’s not finished. The existing functionality needs some tweaking and there is some more functionality that I want to implement.</p> <p>Unfortunately I can’t let you have a copy of the assets we use at work for obvious reasons. I found this <a href="http://giles.roadnight.name/flex/SwcInspector_0.1/Button_Transition_Skin.zip" target="_blank">swc</a> courtesy of this <a href="http://scalenine.com/blog/2007/10/09/%E2%80%9Cstateful%E2%80%9D-flex-skins-with-transitions-using-flash/" target="_blank">blog</a> for you to download and try out with the application if you so want to.</p> <p>You can have a look at the application <a href="http://giles.roadnight.name/flex/SwcInspector_0.1/SWCInspector.html" target="_blank">here</a>. Using it with a swc with only 1 asset isn’t really a very good example but that’s all I’ve got I’m afraid! If you use swcs yourself give it a try and let me know how it goes – I have only been able to test it on a few so  wouldn’t be surprised if there are issues.</p> <p>I’ll post again when I’ve made some progress. I can make the code available to anyone who’d like a look. If you want a copy please <a href="mailto:giles@roadnight.name" target="_blank">e-mail</a> me.</p> Roadershttp://www.blogger.com/profile/15030429903672650150noreply@blogger.com0tag:blogger.com,1999:blog-409108426448940832.post-27899973409992519752010-02-06T12:58:00.001+00:002010-02-06T13:06:10.858+00:00AsyncTokenWrapper is Dead, Long Live AsyncTokenWrapper<p>As I said in the comments of my last post about AsyncTokenWrapper I didn’t like the way I was wrapping AsyncToken and handling the response.</p> <p>A much neater solution to this is to create and register a custom command factory. You register a command based on the return type of your function. In my case I am returning a ProcessingAsyncToken so I go about registering my factory like this:</p><pre class="brush:as3">GlobalFactoryRegistry.instance.messageRouter.addCommandFactory( <br /> ProcessingAsyncToken, <br /> new ProcessingCommandFactory()<br />);</pre><p>I do this in a support class that implements ContextBuilderProcessor so that I can set this up when I create my context:</p><pre class="brush:as3"><fx:declarations><br /> <spicefactory:contextbuilder config="{ SlideShowContext }"><br /> <picasa:picasasupport /><br /> </spicefactory:contextbuilder><br /></fx:declarations></pre><p>My command factory looks like this:</p><pre class="brush:as3">public class ProcessingCommandFactory implements CommandFactory<br />{<br /> public function createCommand( <br /> returnValue : Object, <br /> message : Object, <br /> selector : * = null <br /> ) : Command<br /> {<br /> return new ProcessingCommand( returnValue, <br /> message, <br /> selector <br /> );<br /> }<br />}</pre><p>And just returns a new instance of my ProcessingCommand:</p><pre class="brush:as3">public class ProcessingCommand extends AbstractCommand<br />{<br /><br /> //-------------------------------------------------<br /> //<br /> // Constructor<br /> //<br /> //-------------------------------------------------<br /><br /> public function ProcessingCommand( <br /> returnValue : *, <br /> message : Object, <br /> selector : * <br /> )<br /> {<br /> super( returnValue, message, selector );<br /><br /> _processingToken = ProcessingAsyncToken( returnValue );<br /><br /> _processingToken.token.addResponder( <br /> new Responder( complete, error )<br /> );<br /> <br /> start();<br /> }<br /><br /> //-------------------------------------------------<br /> //<br /> // Private Variables<br /> //<br /> //-------------------------------------------------<br /> <br /> private var _processingToken : ProcessingAsyncToken;<br /> <br /> //-------------------------------------------------<br /> //<br /> // Overridden Methods: AbstractCommand<br /> //<br /> //-------------------------------------------------<br /><br /> protected override function selectResultValue( <br /> result : *, <br /> targetType : ClassInfo <br /> ) : *<br /> {<br /> return ( targetType.getClass() != ResultEvent && result is ResultEvent )<br /> ? ResultEvent( result ).result<br /> : result;<br /> }<br /><br /> protected override function selectErrorValue( <br /> result : *, <br /> targetType : ClassInfo <br /> ) : *<br /> {<br /> return ( targetType.getClass() == Fault && result is FaultEvent )<br /> ? FaultEvent( result ).fault<br /> : result;<br /> }<br /><br /> override protected function complete( result : * = null ) : void<br /> {<br /> var argumentsArray : Array;<br /> <br /> if ( _processingToken.resultProcessingFunction != null )<br /> {<br /> try{<br /> argumentsArray = _processingToken.resultProcessingArguments.concat();<br /> argumentsArray.unshift( result.result );<br /> result = _processingToken.resultProcessingFunction.apply( <br /> this, <br /> argumentsArray );<br /> }<br /> catch( e : Error )<br /> {<br /> error( e );<br /> }<br /> }<br /><br /> super.complete( result );<br /> }<br /><br /> override protected function error( result : * = null ) : void<br /> {<br /> var argumentsArray : Array;<br /> <br /> if ( _processingToken.faultProcessingFunction != null )<br /> {<br /> argumentsArray = _processingToken.faultProcessingArguments.concat();<br /> argumentsArray.unshift( result.fault );<br /> result = _processingToken.faultProcessingFunction.apply( <br /> this, <br /> argumentsArray );<br /> }<br /> super.error( result );<br /> }<br /><br />}</pre><p>We just extend AbstractCommand and override the complete and error functions to apply the functions defined in ProcessingAsyncToken before passing the result on. In the constructor we add a responder to the AsyncToken in the return Value.</p><p>I call the function as follows:</p><pre class="brush:as3">[Command( type="com.pricklythistle.picasa.event.ListPicasaAlbumsEvent", messageProperties="userID,kind" )]<br />public function loadUserAlbums( <br /> userID : String, <br /> kind : String = null <br />) : ProcessingAsyncToken<br />{<br /> url = StringUtil.substitute( BASE_URL, userID );<br /> <br /> return loadUserEntries( kind );<br />}</pre><p>I think this is a much neater solution that wrapping an AsyncToken inside another Async token – that had a really bad smell about it!</p> Roadershttp://www.blogger.com/profile/15030429903672650150noreply@blogger.com0tag:blogger.com,1999:blog-409108426448940832.post-88407092830764310332010-01-30T09:32:00.001+00:002010-01-30T09:32:41.358+00:00Android Development – emulator problems<p><a href="http://picasaweb.google.com/lh/photo/Js-WYzfyoiVHLKOc6EzUaQ?authkey=Gv1sRgCJz76vKLnJSucg&feat=embedwebsite" target="_blank"><img style="display: inline; margin-left: 0px; margin-right: 0px" align="right" src="http://lh5.ggpht.com/_Ac-KtmUjGx8/S2P7F_DyYkI/AAAAAAACe7E/K82sCUKWtSw/s400/Android%20Emulator.JPG" width="240" height="170" /></a>I just had my first go at android development. SO far I have managed to get Hello World running on my phone in debug mode but unfortunately I can’t get the emulator running which is going to make development harder.</p> <p>I’ve posted a question on <a href="http://stackoverflow.com/questions/2167404/android-emulator-crashing-on-windows-7-64-bit" target="_blank">stack overflow</a> so hopefully some helpful person will be able to help me out.</p> Roadershttp://www.blogger.com/profile/15030429903672650150noreply@blogger.com0tag:blogger.com,1999:blog-409108426448940832.post-70771938473379920022010-01-21T21:16:00.001+00:002010-01-21T21:20:32.509+00:00AsyncTokenWrapper<p>I have to confess that I lied ever so slightly in that last post. I said that the service code was exactly the same as it was without using the Command metadatatag.</p> <p>This isn’t strictly true – I had to write a wrapper for AsyncToken to handle the xml translation. I was hoping that I would be able to use an interceptor to intercept the result event, translate the xml and then re-dispatch the event. <a href="http://www.spicefactory.org/forum/viewtopic.php?p=1810#1810" target="_blank">Jens said</a> that this wasn’t possible though so I needed a neat and tidy way to translate the results of the async call before it made it back to the model.</p> <p>I did this by wrapping the async token that I get from whatever async operation I am performing. I can then pass this token to parsley so my code can do what it likes to the result before parsley routes it to it’s destination.</p> <p>AsyncTokenWrapper does just that, it extends AsyncToken and wraps another AsyncToken. When it gets a result or a fault from the original token it applies an optional function to the result or fault before passing this new ResultEvent or FaultEvent onto it’s responders.</p> <p>Code Below:</p> <pre class="brush:as3">package com.pricklythistle.common.service<br />{<br /> import mx.core.mx_internal;<br /> import mx.messaging.messages.IMessage;<br /> import mx.rpc.AsyncToken;<br /> import mx.rpc.Fault;<br /> import mx.rpc.IResponder;<br /> import mx.rpc.Responder;<br /> import mx.rpc.events.FaultEvent;<br /> import mx.rpc.events.ResultEvent;<br /> <br /> use namespace mx_internal<br /><br /> public class AsyncTokenWrapper extends AsyncToken<br /> {<br /><br /> //---------------------------------<br /> //<br /> // Constructor<br /> //<br /> //---------------------------------<br /><br /> public function AsyncTokenWrapper( <br /> token : AsyncToken, <br /> resultProcessingFunction : Function = null, <br /> faultProcessingFunction : Function = null )<br /> {<br /> super();<br /><br /> _token = token;<br /><br /> addResponders();<br /> <br /> this.resultProcessingFunction = resultProcessingFunction;<br /> this.faultProcessingFunction = faultProcessingFunction;<br /> }<br /><br /> //--------------------------------- <br /> //<br /> // Private Variables<br /> //<br /> //---------------------------------<br /> private var _token : AsyncToken;<br /><br /> //---------------------------------<br /> //<br /> // Properties<br /> //<br /> //---------------------------------<br /><br /> public var resultProcessingFunction : Function;<br /> public var faultProcessingFunction : Function;<br /><br /> //--------------------------------- <br /> //<br /> // Public Methods<br /> //<br /> //---------------------------------<br /> private function onResult( data : Object ) : void<br /> {<br /> var originalResultEvent : ResultEvent = ResultEvent( data );<br /> var result : Object = originalResultEvent.result;<br /> if( resultProcessingFunction != null )<br /> {<br /> result = resultProcessingFunction( result );<br /> }<br /> <br /> var newResultEvent : ResultEvent = new ResultEvent( <br /> ResultEvent.RESULT,<br /> originalResultEvent.bubbles,<br /> originalResultEvent.cancelable,<br /> result, <br /> this, <br /> originalResultEvent.message );<br /> <br /> applyResult( newResultEvent ); <br /> <br /> }<br /><br /> private function onFault( info : Object ) : void<br /> {<br /> var originalFaultEvent : FaultEvent = FaultEvent( info );<br /> var fault : Fault = originalFaultEvent.fault;<br /> if( faultProcessingFunction != null )<br /> {<br /> fault = faultProcessingFunction( fault ) as Fault;<br /> }<br /> <br /> var newFaultEvent : FaultEvent = new FaultEvent(<br /> FaultEvent.FAULT, <br /> originalFaultEvent.bubbles, <br /> originalFaultEvent.cancelable, <br /> fault, <br /> this,<br /> originalFaultEvent.message<br /> );<br /> <br /> applyFault( newFaultEvent );<br /> }<br /><br /> //---------------------------------<br /> //<br /> // Private Functions<br /> //<br /> //---------------------------------<br /> private function addResponders() : void<br /> {<br /> _token.addResponder( <br /> new Responder( onResult, onFault ) );<br /> }<br /> }<br />}</pre><p>Sorry for the way the code gets mashed up there but you can click on the little button top right to get it in a new window.</p> Roadershttp://www.blogger.com/profile/15030429903672650150noreply@blogger.com4tag:blogger.com,1999:blog-409108426448940832.post-28730973504117869602010-01-21T20:17:00.002+00:002010-03-18T09:00:54.199+00:00Asynchronous Commands in Parsley 2.2<p>I’ve been working with the latest version of parsley at work over the last few days and it’s got a really nice new feature borrowed from Cairngorm 3.0. It makes it much easier to deal with asynchronous operations. Previously if I was going to load something I might need all these files:</p> <ul> <li>model that wants the data </li> <li>loadData event – possibly with payload </li> <li>Action to receive load event </li> <li>service </li> <li>ResultEvent </li> <li>FaultEvent </li> </ul> <p>Now we can get rid of a lot of these classes and end up with:</p> <ul> <li>model that wants the data </li> <li>loadDataEvent </li> <li>service </li> </ul><p>You don’t actually need a custom event for the load either as you can just use a normal event and use string based matching but I prefer to match on class rather than string.</p><p>Let me give an example. In my Picasa API demo I had the following code in my LoadPicasaAlbumList action:</p><pre class="brush:as3">[MessageHandler]<br />public function loadAlbumList( event : ListPicasaAlbumsEvent ) : void<br />{<br /> var token : AsyncToken = service.loadUserEntries( event.userID, PicasaService.KIND_ALBUM );<br /> token.addResponder( this );<br />}<br />public function result( data : Object ) : void<br />{<br /> var resultEvent : ResultEvent = ResultEvent( data );<br /> <br /> var collection : ArrayCollection = PicasaTranslator.desearialiseXML( XML( resultEvent.result ) );<br /> <br /> dispatchEvent( new ResultEvent( LIST_ALBUM_RESULT, false, true, collection, resultEvent.token, resultEvent.message ) );<br />}<br /><br />public function fault( info : Object ) : void<br />{<br /> var faultEvent : FaultEvent = FaultEvent( info );<br /> <br /> dispatchEvent( new FaultEvent( LIST_ALBUM_FAULT, false, true, faultEvent.fault, faultEvent.token, faultEvent.message ) );<br />}</pre><p>Along with a load of meta data tags at the top of the class. This class is no longer required – which is good as it’s a load of boring boilerplate code that doesn’t really do very much and is tedious to write.</p><p>Now we have the following:</p><p><strong>Model:</strong></p><pre class="brush:as3">protected function loadFeed() : void<br />{<br /> albums = null;<br /> dispatchEvent( new ListPicasaAlbumsEvent( userID.text ) );<br />}</pre><p><strong>Service:</strong></p><pre class="brush:as3">[Command( type="com.pricklythistle.picasa.event.ListPicasaAlbumsEvent", messageProperties="userID,kind" )]<br />public function loadUserEntries( userID : String, kind : String = null ) : AsyncToken<br />{<br /> if( !kind )kind = KIND_ALBUM;<br /> <br /> if( ArrayUtil.getItemIndex( kind, KIND_ARRAY ) < 0 )<br /> {<br /> throw new Error( "kind must be found in KIND_ARRAY" );<br /> }<br /> <br /> url = StringUtil.substitute( BASE_URL, userID );<br /> <br /> return new AsyncTokenWrapper( send( { kind : kind } ), PicasaTranslator.desearialiseXML );<br />}</pre><p>Which is exactly the same code I had in the service originally except for the Command metadata tag. It instructs parsley to fire that function when an event of the correct type is received and tells parsley what properties to pass into the function.</p><p><strong>Model:</strong></p><pre class="brush:as3">[CommandResult]<br />public function onAlbums( albums : ArrayCollection, event : ListPicasaAlbumsEvent ) : void<br />{<br /> this.albums = albums;<br />}<br /><br />[CommandError]<br />public function onAlbumsFault( fault : FaultEvent, event : ListPicasaAlbumsEvent ) : void<br />{<br /> trace( "fault" );<br />}<br />}</pre><p>Parsley calls these functions when the command completes or fails and passes either a ResultEvent or your data in according to how you type the arguments.</p><p>And the really clever bit:</p><pre class="brush:as3">[Bindable]<br />[CommandStatus( type="com.pricklythistle.picasa.event.ListPicasaAlbumsEvent" )]<br />public var loadingAlbum : Boolean;</pre><p>This populates the property with a Boolean value of true when the data is loading so that you can disable buttons / show a loader or do whatever you want.</p><p>For more details about the Command tags take a look <a href="http://www.spicefactory.org/parsley/docs/2.1/manual/roadmap.php#commands" target="_blank">here</a>.</p>Roadershttp://www.blogger.com/profile/15030429903672650150noreply@blogger.com2tag:blogger.com,1999:blog-409108426448940832.post-50858239895399469082010-01-17T18:41:00.001+00:002010-01-17T18:41:20.433+00:00Picasa API Implementation v 0.1<p>Today I finally managed to get some time to carry on working on the Picasa API that I started in October or whenever it was (ok, I had to get up at about 5:00 but I couldn’t sleep!).</p> <p>You can have a look at progress so far <a href="http://giles.roadnight.name/flex/PicasaSlideshow_0.1/PicasaSlideShow.html" target="_blank">here</a>. At the moment it only lists albums and allows you to click on them to go through the Picasa page. Put your own username in at the top and you’ll get your albums listed.</p> <p>The next stage is to load the images for each album and display them.</p> <p>I am pretty pleased with the progress I made today. Most of it was spent writing the translators for the XML which I did with some stub data and TDD which worked pretty well. In the past writing tests for xml translation didn’t work especially well and they always broke – but that was because the service layer changed. I am hoping that the Google APIs will be a bit more stable.</p> <p>The UI code here is pretty ugly with no presentation models or anything like that, just enough to get what you see displayed. At the moment the effort is going into the API code.</p> <p>I am hoping to eventually add support to this for other photo hosting services such as flickr. The model that I am using here is closely based on the xml format that comes back from Picasa. When I move to include other services there might have to be a few tweaks to make it work with more than one service.</p> Roadershttp://www.blogger.com/profile/15030429903672650150noreply@blogger.com2tag:blogger.com,1999:blog-409108426448940832.post-32563572996416962362010-01-03T11:15:00.001+00:002010-01-03T11:15:00.937+00:00Implementing Lazy Loading of XML with ArrayCollection<p>I am still gradually working through my implementation of the Picasa public API to load images into Flex. One of the first apps I want to build is a simple signature app for forums that will loop through images in a Picasa album and display them one by one.</p> <p>A Picasa album can contain 1000 images and the xml is pretty verbose so this would be a very large download. This would download each time the signature appeared on a page and every time the page was refreshed so downloading the whole lot is really bad idea.</p> <p>I want to mimic the fill method of DataService. I would ask for an ArrayCollection to be filled but only the first 5 or however many records are specified would initially be loaded. The length of the collection would be reported as the number of items in the album and not the number of items downloaded. Additional items would be loaded as they are required.</p> <p>Looking at ArrayCollection the <a href="http://www.adobe.com/livedocs/flex/3/langref/mx/collections/ListCollectionView.html#getItemAt()" target="_blank">getItemAt</a> method has a prefetch argument specifying the number of items to fetch if the item is not local. There is also the <a href="http://www.adobe.com/livedocs/flex/3/langref/mx/collections/errors/ItemPendingError.html" target="_blank">ItemPendingError</a> that is despatched if the item that is requested is not local but there isn’t much documentation about this and it’s not clear exactly how this is handled.</p> <p>I had hoped that List and DataGroup for example would listen for ItemPendingError and add responders but they don’t seem to so it might not be as useful to implement the behaviour in this way.</p> <p>If anyone has any clues as to how all this holds together I’d be very interested to hear them. I am particularly interested in how the DataService class interacts with ListCollectionView. Somehow DataService has to get ListCollectionView to report the length of the remote list and not the local list. <br />Unfortunately the source for DataService doesn’t seem to be available.</p> <p>I could possibly implement this with some specific implementation of IList that is passed to a ListCollectionView but I would rather do it a similar way to the framework.</p> <p>Any help much appreciated.</p> Roadershttp://www.blogger.com/profile/15030429903672650150noreply@blogger.com2tag:blogger.com,1999:blog-409108426448940832.post-58881055877330673092009-12-18T17:49:00.001+00:002009-12-18T17:50:00.042+00:00Updating Flex 4 SDK GeneratedResourceModule Error<p>I was updating to the latest Flex 4 SDK today which was a bit involved. For ages we’ve been using 10708 and have been unable to upgrade to a later version as Parsley didn’t work with it. There were some changes to the ModuleManager interface or something like that and Parsley’s Module management code needed to be updated.</p> <p>Anyway, the <a href="http://opensource.powerflasher.com/jira/browse/PSL-283" target="_blank">parsley bug</a> had been fixed and I was having problems with an <a href="https://bugs.adobe.com/jira/browse/SDK-23913" target="_blank">SDK bug</a> that I had reported a while ago and which has now been fixed. It seemed like a good time to update to the SDK but it did take a while:</p> <ol> <li>Download and set up new SDK version 13099</li> <li>Spend a while fixing all the compiler errors and adjusting code to work with new framework</li> <li>Run App</li> <li>Got Module errors due to Parsley (as in this <a href="http://www.spicefactory.org/forum/viewtopic.php?t=370" target="_blank">thread</a>)</li> <li>Check out latest parsley code from SVN</li> <li>build parsley swcs</li> <li>Run App</li> <li>Get module errors again</li> <li>build parsley swcs properly</li> <li>Run App</li> <li>Get a different error:</li> </ol> <p>param 2 incompatible <br />  virt Object mx.core::FlexModuleFactory/callInContext() <br />  over * <br />GeneratedResourceModule7445881329779043571_mx_core_FlexModuleFactory/callInContext <br />() <br />VerifyError: Error #1053: Illegal override of <br />GeneratedResourceModule7445881329779043571_mx_core_FlexModuleFactory in <br />GeneratedResourceModule7445881329779043571_mx_core_FlexModuleFactory. </p> <p>     at global$init()</p> <p>Initially I incorrectly blamed this on Parsley again. I did some googling and couldn’t find much about GeneratedResourceModule apart from <a href="http://opensource.adobe.com/svn/opensource/flex/sdk/trunk/modules/compiler/src/java/flex2/compiler/i18n/I18nUtils.java" target="_blank">this</a>. That got me thinking about resource bundles. It turns out that all I needed to do was to re-build my resource bundles with the new SDK so they were compiled with the new Module interface. It was a simple step that I should have done straight away but I had forgotten.</p> <p>Hopefully this post will save someone else a bit of time if they have the problem as well.</p> Roadershttp://www.blogger.com/profile/15030429903672650150noreply@blogger.com0tag:blogger.com,1999:blog-409108426448940832.post-130378528519186942009-11-23T18:10:00.001+00:002009-11-23T18:10:36.643+00:00XML Namespaces<p>Recently I have been lucky enough to be working on a project that uses LCDS so I don’t have to write XML translators – all the objects arrive from server ready typed – it is soooo much easier and saves an awful lot of time.</p> <p>At home though I have started working with the Picasa data API which means I am back to writing translators. <br />This is a job I really don’t like – it never works the first time and takes a lot of trial and error to get it write. I am actually going to write a base translator class to make it a bit easier the next time I have to do it.</p> <p>Getting to grips with xml can be tricky but when namespaces are involved it gets exponentially more difficult and annoying!</p> <p>I’ll make a note of the syntax of how to deal with namespaces here so that next time I’ve forgotten how to do it I can look it up.</p> <p>I am trying to retrieve the href of the link node below with the relevance of self:</p> <p><feed <br />    xmlns='<a href="http://www.w3.org/2005/Atom'">http://www.w3.org/2005/Atom'</a> <br />    xmlns:gphoto='<a href="http://schemas.google.com/photos/2007'">http://schemas.google.com/photos/2007'</a> <br />    > <br />    <link <br />        rel='alternate' <br />        type='text/html' <br />        href='<a href="http://picasaweb.google.com/Giles.Roadnight'">http://picasaweb.google.com/Giles.Roadnight'</a> <br />        /> <br />    <link <br />        rel='self' <br />        type='application/atom+xml' <br />       href='<a href="http://picasaweb.google.com/data/feed/api/user/Giles.Roadnight'">http://picasaweb.google.com/data/feed/api/user/Giles.Roadnight'</a> <br />        /> <br /></feed></p> <p>My first attempt was as follows:</p> <p>var href : String = xml.link(@rel=’self’)[ 0 ]@href;</p> <p>but that didn’t work. The give away is this line:</p> <p>xmlns='<a href="http://www.w3.org/2005/Atom'">http://www.w3.org/2005/Atom'</a></p> <p>declaring the default namespace for the xml. What worked in the end was this:</p> <p>var atom : Namespace = new Namespace( "<a href="http://www.w3.org/2005/Atom"">http://www.w3.org/2005/Atom"</a> ); <br />var href : String = xml.atom::link.( @rel == 'self' )[ 0 ]@href;</p> <p>Hopefully that’ll save me (and maybe you) a few hours in the future.</p> Roadershttp://www.blogger.com/profile/15030429903672650150noreply@blogger.com4tag:blogger.com,1999:blog-409108426448940832.post-20297957327112168722009-11-15T17:57:00.001+00:002009-11-15T17:57:08.976+00:00Picasa Web Albums Data API<p>I have previously tried to get Flex to play nicely with the Picasa API. I use Picasa a lot and host all <a href="http://picasaweb.google.com/Giles.Roadnight" target="_blank">my pictures</a> there so to be able to do things with them with Flex would be very useful.</p> <p>Before I have had issues as there was no crossdomain.xml but having had a look at the <a href="http://code.google.com/apis/picasaweb/docs/2.0/reference.html" target="_blank">docs</a> today this seems to now be fixed (or I missed it last time) as detailed <a href="http://code.google.com/apis/picasaweb/docs/2.0/reference.html#Flash" target="_blank">here</a>.</p> <p>There are a couple of small projects I want to build on this API so it’s great that I won’t have to proxy these calls through the server.</p> Roadershttp://www.blogger.com/profile/15030429903672650150noreply@blogger.com1tag:blogger.com,1999:blog-409108426448940832.post-47221506427133695282009-10-10T14:34:00.001+01:002009-10-10T14:34:46.005+01:00More Waving<p>I’m excited to learn that there is already an Actionscript client library that enables you to write a flex application as a Google wave extension!</p> <p>Not sure what I would develop yet but there is a lot of scope for some cool apps I think.</p> <p><a href="http://code.google.com/p/wave-as-client/">http://code.google.com/p/wave-as-client/</a></p> <p><a href="http://wave-samples-gallery.appspot.com/results?q=flex">http://wave-samples-gallery.appspot.com/results?q=flex</a></p> Roadershttp://www.blogger.com/profile/15030429903672650150noreply@blogger.com0tag:blogger.com,1999:blog-409108426448940832.post-23199254411800582512009-10-10T14:23:00.001+01:002009-10-10T14:23:14.797+01:00Google Wave – first impressions<p>I got my invite to Google Wave today and have had a bit of a play about. If you don’t know what it’s all about then here is a 10 minute video explaining the basics:</p> <object width="480" height="295"><param name="movie" value="http://www.youtube.com/v/p6pgxLaDdQw&hl=en&fs=1&rel=0"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/p6pgxLaDdQw&hl=en&fs=1&rel=0" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="295"></embed></object> <p>So far it’s a bit frustrating as I don’t know many other people who have Google Wave. I can see the potential and would love to be able to use all the features. I am actually organising a trip to Scotland for May next year with Linzi and 4 friends and Google Wave would be great to help organise that but only Linzi and I have access so we can’t use it.</p> <p>So far I have installed Tweety which is pretty cool – you can get all your twits directly in Google Wave. I’ve also had a play with the map extension and the Sudoku extension.</p> <p>So, if anyone from Google Wave is listening please give me 4 invites so I can use wave to organise our trip next year!</p> Roadershttp://www.blogger.com/profile/15030429903672650150noreply@blogger.com0tag:blogger.com,1999:blog-409108426448940832.post-39639119144377218822009-08-31T18:10:00.001+01:002009-08-31T18:10:26.102+01:00Flex, Blaze DS and GAE<p>I’ve spent a fair bit of the long bank holiday weekend trying to get Blaze DS installed on Google App Engine but frustratingly I’ve not managed it so far.</p> <p>I was working off this <a href="http://jvalentino.blogspot.com/2009/06/flex-blazeds-google-app-engine-java.html" target="_blank">blog post</a> but when I tried to create a flex project it would not validate the Blaze DS server. I think it is something to do with the flex context root that  he is using in the example. When the validator tries to do a test on that context it doesn’t work.</p> <p>I’ll have another go next time I have some time. It’s annoying when you can’t get these things to work.</p> <p>Other than that I am very impressed with GAE – the eclipse plug-in is really easy to set up and use. It builds a sample site with web kit and a server call for you which works as soon as launch it.</p> <p>I really hope I can get it playing nicely with Flex.</p> Roadershttp://www.blogger.com/profile/15030429903672650150noreply@blogger.com0