Monday, February 14, 2011

Inconsistencies with Flash and HTTP status codes.

I ran into an interesting issue today where my Flash application was not working with a back-end RESTful service consistently across browsers and platforms. One of the nice things about Flash is that it does for the most part, run extremely well across a vast array of environments. To my surprise, I found an exception:

The RESTful service that my Flash app is consuming is one that is being custom built by a third party for my application. If a successful transaction takes place, I get an XML response with some useful data. If the transaction was unsuccessful, I get a predictable XML response containing an error code and message that are specific to the application. However, the back-end developer is using HTTP status codes in the range of 400 and greater for errors. The Flash documentation indicates that when using the URLLoader class, its data property will only be populated if the transaction completes successfully. Its HTTPStatusEvent event is considered to be unreliable due to inconsistencies across browsers. Therefore, I'm only really listening for Event.COMPLETE, IOErrorEvent.IO_ERROR and SecurityErrorEvent.SECURITY_ERROR.

Whenever I get an error response, (which for me could happen if a session is expired or if bad data is passed through...), I get valid XML back with a custom status code within the XML itself, and an HTTP status code of say, 405. A successful response would have an HTTP status code of 200. Event.COMPLETE is only triggered when the HTTP status code is 200, which means OK. Anything else triggers the IOErrorEvent.IO_ERROR event. What I was doing is putting try, catch around my attempt to access the error XML. This way I could catch if the response wasn't even valid XML and show some generic message. Then within the try block, I had a switch statement that would look for the custom status codes within my XML so that I could show more specific feedback to the user, like "Your session has timed out, click here to sign in again".

This all worked actually. I develop on OS X 10.6 and was using FireFox 3.6.x. For some reason though, my builds, when deployed to the dev server, were not working for some of my other team mates. We confirmed that it wasn't their cache, and that the deployment was intact and was indeed the latest build. They were also using FireFox but on Windows 7. Through the use of some packet sniffers we were able to confirm that in my environment I was getting past the first web service call and my colleague was not. I then tested again in OS X but with the latest version of Safari. In Safari I had the same failure as my colleague and was able to confirm that the data property of the URLRequest object was not being populated in my IO_ERROR handler (whereas for me, in FireFox it was).

The solution unfortunately must be that I had to get the back-end web service developer to modify his logic so that all application errors that would return error related XML for the application, be returned with an HTTP status code of 200. I have consumed XML from many RESTful services in the past and have never run into this issue in all my years. I believe I have just taken for granted that all these other services always return an HTTP status code of 200 when they want to return you useful XML error messages.

Hopefully this saves someone else some time!

Labels:

Wednesday, February 09, 2011

My thoughts on AS3 Signals

Here’s my evaluation of Signals, and I’ll preface this by conceding that I haven’t actually tried them in a project to fully appreciate the amount of code savings.

1. I like the simplicity of the API. It’s different than the standard but at least it’s clear (probably more so than the standard). I like the addOnce feature a lot but it’s also pretty easy to explicitly remove my event listeners. I just copy the foo.addEventListener line and paste it where it needs to be removed, and erase the ‘add’ part and rename it to ‘remove’. That’s not a lot of typing. Admittedly though one can forget to do it at all, and it does add more code to your project overall. Big deal? Doesn’t seem like it.

2. I don’t see a huge code writing savings in the context that most coders use an IDE that helps them generate the extra boilerplate code. I’m either going to have my IDE create an Event subclass or I’m going to copy and paste an old one and tweak a couple parts of it by hand. That seems to me like just as much of a time saver as the brevity that Signals offers.

3. It’s really fast.

So, in summary, I see a lot of trivial benefits that don’t really persuade me to change a current project started with regular events or to introduce something that might seem esoteric to a future developer that needs to take over my code. #3 though seems to be the most unadvertised feature that is also the strongest argument. 4-13x faster is a pretty damn strong argument. Still – it depends on your project right? If your project won’t appreciate the speed benefits then maybe it’s better to stick with the conventional approach.

So, for me I think I’ll definitely reserve the use of Signals for a project with a more intense level of event dispatching.

I'm interested in your comments!

Monday, August 31, 2009

Flash player 10 for Android - progress update

A nice progress update from Adobe on their commitment to bring the full Flash Player 10 to mobile – demoing the HTC Hero device running Flash Player 10 for Android.

http://www.adobe.com/devnet/devices/articles/htchero.html

Friday, August 14, 2009

Flex 3 doesn't support Vector type as bindable dataprovider

Yesterday I tried using a Vector as the dataprovider of a ComboBox control. Flex 3 doesn't like this FYI so don't bother trying it. I'm pretty sure in Gumbo this'll work fine though.

Thursday, June 04, 2009

Targeting Flash Player 10 for AIR projects with Flex 3.3

I got a project passed to me from Fraser and it was in AIR and Flex 3.3 for Flash Player 10. For some reason he could compile it but I was getting errors. This is after setting up my Eclipse (with FlexBuilder 3 plugin) for Flex SDK 3.3

Eventually it was determined that I needed to upgrade my FlexBuilder 3 plugin (not to 4!), to a slightly higher minor version because 3.02 introduces support for Flash 10. So, I launched my Adobe Updater application (you can search for it on Spotlight on a mac) and sure enough, immediately it told me there is an update for FlexBuilder. I ran that and my project was then able to compile. Hope this helps someone. Thanks for the frantic Googling Fraser!

Links:
http://www.adobe.com/devnet/flex/articles/sdk32_fb302.html

http://www.adobe.com/devnet/flex/articles/sdk32_fb302.html

Cheers,

Andrew

Wednesday, September 17, 2008

Elegant Code Snippets in blogger.

This might not be Actionscript/flash related but I thought I would explain how we got our code snippets to look so nice.

Searching the internet I ran into syntaxhighlighter which is a plugin that allows you to create nicer code snippets, unfortunately there is no style for Actionscript yet, but the Java highlighting style works quite nicely for AS snippets.

Quick instructions.

1. download the rar file from the google.code page (link above).
2. Unrar and upload to your own server under /syntaxhighlighter/
3. Add this to your blog template, just before the closing </body> tag.

<!-- START OF SyntaxHighlighter -->
<link href='http://www.YOUR_SITE.com/syntaxhighlighter/SyntaxHighlighter.css' rel='stylesheet' type='text/css'/>
<script src='http://www.YOUR_SITE.com/syntaxhighlighter/shCore.js' type='text/javascript'></script>
<script src='http://www.YOUR_SITE.com/syntaxhighlighter/shBrushCpp.js' type='text/javascript'></script>

<script src='http://www.YOUR_SITE.com/syntaxhighlighter/shBrushCSharp.js' type='text/javascript'></script>
<script src='http://www.YOUR_SITE.com/syntaxhighlighter/shBrushCss.js' type='text/javascript'></script>
<script src='http://www.YOUR_SITE.com/syntaxhighlighter/shBrushDelphi.js' type='text/javascript'></script>
<script src='http://www.YOUR_SITE.com/syntaxhighlighter/shBrushJava.js' type='text/javascript'></script>
<script src='http://www.YOUR_SITE.com/syntaxhighlighter/shBrushJScript.js' type='text/javascript'></script>
<script src='http://www.YOUR_SITE.com/syntaxhighlighter/shBrushPhp.js' type='text/javascript'></script>
<script src='http://www.YOUR_SITE.com/syntaxhighlighter/shBrushPython.js' type='text/javascript'></script>
<script src='http://www.YOUR_SITE.com/syntaxhighlighter/shBrushRuby.js' type='text/javascript'></script>
<script src='http://www.YOUR_SITE.com/syntaxhighlighter/shBrushSql.js' type='text/javascript'></script>

<script src='http://www.YOUR_SITE.com/syntaxhighlighter/shBrushVb.js' type='text/javascript'></script>
<script src='http://www.YOUR_SITE.com/syntaxhighlighter/shBrushXml.js' type='text/javascript'></script>
<script class='javascript'>
//<![CDATA[
function FindTagsByName(container, name, Tag)
{
var elements = document.getElementsByTagName(Tag);
for (var i = 0; i < elements.length; i++)
{
if (elements[i].getAttribute("name") == name)
{
container.push(elements[i]);
}
}
}

var elements = [];
FindTagsByName(elements, "code", "pre");
FindTagsByName(elements, "code", "textarea");

for(var i=0; i < elements.length; i++) {
if(elements[i].nodeName.toUpperCase() == "TEXTAREA") {
var childNode = elements[i].childNodes[0];
var newNode = document.createTextNode(childNode.nodeValue.replace(/<br\s*\/?>/gi,'\n'));
elements[i].replaceChild(newNode, childNode);
}
else if(elements[i].nodeName.toUpperCase() == "PRE") {
brs = elements[i].getElementsByTagName("br");
for(var j = 0, brLength = brs.length; j < brLength; j++) {
var newNode = document.createTextNode("\n");
elements[i].replaceChild(newNode, brs[0]);
}
}
}

//clipboard does not work well, no line breaks
//dp.SyntaxHighlighter.ClipboardSwf = "http://www.YOUR_SITE.com/syntaxhighlighter/clipboard.swf";
dp.SyntaxHighlighter.HighlightAll("code");
//]]>
</script>
<!-- END OF SyntaxHighlighter -->

4. Replace www.YOUR_SITE.com for your actual URL.
5. Post something following the syntaxhighlighter usage
6. You are Done.

Cheers.

FlexBuilder bug found today with event metadata

Found out the hard way today that you can't use camel case (as you should be able to) in event metadata in AS3 / MXML classes.

Here's my event class:

package ca.abcd.button
{
import flash.events.Event;

public class MyButtonEvent extends Event
{
public static const CLICK:String = "clickMyButton";
public function PlaylistEvent(type:String, bubbles:Boolean=true, cancelable:Boolean=false)
{
super(type, bubbles, cancelable);
}
}
}


Here's a snippet of a class that I want event metadata for. You should be able to define events that get dispatched from the class like this:

[Event(name="
clickMyButton", type="ca.abcd.button.MyButtonEvent")]
public class Playlist {

....


but when code hinting, for addEventListener, when you expect to see MyButtonEvent.CLICK in the list of event options, you get MyButtonEvent.CLICK_MY_BUTTON. What you'll find is you get underscores replacing any place in the event's string value where camel case is used.

Known Bug
Turns out it's a known FlexBuilder parsing bug and you can work around it by not using camel case and using underscores instead to separate words in your event value. You'll see I added a note in the bug report that it's still a problem in FlexBuilder 3.1. Hopefully they fix this soon, but otherwise, using underscores, no biggie, just a big of a waste of time, grr.


As a side note, if you're wondering what the problem is with just doing this inside of MyButtonEvent:

public static const CLICK:String = "click"

The reason is that MouseEvent.CLICK is also defined as "click" and so you'll get a conflict, catching events you don't mean to. The workaround has to then be in MyButtonEvent,

public static const CLICK_MY_BUTTON:String = "clickMyButton"

or

public static const CLICK_MY_BUTTON:String = "click_my_button"


or

public static const CLICK_MY_BUTTON:String = "CLICK_MY_BUTTON"

Saturday, September 13, 2008

Using namespaces to implement the state design pattern

I was reading up on the namespaces feature of AS3, trying to imagine a use for them (outside of the XML context), and decided that they would be useful for implementing the state design pattern. For that design pattern I used to use external state classes. Now, unless my various implementations for an API require a lot of code, it's cleaner to put the various implementations as same-named functions in the same class, differentiated with namespaces. Here's the classic gumball machine example that illustrates the state pattern that I implemented with the help of namespaces.


TryGumballMachine.as

package {

import ca.abcd.gumballmachine.GumballMachineModel;

public class TryGumballMachine extends Sprite
{
public function TryGumballMachine()
{
var gumballMachine:GumballMachine = new GumballMachine();
gumballMachine.turnHandle();
gumballMachine.insertCoin();
gumballMachine.insertCoin();
gumballMachine.turnHandle();
}
}
}


The above will trace out the following:

Can't turn handle, you must insert a coin first!
One coin inserted. Turn the handle to get a gumball.
You can't put a coin in the machine right now because there's already one there. Turn the handle then add another coin.
I hereby give you a gumball, don't forget to brush your teeth!



GumballMachine.as

package ca.abcd.gumballmachine
{
public class GumballMachine
{
private namespace hasCoin;
private namespace noCoin;

use namespace noCoin;
private var _state:Namespace;

public function GumballMachine()
{
_state = noCoin;
}

public function turnHandle():void {
_state::turnHandle();
}

public function insertCoin():void {
_state::insertCoin();
}

noCoin function turnHandle():void {
trace("Can't turn handle, you must insert a coin first!");
}

hasCoin function turnHandle():void {
trace("I hereby give you a gumball, don't forget to brush your teeth!");
}

noCoin function insertCoin():void {
_state = hasCoin;
trace("One coin inserted. Turn the handle to get a gumball.");
}

hasCoin function insertCoin():void {
trace("You can't put a coin in the machine right now because there's already one there. Turn the handle then add another coin.");
}
}
}

Labels: