Martín Bove Blog! | Otro blog de tecnología…

TAG | AS3

En este post me gustaría exponer un poco de las interesantes cualidades que encontré revisando este relativamente nuevo framework, o como le gusta decir a los norteamericanos la segunda generación de frameworks para Flex, o mejor dicho para AS3.

Swiz es un framework muy liviano y que introduce la idea de inversión de control o (ioc) de sus siglas en ingles, también dispone obviamente de inyección de dependencia para cumplir con su objetivo. Para la gente que conoce un poco de Java, seguramente ya se le vino la primavera a la mente…si  “Spring”  jajaja . Swiz propone la misma idea que Spring en java, pero claro con sus diferencias obvias, pero la idea es básicamente la misma.

Para la gente que no conoce mucho de patrones de diseño, ni de arquitectura de software en general, la IOC es conocida y adoptada por ayudar a la reducción de código redúndate, y aquí viene lo bueno, ya que tendremos que escribir menos código.  jajaja

Sin más preámbulo, he pensado en reescribir el sencillo ejemplo que hice en el post anterior  con Swiz,  así pueden ver lo fácil que es de implementar este framework.

Lo primero q tenemos que hacer es bajar el bajar el swc que contiene al framework de esta dirección: http://code.google.com/p/swizframework/
Y copiarlo dentro de nuestra carpeta libs.

Sería bueno que armemos una pequeña estructura MVC de paquetes, esto no es necesario pero ayuda mucho al orden.
Algo así sería más que suficiente:

Estructura de paquetes

Lo primero que necesitamos crear es, lo que en Swiz se conoce como un “Bean Loader” y esto se hace simplemente extendiendo un componente del tipo BeanLoader, que viene incluido en el framework. Se vería así:


<BeanLoader xmlns="org.swizframework.util.*"
			xmlns:mx="http://www.adobe.com/2006/mxml" >

	<model:DnsModel
		id="DnsModel"
		xmlns:model="com.martinbove.model.*" />

    <controllers:DnsController
		id="DnsController"
		xmlns:controllers="com.martinbove.controllers.*"/>

</BeanLoader>

Ahora necesitamos inicializar el framework desde el punto de entrada de nuestra aplicación. Para este fin Swiz posee un componente que se encarga del trabajo.


<swiz:SwizConfig strict="true"
			mediateBubbledEvents="true"
			eventPackages="com.martinbove.events"
			viewPackages="com.martinbove.views"
			beanLoaders="{[Beans]}" />

Seguiremos con la creación del modelo de datos, que en este caso es tan sencillo como esto:


package com.martinbove.model
{
	public class DnsModel
	{
		[Bindable]
		public var informacion:String = new String();

		public function DnsModel()
		{

		}
	}
}

En el código del controlador es donde se pueden ver un poco la magia de Swiz. En este caso el controlador espera la llamada desde la vista, luego procesa dicha llamada, en nuestro caso efectuando un dns lookup, y seguidamente altera el modelo de datos como respuesta, que a su vez se ve reflejado en la vista nuevamente.


package com.martinbove.controllers
{
	import com.martinbove.model.DnsModel;

	import flash.events.DNSResolverEvent;
	import flash.events.ErrorEvent;
	import flash.net.dns.AAAARecord;
	import flash.net.dns.ARecord;
	import flash.net.dns.DNSResolver;
	import flash.net.dns.MXRecord;
	import flash.net.dns.PTRRecord;
	import flash.net.dns.SRVRecord;

	import org.swizframework.controller.AbstractController;

	public class DnsController extends AbstractController
	{
		public var dnsResolver:DNSResolver;

		// aquí se inyecta el modelo en esta variable usando la meta etiqueta [Autowire]
		[Autowire]
		public var dnsModel:DnsModel;

		// constructor de la clase
		public function DnsController() {
			// se inicializa el objeto DNSResolver y se agregan 2 manejadores que se usaran para las consultas de DNS
			dnsResolver = new DNSResolver();
			dnsResolver.addEventListener(DNSResolverEvent.LOOKUP, lookupHandler);
			dnsResolver.addEventListener(ErrorEvent.ERROR, errorHandler);
		}

		// en este caso registramos a este metodo como manejador del evento DnsEvent.DNS_LOOKUP mediate la etiqueta [Mediate]
		[Mediate(event="DnsEvent.DNS_LOOKUP", properties="dnsType, queryString")]
		public function lookupDNS(dnsType:String, queryString:String ):void {
			switch(dnsType)
			{
				case "ARecord":
					dnsResolver.lookup(queryString, ARecord);
					break;
				case "AAAARecord":
					dnsResolver.lookup(queryString, AAAARecord);
					break;
				case "MXRecord":
					dnsResolver.lookup(queryString, MXRecord);
					break;
				case "PTRRecord":
					dnsResolver.lookup(queryString, PTRRecord);
					break;
				case "SRVRecord":
					dnsResolver.lookup(queryString, SRVRecord);
					break;
			}
		}

		// Manejador de resultados de busqueda de DNS
		public function lookupHandler(event:DNSResolverEvent):void
		{
			var records:Array = new Array();
			records = event.resourceRecords;
			var name:String = "Name: " + records[0].name;
			var ttl:String = "TTL: " + records[0].ttl;

			// aqui directamente escribimos en el modelo de datos el resultado
			dnsModel.informacion += name + "\n";
			dnsModel.informacion += ttl + "\n";

			if (records[0] is ARecord) {
				var addr:String = "Addr: " + records[0].address;
				dnsModel.informacion += addr;
			}

			else if (records[0] is MXRecord) {
				var exchange:String = "Exchange: " + records[0].exchange;
				var preference:String = "Preference: " + records[0].preference;
				dnsModel.informacion += exchange + "\n" + preference;
			}

			else if (records[0] is PTRRecord) {
				var ptr:String = "PTR: " + records[0].ptrdName;
				dnsModel.informacion += ptr;
			}

			else if (records[0] is SRVRecord) {
				var priority:String = "Priority: " + records[0].priority;
				var weight:String = "Weight: " + records[0].weight;
				var port:String = "Port: " + records[0].port;
				var target:String = "Target: " + records[0].target;

				dnsModel.informacion += priority + "\n" + weight + "\n" + port + "\n" + target;
			}

			dnsModel.informacion += "\n----------------------------------------------------------------------------\n";
		}

		// Manejador de errores
		protected function errorHandler(event:ErrorEvent):void {
			dnsModel.informacion += "Ha ocurrido un error en la consulta";
			dnsModel.informacion += "\n----------------------------------------------------------------------------\n";
		}
	}
}

La comunicación entre la vista y el controlador la hacemos mediante un evento propio, esto es básicamente extender la clase base event y añadirle las propiedades que necesitemos.


package com.martinbove.events
{
	import flash.events.Event;

	public class DnsEvent extends Event
	{
		public static const DNS_LOOKUP:String = "DnsEvent.DNS_LOOKUP";

		private var _dnsType:String;
		private var _queryString:String;

		public function get dnsType():String {
			return _dnsType;
		}

		public function get queryString():String {
			return _queryString;
		}

		public function DnsEvent(type:String, dnsType:String, queryString:String, bubbles:Boolean = false, cancelable:Boolean=false)
		{
			super(type, bubbles, cancelable);
			_dnsType = dnsType;
			_queryString = queryString;
		}

		override public function clone() : Event {
			return new DnsEvent(type, dnsType, queryString, bubbles, cancelable);
		}
	}
}

La vista también es muy sencilla, y solo tiene que despachar el evento cuando se realiza la consulta.

El código es el siguente:


<?xml version="1.0" encoding="utf-8"?>
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009"
		 xmlns:s="library://ns.adobe.com/flex/spark"
		 xmlns:mx="library://ns.adobe.com/flex/halo" >

	<fx:Script>
		<![CDATA[
			import com.martinbove.events.DnsEvent;
			import com.martinbove.model.DnsModel;
			import flash.events.MouseEvent;
			import org.swizframework.Swiz;

			// aqui sigue la magia del framework que solo se encarga de inyectar el dnsModel
			[Autowire]
			[Bindable]
			public var dnsModel:DnsModel;

			protected function button_clickHandler(event:MouseEvent):void {
				var tipo:String = tipos.selectedItem.label;

				// creamos el evento q se manejara en el controller mediante la etiqueta [mediate]
				var e:DnsEvent = new DnsEvent(DnsEvent.DNS_LOOKUP, tipo, queryString.text, true);
				dispatchEvent(e);
			}

		]]>
	</fx:Script>

	<s:Group width="90%" horizontalCenter="0" top="20">
		<s:layout>
			<s:HorizontalLayout/>
		</s:layout>
		<s:TextInput id="queryString" width="100%" text="www.martinbove.com.ar"/>
		<mx:ComboBox editable="false" id="tipos">
			<fx:Array>
				<fx:Object label="ARecord" />
				<fx:Object label="AAAARecord" />
				<fx:Object label="MXRecord" />
				<fx:Object label="PTRRecord" />
				<fx:Object label="SRVRecord" />
			</fx:Array>
		</mx:ComboBox>
		<s:Button label="consultar" click="button_clickHandler(event)"/>
	</s:Group>
	<s:Group top="86" width="90%" horizontalCenter="0" height="90%">
		<s:layout>
			<s:HorizontalLayout/>
		</s:layout>

		<s:TextArea id="resultado" width="100%" height="100%" text="{dnsModel.informacion}"/>

	</s:Group>
	<s:Label x="20" y="66" text="Resultados" color="#FFFFFF"/>
</s:Group>

Con esto hemos concluido la recorrida por esta breve aplicación que muestra la implementación de Swiz, aquí les dejo el código fuente de la aplicación de ejemplo para q lo pueda evaluar con más tranquilidad y algunos recursos por si quieren seguir viendo algo más sobre este framework.

Air2 Swiz -Ejemplo

  1. http://swizframework.org/
  2. http://www.madeinflex.com/2009/07/01/el-principio-de-inversion-of-control-y-flex/
  3. http://groups.google.com/group/swiz-framework/

                             

La nueva habilidad de Adobe Air 2 de resolver DNS, puede ayudar en gran a mejorar las operaciones relacionadas con el manejo de redes en nuestras aplicaciones, si a esto le sumamos el manejo de Sockte´s, que es otra de las innovaciones en la versión 2 de Adobe AIR, se puede ver claramente como despunta un potencial interesante en lo que respecta al desarrollo de aplicaciones que hagan uso de los recursos de red, como por ejemplo serian aplicaciones del estilo per2per o inclusive aplicaciones de telefonía Ip.

Veamos un poco más en profundidad que puede hacer Adobe Air con respecto a los DNS.

Para dar soporte a la resolución de DNS, Adobe a integrado una nueva clase llamada:  DNSResolver, que se encuentra en el paquete “flash.net.dns”. Esta clase, resuelve DNS ejecutando un DNS Query estándar, y devolviéndonos una respuesta de los registros en lo que habitualmente se conoce como DNS Records.

Hay muchas clases de DNS Records, pero aquí les detallo cuales son los que Adobe Air 2, va a manejar.

  • A: Los registros A son los que mapean una dirección IPv4 con un hostname. Este registro contiene:  “hostname”, “TTL (Time To Live)” y la dirección “IPv4″.
  • AAAA: Los registros AAA son los que mapean una dirección IPv6 con un hostname. Este registro contiene: “hostname”, “TTL” y la dirección “IPv6″.
  • MX: Los registros MX mapean una lista de servidores de mail con un nombre de domino. Este registro contiene: “hostname”, “TTL”, “exchange server” y preferencias.
  • PTR: Los registros PTR mapean un hostname  con una dirección Ip, en esencia es lo que se conoce como “reverse DNSLookup” . Este registro contiene: “hostname”, “TTL”, y un puntero hacia el host.
  • SRV: Los registros SRV mapean una lista de servicios con un hostname. Este registro contiene: “hostname”, “TTL”, “priority”, “weight”, “port”, y “target domain”

La sintaxis para usar la clase sería la siguiente:

public function DNSResolverExample()
{
//Create the resolver object
var resolver:DNSResolver = new DNSResolver();
resolver.addEventListener( DNSResolverEvent.LOOKUP, lookupComplete );
resolver.addEventListener( ErrorEvent.ERROR, lookupError );

//Look up records
resolver.lookup( "example.com.", ARecord );
resolver.lookup( "example.com", AAAARecord );
resolver.lookup( "example.com", MXRecord );
resolver.lookup( "208.77.188.166", PTRRecord );
resolver.lookup( "_sip._tcp.example.com.", SRVRecord );
}

Para probar un poco esta nueva funcionalidad he realizado esta pequeña aplicación, que aquí pueden ver y más abajo descargar.
nota: Es necesario para compilar está aplicación el SDK de Adobe AIR2 instalado en nuestro entrono de desarrollo, en este post hay un tutorial de como instalarlo.
AIR 2 Ejemplo de uso de DNS

Aquí se puede descargar la aplicación de ejemplo como sus fuentes.
AIR2 Ejemplo DNS

               

Viejos Posts >>