Monthly Archive for January, 2008

Saffron UML Editor - Squishing the rumors.

Saffron lives!

This is something I've been anticipating for close to a year now, and apparently development is back in full gear. I've worried on a few occasions that Saffron might have grown so far out of the scope of developer Sam Pastel's original intent that the project was just going to die. That is apparently, and thankfully, not the case. This is one to keep an eye on.

I took inspiration from his Flex Builder screens and switched to white on black. It might take some getting used to, but I like it.

8/13/08 - at this point I've basically given up on this utility. It makes me sad, but I'd rather be pleasantly surprised than have my hopes and dreams dashed against the rocks of disappointment.

Actionscript string replacement and international currency.

This made me a little nostalgic for the olden days when a vacation to Europe was a remote possibility:

var str:String = "Now only $9.95!";
var price:RegExp = /\$([\d,]+.\d+)+/i;
trace(str.replace(price, usdToEuro));
 
function usdToEuro(matchedSubstring:String,
                    capturedMatch1:String,
                    index:int,
                    str:String):String {
    var usd:String = capturedMatch1;
    usd = usd.replace(",", "");
    var exchangeRate:Number = 0.853690;
    var euro:Number = usd * exchangeRate;
    const euroSymbol:String = String.fromCharCode(8364);
    return euro.toFixed(2) + " " + euroSymbol;
}

Maximizing your AIR application programatically - stage.nativeWindow.maximize()

Just be sure to call it in an applicationComplete handler. My attempts to call it from creationComplete were resulting in a null object reference.

stage.nativeWindow.maximize()

Django Authentication from Flex

Django 'salts' passwords for added protection. They use SHA1 with a random key applied to further obfuscate the resulting hash. This is a good thing, but it threw me off for a bit. I don't want to send the unencrypted passwords over the wire, so I needed to grab the hash string from Django, break it apart, and reassemble it inside of flex. This did the trick:

private function onGetUsersComplete( re:ResultEvent ):void
{
	var users:Array = re.result as Array;
	var userArray:Array = [];
	for ( var ii:int = 0; ii < users.length; ii++ )
	{
		var user:UserVO = users[ii] as UserVO;
		userArray.push( user );
		trace( users[ii].first_name );
	}			
 
	var isValidUser:Boolean = false;
	loginService.removeEventListener(ResultEvent.RESULT, onGetUsersComplete);
	for ( var i:int = 0; i < users.length; i++ )
	{
		if ( users[i].username == this.username )
		{
			currentUser = users[i] as UserVO;
			var salt:String = users[i].password.split('$')[1];
			//django specific password scheme
			password = 'sha1$' + salt + '$' + SHA1.hash( salt + password );
			loginService.verify_credentials( username, password );
			loginService.addEventListener(ResultEvent.RESULT, onVerifyCredentialsResult, false, 0, true );
			isValidUser = true;
		}
	}
 
	if ( !isValidUser )
	{
		sendNotification( ApplicationFacade.LOGIN_FAILED, "Invalid Username" )
	}
}

pyAMF - Communication with Django from Flex

Up until this point I have been using Django AMF for my remote services. It was working fairly well on my windows machine, but when I tried to deploy my application to my Ubuntu slice, it started kicking up weird errors. I'd spoken with one of the pyAMF developers in a Reddit thread, and they seemed like a motivated group, so I decided to give pyAMF a go.

*sigh*

Now I have new errors to deal with. Not a problem though, signed up to their mailing list and Thijs and Nick were extremely helpful in hunting down the bugs and squishing them dead. pyAMF is still in alpha, but they are moving over to beta soon. It is working well now, so give it a try if you need communication between Flash/Flex/AIR and Python.

The Gateway

They have a couple of examples on the pyAMF site, but here are a couple things that I learned. In my amfgateway.py, which is the equivelant of a Django views.py, I had to register my models so that pyAMF would send and recieve typed custom objects. It ended up looking something like this:

amfgateway.py

import pyamf
from pyamf.remoting.djangogateway import DjangoGateway
from django.contrib.auth.models import Userpyamf.register_class( User, 'django.contrib.auth.models.User' )
 
def get_users(request):
    return User.objects.all()
 
sessionGateway = DjangoGateway({'ve.get_users'  : get_users})  # could include other functions as well

I am using the Django auth structure to authenticate users in my application, so that is the bare bones of what you need to get that going. Here's what the urls.py looks like:

urls.py

from django.conf.urls.defaults import *urlpatterns = patterns(' ',
     (r'^ve/gateway/', 've.clients.amfgateway.sessionGateway'),
)

As you can see, it is extremely simple. It is setup in the same fashion you would use to link up a Django view.

In Flex, I've set up a RemoteServiceDelegate which is extending the Seasar RemotingService [the site is in japanese]. This is actually a holdover from Django AMF, but it works well, so I am going to continue to use it. Here's the code:

RemoteServiceDelegate.as

package com.visualempathy.session.model.delegate
{
 import mx.controls.Alert;
 import mx.rpc.events.FaultEvent;	import org.seasar.flex2.rpc.remoting.RemoteService;
 
  public class RemoteServiceDelegate extends RemoteService
  {
 	public static const gatewayURL:String = "http://myserver.com/ve/gateway/"
 	public function RemoteServiceDelagate()
        {
 		super();
 		useAMF0 = false;
 		gatewayUrl = gatewayURL;
 		destination = 've';
                addEventListener(FaultEvent.FAULT, handleDataFault);
 	}
 
 	private function handleDataFault( fe:FaultEvent ):void
 	{
 		Alert.show( fe.fault.faultDetail );
 	}
 }
}

Using this setup, the destination in the remoting service is used like this:

 sessiongateway = DjangoGateway({'ve.get_users' : ve.get_users
've.get_orders': ve.get_orders})

where 've', the destination in the RemotingService class precedes the method name in the DjangoGateway argument. This can be added to as much as needed as demonstrated above.