Blog de Daniel Zegarra Rotating Header Image

AS2

Tips sobre Class mapping con Zend AMF

En resumen Class mapping consiste en relacionar dos clases de lenguajes distintos de tal forma que en cada lenguaje se traten del mismo elemento. Esta relacion (comunmente llamada mapeo en español) permite intercambiar instancias de estas clases entre lenguajes de manera transparente.

Zend AMF mapea por defecto las clases mas comunes como son String, Number, Array, Object, ArrayCollection, etc y tambien permite mapear clases creadas por el usuario. Para lograr el mapeo bidireccional te recomiendo cumplir dos puntos.

  • Define la variable $_explicitType con el alias en cada clase deseas mapear o usa el metodo getASClassName() en lugar de registrar cada mapeo con $serveramf->setClassMap(). Dara mas flexibilidad a tu aplicacion.
  • Intenta relacionar el alias de la clase con la ruta donde la clase PHP a mapear se encuentra. Esto te ayudara a mapear clases de AS3 a Zend AMF.
    Cuando Zend AMF recibe una solicitud lee los alias de las clases AS3 en el mensaje y busca sus clases PHP homologas en el directorio dado por $serveramf->addDirectory(). Si el alias elegido para las clases es, por dar un ejemplo, VO.Usuario Zend AMF buscara la clase VO_Usuario en la ruta VO/Usuario.php.
    Ten en cuenta esto solo si usas addDirectory() para definir la ubicacion de tus servicios y no deseas usar setClassMap() para registrar cada alias.

Las siguientes dos clases se mapearan correctamente entre PHP y AS3 de forma bidireccional.

Ruta: [ServicesPath]/VO/Usuario.php

<?php
class VO_Usuario{

	/**
	 * Usado por Zend AMF. Devuelve el alias de
	 * esta clase para actionscript.
	 * Devuelve una cadena con el nombre de la
	 * clase actual reemplazando _ por puntos.
	 */
	public function getASClassName(){
		return str_replace("_",".",get_class($this));
	}

	public $id;
	public $username;
	public $firstname;
	public $lastname;
	public $enabled;
}
?>

Nota: En este ejemplo uso getASClassName() para obtener dinamicamente el alias de la clase. Seria muy util que este metodo se encontrara en una clase base y que cada clase a mapear herede de esta. De esta forma no tendras que preocuparte por verificar el alias elegido.

Y por otro lado tenemos su clase homologa en AS3:

Ruta: /net/danielzegarra/VO/UsuarioVO.as

package net.danielzegarra.VO{
	//Recuerde que no es necesario que el alias tenga relacion
	//con el nombre de la clase
	[RemoteClass(alias="VO.Usuario")]
	public class UsuarioVO{
		public var id:uint;
		public var username:String;
		public var firstname:String;
		public var lastname:String;
		public var enabled:Boolean;
	}
}

La version de Zend Framework al escribirse este documento es la 1.10.
Puedes encontrar la documentacion de Zend AMF en http://framework.zend.com/manual/en/zend.amf.server.html

Decidirse entre Zend AMF, AMFPHP, WebORB, …

Para mi, decidir que framework usar para conectar una aplicacion Flex/Flash con un servidor PHP es todo un dilema debido a que mi eleccion influrira mucho en mi calendario de trabajo. Supongo a muchos les  pasara que se familiarizan con un pequeño grupo de lenguajes y/o  frameworks y lo utiliza en todo proyecto que crea conveniente. Asi era yo con AMFPHP, el primer gateway AMF que conoci alla cuando Flash 8 era el ultimo lanzamiento de Macromedia.

En si tenemos tres o cuatro candidatos potenciales y estos son: Zend AMF, AMFPHP y WebORB. A continuacion comento las caracteristicas de cada uno.

AMFPHP es creo, sin lugar a dudas, la mejor alternativa si deseas conectar tu aplicacion Flex o Flash con un servidor PHP (y este a su vez con la BD) y no deseas tener que pasar por una larga curva de aprendizaje. AMFPHP es ligero, incluye una gestion de roles bastante simple, no es necesaria su instalacion, soporta mapeo de clases (VOs) y por ultimo, incluye un navegador de servicios para que puedas probar los mismos rapidamente. Ademas, soporta AMF0 y AMF3 (por si usas AS2 o AS3) de forma transparente. Ademas, viene preparado para comsumir Web services. Entre sus desventajas estaba la falta de soporte. La persona detras del proyecto lo abandono dejandolo en una version beta (y sin la nueva documentacion completa) durante un par de años  pero recientemente su desarrollo acaba de ser retomado y gracias a ello, se acaba de lanzar, por fin, la version 1.9 oficial.

El siguente es Zend AMF, desarrollado por Zend (la empresa detras de PHP) es el mas apoyado de todas las alternativas debido a que tiene la venia de Adobe y, obviamente, es desarrollado por Zend. A pesar de esto, carece de caracteristicas que AMFPHP o WebORB ya ofrecen (como seguridad integrada y un navegador de servicios) obligandote a implementarlas tu mismo o, lo que es mas facil, a vivir sin ellas. Pero su gran ventaja es que al ser una parte de Zend Framework (aunque se puede descargar de manera independiente) se acopla perfectamente a su arsenal de herramientas lo que es muy util, creeme. Hoy acabo de enterarme que el problema de la lenta serializacion de datos que Zend AMF tenia en versiones anteriores acaba de ser solucionada de manera oficial en la version 1.10.4.

El tercero es WebORB. Si tuviera que definirlo en una sola palabra esa seria “Completo”. Tiene tantas caracteristicas que impresiona. Un administrador de servicios decente junto con opciones pensadas para ahorrarle al desarrollador la necesidad de escribir codigo, incluye su propio administrador de acceso a servicios y metodos ademas de un administrador centralizado para el mapeo de clases. Sin lugar a dudas es el que ofrece mas opciones a simple vista. El problema de WebORB es justo eso, ofrece tantas opciones que pueden confundir al novato, darle una sensacion de demasiada complejidad.

Escribo este post porque hace poco he pasado de AMFPHP a Zend AMF. Me costo hacer la mudanza debido a que tenia muchas clases que recibian matrices asociativas como parametros (AMFPHP mapeaba los objetos de Flash en arrays asociativos y Zend AMF lo hace como objetos) y basaba casi toda la implementacion de seguridad en el metodo beforeFilter de cada clase/servicio.

Problema con archivos externos AS2 y File Servers

He descubierto algo curioso en la forma en que Flash trabaja con los archivos externos .as usando ActionScript 2. Es un problema molesto la verdad. Me ha tomado mucho tiempo descubrirlo y ahora comparto el secreto.

Si tu aún trabajas en AS2, ya sea con Flash 8, 9 o 10, y empiezas a importar clases, Flash creará un archivo de extension .ASO para cada clase que importes.

Este archivo ASO es un intermediario binario que Flash usa para no tener que estar compilando una y otra vez las mismas clases. Al tu dar la orden de compilar, Flash verifica el timestamp de la última modificación realizada de cada uno los archivos de clases usados y los compara con el timestamp de sus respectivos archivos ASO para así volver a compilar solo las clases que han cambiado.

Esto parece muy simple y práctico. Pero, ¿que pasa cuando los archivos de mi proyecto no se encuentran localmente en mi computador?

Cuando los archivos a compilar se encuentran en un computador distinto y se tienen acceso a estos archivos de forma remota la fecha de la última modificación la define el SO del computador donde se almacenan los ficheros.

Esto es un problema para Flash puesto que la fecha de última modificación es lo único que usa para saber si una clase ha sido actualizada. Si el servidor de archivos donde se guarda el proyecto tuviera una hora distinta a la estación de trabajo podría afectar la habilidad de Flash de detectar si han habido cambios en las clases lo que provocaría que al hacer cambios en las clases estos no surtirían efecto en los archivos compilados .swf.

La solución

Usar la misma fecha y hora tanto en el servidor de archivos como en las estaciones de trabajo. Esto se puede lograr definiendo el mismo time server para ambos equipos.
Los siguientes ejemplos han sido recopilados de Time Synchronisation with NTP de la documentación oficina de Ubuntu y HOWTO: Set up NTP on Windows Vista de www.cumps.be.

En Ubuntu

Instalar el servicio ntpd el cual ajustará el reloj del computador para que le fecha y hora se mantenga sincronizada con el o los servidores ntp configurados. Para ello primero hay que revisar si el servicio ya esta instalado:

sudo service ntp status

Si el resultado es unrecognized service entonces el paquete no se encuentra instalado. En ese caso lo instalamos con:

sudo apt-get install ntp

Y luego procedemos a definir los servidores ntp editando el fichero /etc/ntp.conf.

sudo vi /etc/ntp.conf

En la línea 16 aprox. se definen los servidores NTP que se van a usar. Cambialos por estos si es que estas en sudamerica:

server 0.south-america.pool.ntp.org
server 1.south-america.pool.ntp.org
server 2.south-america.pool.ntp.org
server 3.south-america.pool.ntp.org

Puedes encontrar los servidores NTP mas cercanos a tu ubicación en www.pool.ntp.org.

Guardas los cambios y reinicias el servicio con la siguiente sentencia:

sudo /etc/init.d/ntp restart

En Windows Vista

Sigue el siguiente tutorial.

También puedes borrar los archivos ASO luego de cada cambio en tus clases pero al final, perderías mas tiempo. Mejor pierdes al inicio y luego ya no mas.

wwmjw.cumps.bewww.cumps.be