Archive for October, 2009

SVN using Tags and Merging – Part 1.

Thursday, October 29th, 2009

I’m going to make a few assumptions before I start this tutorial.

  1. You have windows (2000+)
  2. You have TortoiseSVN client
  3. You are familiar with the basics of SVN, i.e. you have checked out a trunk onto your local machine.
  4. You SVN repository is available over HTTP, e.g. http://svn.yourdomain.com/svn

For the setup I am going to be working with example directories, in this case “C:/dev” is your development directory on your local machine. You can of course make this whatever you choose but all other paths in this tutorial will need to reflect that change you have made. So i’m now going to checkout a project into my development environment at “C:/dev/example-svn”. If the person responsible for setting up your SVN repository has done their job properly you should see 3 directories, “trunk” (containing the latest code changes), “tags”, and “branches”. Your setup may differ from this, but i’ll assume you can translate that to whatever you environment is.

Now a little word about what “Tags” and “Branching” are:

By the method with which SVN operates, essentially both tags and branches are the same thing, i.e. a snapshot of the trunk that you are working with. Thus when you create a tag/branch you are creating a copy of a particular revision of your trunk code (it could be a branch of a branch etc, but lets not go down that road just yet). Doing this allows you to have 2 or more simultaneous code copies that can be altered separately, but merged back together at any time (covered in Part 2).

It’s worth noting that SVN doesn’t actually create a copy of the code base, it merely creates files that represent the differences between the trunk and the tag that was created. Nothing for you to worry about really, but basically stops your hard drive space from being used up with lots of different copies.

How to do it:

  1. Using your TortoiseSVN client navigate to your trunk directory (e.g. C:/dev/example-svn/trunk)
  2. Right click inside the directory (do NOT select a folder inside this directory, just some blank space).
  3. Select TortoiseSVN > Branch/tag
  4. Change the “To URL” to “http://svn.yourdomain.com/svn/tags/stable/0.1″
  5. Select either the “HEAD” or pick a revision number (you can browse revisions)
  6. Add a comment
  7. Hit “Ok”

Note in the above, for the tagged URL I chose a structure inside tags to represent a “stable” release, and a meaningful version number “0.1″.

Now, once you’ve done this you will need to head into “C:/dev/example-svn/tags”, Right-Click, and choose “SVN Update”. This should pull out the tagged release code we just have created.

Now if you perform any changes inside the tag or the trunk and commit them you will see they are only contained within their respective directories.

Why would you do this:

  1. You want to have a “production”, or series of “stable” releases.
  2. The tagged versions can be modified with fixes (for production release) and not be affected by any changes in the trunk
  3. You wish to perform fixes against a production code state, and test them against the last production release, and then re-merge them into the trunk (merging will be covered shortly in part 2).

AMFPHP Cake constructor arguments causing NetConnection.Call.BadVersion

Saturday, October 10th, 2009

So… you’re seeing “NetConnection.Call.BadVersion” from Flash while attempting to talk to CPAMF or AMFPHP.
Well my friend, there’s a good probability that something is wrong.
Here are some suggestions:

  1. Fatal Error
  2. Redirect

What I tracked my problem down to was the fact that the following happens when AMFPHP receives a Flash remote object (using remoting):

  1. AMFPHP receives an AMF stream
  2. AMFPHP inteprets the stream byte by byte
  3. AMFPHP decides what sort of “thing” that Flash has attempted to send back
  4. AMFPHP attempts to “find” the relevant PHP class, defined by the class alias that has been sent in Flash.
    e.g. Flash object is "com.org.my.namespace.path.MyClass"
    and interprets that as com/org/my/namespace/path/MyClass.php (or MyClass.class.php) based on the base classMappingPath you sent in the service gateway, $gateway->setClassMappingsPath( '/absolute/path/to/vo/models' );
    attempts to include it, and instantiate an object of MyClass (therefore your filename MUST match your class name).
    i.e. $clazz = new $classname;

So I realised a problem. Constructors, both in Flash and PHP MUST at all costs have default values for them, i.e. the constructor variables are optional, because AMFPHP and Flash don’t use the sent objects, they literally convert them to their relevant objects on each side.

Further info on problems and debugging NetConnection.Call.BedVersion in Flash and AMFPHP can be found by google of course.

Cpamf accepting VO objects in service calls as parameters

Monday, October 5th, 2009

Here’s the status:
Cake implementation of AMFPHP via the plugin cpamf appears to be lacking some particular documentation regarding “accepting” flash objects in calls.
i.e.
Flash -> PHP object conversion.

Sure you can send back flash objects no problem, and there are plenty of documented places that tell you how to send flash objects back from PHP using class mapping and there was even some information on the reverse using AMFPHP on how to map VO’s from Flex to PHP using AMFPHP, but what seemed to be lacking was some particular documentation on how to get CPAMF, cake’s own brand of AMFPHP working with Flex VO to PHP. Begin investigation:

I am indeed hoping that I can get my controllers to accept objects instead of parameters or arrays. Allowing the flash app to pass through an object instead of having to decide what parameters or format it should be returning each time.

e.g.
Controller | Method | Parameter
TestController->test(StandardVO $vo)

As cake does; it likes to have controllers and models for everything it does. Aren’t you a nice cake! *grumble*
So it’s written it’s own CakeGateway.php class to extend the PHPAMF Gateway class, overriding action calls for the gateway. Aside from overriding them all and not calling the parent::registerActionChain() that seems to be fine.
A little hunt through the documentation/notes and general settings in globals.php seems to indicate that you can set the directory for controllers and vo classes. Great I think; changing these values should resolve my problem. If only!

The CakeGateway class appears to initialise the gateway with it’s own set of parameters for the controllers, sensibly (for a change) reading cake’s default controllers folder. Thus, all appears to be working within the /cpamf/browser , but still without the ability to pass objects, DOH!
The voPath mapping that appears to be set from the original globals file points to “services/vo”, i’m assuming this is supposed to indicate the current directory is the base and the services/vo folder is the one containing the vo’s. Thus, following some logical thinking I begin to stuck some classes in various folders that cake might just be reading.
In goes a StandardVo class, in the models/ directory and also inside the plugins/cpamf/vendors/amfphp/services/vo directory, try again. Nope still not recognising my object.
Ok, I know Cake’s naming convention is totally crap, lets try naming the file standard_vo.php instead of StandardVo.php . Still nothing, despite being implemented in both directories.

A few hours later, and after a fair amount of digging around in AMFPHP I came across what looked like some form of include()’ing. Having managed to stop the flash from doing it’s thing an instead die()’ing in certain places, I realised that this part here was responsible for loading in the PHP class to map to (lines 351-396 of /plugins/cpamf/vendors/amfphp/core/amf/io/AMFBaseDeserializer.php). Stepping through the logic I saw it: “$mappedClass = str_replace(’.', ‘/’, $typeIdentifier);”
The mapClass() function was doing the magic; interpreting the type of the flash object (which seemed to resolve to a full package name) into an include. AH HAH! It was also resolving it relative to the customMappingsPath which we saw earlier was set in CakeGateway class (cake_gateway.php).
So it would seem that AMFPHP was expecting to see a full package naming convention for all the Flash Objects it was going to receive.

I headed back to the CakeGateway class and amended the setCllassMappingPath() to

// This is the path to the Vo models!
$gateway->setClassMappingsPath( MODELS . 'vo' );

I then created a “vo” directory inside the cake models directory, and further proceeded to mimic the flash namespace package path.
models/vo/com/test/StandardVo.php , et VOILA! Problem resolved; cpamf now knows which object it is receiving and fills it with the data received from the flash object.

Now back to pulling out some hair over other issues.