Spring & ActionScript 3.0 (en 3 pasos)

June 3rd, 2009

El ya famoso Spring Framework ahora también llega al mundo de ActionScript 3.0. La principal ventaja del contenedor Spring es que permite plasmar la creación de los objetos y sobre todo las relaciones entre los objetos desde un archivo de configuración XML (o varios). Se utiliza la palabra contenedor ya que Spring funciona como un escenario donde actúan todos los objetos de una aplicación. Tradicionalmente, la instanciación de objetos se ha realizado directamente desde el código. Con Spring ocurre lo que se llama una inversión de control ya que es el mismo contenedor el que se encarga de crear los objetos así como sus respectivas dependencias (herencia, interfaz, asociación, etc.). Uno se desconcierta un poco cuando empieza a trabajar con este tipo de contenedores. Esto sucede porque el control de la ejecución de la aplicación ya no es completo. Aparece un nuevo actor durante la ejecución cuyo trabajo es manejar el ciclo de vida de cada objeto. Esta inversión de control permite al desarrollador crear aplicaciones más flexibles (porque son más configurables) además de externalizar las dependencias entre componentes, y por lo tanto crear clases más fáciles de reutilizar.

Spring ActionScript está escrito en ActionScript 3.0, su migración ha sido realizada principalmente por Christophe Herreman, inicialmente bajo el nombre de Prana Framework. Actualmente, el proyecto ha sido aceptado como una extensión oficial del Spring Framework.

El propósito de este post es enseñarles cómo preparar su entorno de trabajo para poder disfrutar de Spring ActionScript desde Flash CS3. Primero, necesitamos descargar el contenedor. Lo pueden conseguir aquí. Coloquen los archivos fuentes (’org\springextensions\actionscript\*’) en la raíz del directorio donde van a trabajar. También se necesita bajar las fuentes de la biblioteca as3reflects desde as3commons. Asimismo, las fuentes se deben colocar en la raíz (’as3reflect\*’).

Con el Framework instalado, ya podemos empezar a crear nuestro objeto de prueba. El primer paso consiste en crear una clase sencilla que tendrá como única propiedad su nombre además de su respectivo setter & getter: 

package com.springframework
{
   public class MiBean
   {   
       // ------- Constructor -------
       public function MiBean() { }

       // ------- Propiedades -------
       protected var _nombre:String;
       public function set nombre(value:String):void { _nombre = value; }
       public function get nombre():String { return _nombre; }
   }
}

El archivo debe llamarse ‘MiBean.as’ y ubicarse en el directorio ‘com\springframework’.

En el segundo paso, vamos a crear nuestro archivo de configuración XML. Este archivo va a indicar al contenedor qué objeto se necesita instanciar y qué valor se asignará a la propiedad ‘nombre’:

<?xml version="1.0" encoding="utf-8"?>
<objects xmlns="http://www.pranaframework.org/objects"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.pranaframework.org/objects http://www.pranaframework.org/schema/objects/prana-objects-0.6.xsd">
<object id="miBean" class="com.springframework.MiBean">
<property name="nombre" value="jdecuyper" />
</object>
</objects>

En nuestro tercer y último paso, vamos a crear un archivo .fla en el cual se va a crear el contenedor Spring. Usando nuestro archivo de configuración, el contenedor va a instanciar la clase MiBean y pasarle el valor ‘jdecuyper’ a su propiedad ‘nombre’. En el primer frame de nuestro archivo, se coloca el siguiente código:

import com.springframework.MiBean;
import org.springextensions.actionscript.context.support.XMLApplicationContext;
registerClassAlias("com.springframework.MiBean", MiBean);

var xmlApplicationContext:XMLApplicationContext;
xmlApplicationContext = new XMLApplicationContext("http://localhost/springactionscript/applicationContext.xml");
xmlApplicationContext.addEventListener(Event.COMPLETE, applicationContextCompleteHandler);
xmlApplicationContext.load();

function applicationContextCompleteHandler(e:Event):void {
var miBean:MiBean;
miBean = xmlApplicationContext.getObject("miBean");
trace(miBean.nombre);
}

La clase XMLApplicationContext sirve para crear el contenedor, también se conoce como la ‘bean factory’. El método ‘getObject’ se encarga de regresarnos una referencia a nuestro objeto. Una vez que MiBean está instanciado, se manda a llamar su propiedad ‘nombre’, y si todo sale bien, se pintará ‘jdecuyper’ en su ventana de debug.

Les dejo con este ejemplo bastante sencillo pero que espero les pueda servir de inicio para desarrollos más complejos.

 

¿Cómo crear un branch desde algún repositorio?

May 15th, 2009

 

1. Click derecho en el directorio dónde se va a trabajar. 

2. Selecionar Tortoise SVN -> Checkout (selecionar HEAD revision o alguna anterior).

3. Selecionar Tortoise SVN -> Branch/Tag. Ingresar la URL dónde se tendrá que almacenar el nuevo “branch” .

Tortoise - Crear Branch

 

Tortoise nos avisa que nuestro working copy todavía pertenece al trunk y no al branch creado. 

 

Tortoise - Switch

 

Para cambiarse al branch, seleciona Tortoise SVN -> Switch, luego indica la URL del branch que requieres.
A partir de ahora, los cambios que se harán al proyecto ya no afectarán el trunk. Si en algún momento, se decide intregar los cambios del branch al trunk, se utilizará el comando merge.

 

¿Cómo correr programas en segundo plano como servicios de windows?

July 15th, 2008

Recientemente me encargaron una aplicación que leyera varios feeds y los almacenara en una base de datos sin que tuviera que intervenir un usuario. Y se me ocurrió que crear un servicio de windows sería la mejor forma de hacerlo.

Para ponerlo en palabras sencillas, un servicio windows es un ejecutable que -en segundo plano- realiza tareas especificas como monitorear cambios en archivos del sistema o en perifericos (USB, disco duro externo,…), o cualquier cosa que necesitemos hacer automáticamente, por ejemplo recordatorios o enviar correos. Su característica más interesante es que un servicio no requiere intervención de un usuario, funcionan al fondo. Por lo mismo, en la mayoría de los casos no son visibles en el entorno UI del usuario (aunque no es el caso, por ejemplo, de la consola SQL server Service Manager de MS SQL Server). La no-visibilidad y la autonomía de esos procesos, ocasionó, en el mundo UNIX®, su asosiación con la palabra “daemon”. Aunque se parecen, las palabras “daemon” y “demonio” no significan lo mismo. Evi Nemeth, co-autora del libro “UNIX System Administration HandBook“, indica lo siguiente:

Many people equate the word “daemon”‘ with the word “demon”, implying some kind of Satanic connection between UNIX and the underworld. This is an egregious misunderstanding. “Daemon” is actually a much older form of  “demon”; daemons have no particular bias towards good or evil, but rather serve to help define a person’s character or personality. The ancient Greeks’ concept of a “personal daemon” was similar to the modern concept of a “guardian angel” — “eudaemonia” is the state of being helped or protected by a kindly spirit. As a rule, UNIX systems seem to be infested with both daemons and demons.

El servicio que desarrolle se encarga, mediante un uso básico de threads, de hacer peticiones HTTP a una serie de ligas RSS. El resultado de las peticiones se procesan y almacenan en una base de datos. Visual Studio 2005 y 2008 ofrecen todo lo necesario para desarrollar un servicio de tipo “Hello world” en unos instantes. Les aconsejo desarrollar primero una aplicación de consola y luego pasar su código en un servicio para evitar perder tiempo en instalar y desinstalar el servicio durante la fase de debugeo. Cuando tiene listo su ejecutable, nada más le falta instalarlo mediante la herramienta installutil.exe que se encuentra en:

%SystemRoot%\Microsoft.NET\Framework\v2.0.50727

Para installar el servicio:

installutil "C:\serviciosWindows\miAssembly.exe"

Para installar el servicio y cambiar la ruta del log de instalación:

installutil
/LogFile="C:\serviciosWindows\log\instalUtil.installLog"
"C:\serviciosWindows\miAssembly.exe"

Para desinstallar el servicio:

installutil /u "C:\serviciosWindows\miAssembly.exe"

No tuve ningún problema para instalar mi servicio en XP Pro. Sin embargo, cuando lo intente hacer en una máquina Vista me encontre con unos problemas de seguridad. A la hora de arrancar, el servicio lanzaba un error en el CLR Debugger:

No se controló System.Security.SecurityException
Message="No se encontró el origen, pero no se pudo buscar en algunos o
todos los registros de eventos. Registros inaccesibles: Security."
Source="System" StackTrace: en System.Diagnostics.EventLog.FindSourceRegistration(String source,
String machineName, Boolean readOnly) en System.Diagnostics.EventLog.SourceExists(String source, String machineName) en System.Diagnostics.EventLog.SourceExists(String source) en Lab.MiServicio..ctor() en Lab.Program.Main()

Y del lado de la consola de los servicios (services.msc):

Windows no pudo inicar el servicio "" en Equipo local. Error 1053: El servicio no respondió a tiempo a la solicitud de inicio o de control.

Cuando un servicio arranca, intenta registrarse en el visor de eventos. Si no tiene los permisos necesarios, se termina inmediatamente. Para evitar esta restricción, se tiene que abrir el cmd con los derechos de administrador y luego ejecutar el commando de instalación. Además de ser una herramienta muy poderesa, los servicios generalmente obligan el programador a trabajar con threads. Lo cual implica unos dolores de cabeza pero nuevas ideas para solucionar problemas de computación.

Ligas de interés:

http://www.freebsd.org/copyright/daemon.html
http://es.wikipedia.org/wiki/Daemon