Adobe Flex SDK y Flex Builder 3

Transcripción

Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
Adobe Flex SDK y
Flex Builder 3
Álvaro Martínez del Val
23/03/2010
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
Contenido
1.
Adobe Flex SDK y Flex Builder ............................................................................................... 4
1.1.
Adobe Flex SDK.............................................................................................................. 4
1.2.
Flex Builder .................................................................................................................... 4
2.
Primera aplicación ................................................................................................................. 5
3.
MXML vs AS ........................................................................................................................... 6
4.
Modo de depuración ............................................................................................................. 7
5.
Creando un formulario .......................................................................................................... 7
6.
Creando un componente complejo .................................................................................... 13
7.
Creando el modelo en el cliente ......................................................................................... 16
8.
Visualización de datos (DataGrid) ....................................................................................... 19
9.
Programando con eventos .................................................................................................. 23
10.
Arquitectura de una aplicación web con Adobe Flex SDK .............................................. 26
10.1.
Cliente ..................................................................................................................... 26
10.2.
Servidor ................................................................................................................... 27
10.3.
Comunicación cliente – servidor (Intefaz Http) ...................................................... 27
10.4.
BlazeDS .................................................................................................................... 30
10.4.1.
Productor – Consumidor (Message Service) ....................................................... 30
10.4.2.
Objeto Remoto (Remoting Service) .................................................................... 35
10.4.3.
Proxy Service ....................................................................................................... 40
10.5.
Localización de aplicaciones .................................................................................... 42
10.6.
Paso de parámetros http a un swf .......................................................................... 48
11.
Creación de un html que envuelva a el swf .................................................................... 49
11.1.
12.
Paso de variables ..................................................................................................... 50
Otras características de Adobe Flex SDK ......................................................................... 50
12.1.
Comunicación con interfaces externas (javascript) ................................................ 50
13.
SharedObjects ................................................................................................................. 51
14.
Adobe AIR ........................................................................................................................ 54
14.1.
Creando una aplicación con Adobe AIR .................................................................. 54
Anexo I: Instalación de Adobe Flex SDK ...................................................................................... 62
Anexo II: Creando y compliando una aplicación AIR con Adobe Flex SDK .................................. 62
2
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
Tabla de ilustraciones
Ilustración 1: Entorno Flex Builder ................................................................................................ 4
Ilustración 2: Editor de texto MXML ............................................................................................. 5
Ilustración 3: Editor visual de mxml .............................................................................................. 5
Ilustración 4: Ventana de creación de proyecto (Flex Builder) ..................................................... 6
Ilustración 5: Flex Builder, perspectiva de depuración ................................................................. 7
Ilustración 6: Proyecto FormularioVehiculos ................................................................................ 8
Ilustración 7: Ventana de creación de nuevo componente (Flex Builder) .................................... 9
Ilustración 8: Editor textual MXML ............................................................................................. 10
Ilustración 9: Editor visual ........................................................................................................... 10
Ilustración 10:Ventana de componentes .................................................................................... 11
Ilustración 11: Formulario de inserción de coches ..................................................................... 12
Ilustración 12: Ejemplo de formulario......................................................................................... 15
Ilustración 13: Formulario + Datagrid (1) .................................................................................... 20
Ilustración 14: Formulario + DataGrid (2) ................................................................................... 20
Ilustración 15: Ventana de propiedades A-Z de un componente (Flex Builder) ......................... 23
Ilustración 16: Ejemplo inserción de datos (1) ............................................................................ 26
Ilustración 17: Ejemplo inserción de datos (2) ............................................................................ 26
Ilustración 18: Buscador de Yahoo de prueba ............................................................................ 27
Ilustración 19: Proyecto Flex con BlazeDS .................................................................................. 32
Ilustración 20: Proyecto Flex con BlazeDS .................................................................................. 33
Ilustración 21: Ventana de propiedades de compilación (Flex Builder) ..................................... 43
Ilustración 22: Ventana de propiedades de archivo (Flex Builder) ............................................. 45
Ilustración 23: Vista de diseño del componente Historico.mxml ............................................... 52
Ilustración 24: Componente chat1.mxml modificado................................................................. 53
Ilustración 25: Ventana de creación de proyecto Adobe AIR ..................................................... 55
Ilustración 26: Prueba del editor de texto .................................................................................. 61
3
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
1. Adobe Flex SDK y Flex Builder
1.1.
Adobe Flex SDK
Adobe Flex SDK es un framework opensource de Adobe que nos permite crear complejas
aplicaciones cliente con ActionScript, además nos permite crear aplicaciones escritorio
utilizando Adobe AIR.
Es gratuito y funciona en Windows, Linux y Mac.
Instalación de Flex SDK:
1.2.
Flex Builder
Flex Builder es un entorno de desarrollo integrado (IDE) basado en Eclipse y desarrollado por
Adobe. Nos permite crear proyectos utilizando Flex SDK, tal como Eclipse hace con otros
lenguajes.
Las principales ventajas que ofrece son:
•
•
•
•
Reconocimiento dinámico de errores.
Detección de librerías.
Edición de archivos ActionScript y mxml
Interfaz visual para el diseño de componentes, utilizando la extensión MXML de Flex
SDK, que consiste en un lenguaje XML en el que definir un conjunto de componentes
Flex, permitiendo añadir código ActionScript.
El principal problema es que Flex Builder es una herramienta de pago, aunque es posible
conseguir una licencia para educación en la página de Adobe, proporcionando una
identificación que nos acredite como estudiantes o profesores.
En la ilustración inferior se puede ver el entorno Flex Builder:
Ilustración 1: Entorno Flex Builder
Editor de texto para archivos MXML:
4
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
Ilustración 2: Editor de texto MXML
Vista de diseño (visual) para el archivo MXML:
Ilustración 3: Editor visual de mxml
2. Primera aplicación
Para crear un nuevo proyecto hacemos clic en File/New/Flex Project
Se nos abrirá una ventana en la que introducir el nombre del proyecto y en la que podremos
elegir el tipo:
5
Adobe Flex SDK y Flex Builder 3
•
•
Universidad de Cádiz
Web application (Funciona con Flash Player)
Desktop application (Funciona con Adobe Air)
Para empezar crearemos una aplicación Web, por defecto. Introducimos un nombre para el
proyecto, por ejemplo Prueba, y pusamos “Finish”:
Ilustración 4: Ventana de creación de proyecto (Flex Builder)
3. MXML vs AS
En un proyecto Flex podemos añadir clases ActionScript o componentes MXML. Las clases
ActionScript son como cualquier clase de un lenguaje orientado a objetos, permiten herencia,
definir interfaces, etc. Las clases ActionScript son principalmente utilizadas para definir el
modelo de la aplicación, si bien es posible utilizar ActionScript para crear directamente vistas,
no es lo más indicado, ya que las clases ActionScript no pueden ser visualizadas con el editor
gráfico de Flex Builder.
Por otro lado, los componentes MXML son ficheros XML que siguen una determinada sintaxis
basada en etiquetas con los nombres de los elementos de Flex SDK, es algo parecido a un
fichero html pero mucho más potente y en el que se puede incorporar código ActionScript. La
principal ventaja de los ficheros MXML es que pueden ser visualizados con el editor gráfico de
Flex Builder, pudiendo crear interfaces fácilmente. Los componentes MXML son utilizados para
definir la vista de la aplicación.
Más adelante veremos ejemplos de uso de unos y otros.
6
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
4. Modo de depuración
Flex Builder tiene, al igual que Eclipse, perspectiva de depuración, a la que se accede a través
del botón “Open perspective” en la parte superior izquierda:
Ilustración 5: Flex Builder, perspectiva de depuración
El modo de depuración nos permite añadir “breakpoints” al código y añadir el comando trace()
a nuestro código ActionScript, que imprime cualquier cadena de caracteres que le pasemos
como parámetro, y la muestra por la consola de depuración.
5. Creando un formulario
Vamos a crear un primer proyecto en el que construiremos un formulario simple utilizando
MXML.
Primero creamos un proyecto con Flex Builder. Pulsamos File\New\Flex Project y le damos el
nombre “FormularioVehiculos”. Pulsamos “Finish”:
7
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
Ilustración 6: Proyecto FormularioVehiculos
Vamos a añadir un componente MXML al proyecto, por lo que pulsamos File\New\MXML
Component:
8
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
Ilustración 7: Ventana de creación de nuevo componente (Flex Builder)
Si nos fijamos, en la parte inferior de la ventana que se abre tenemos tres atributos:
Filename Nombre del componente
Base don Es el elemento gráfico en el que estará basado el componente, por defecto es
Canvas, que representa un fondo vacío en el que se pueden añadir libremente elementos,
como veremos a continuación. Alternativas similares a Canvas son HBox, que es parecido pero
limitando la colocación de los elementos de forma horizontal; VBox, limita la colocación de los
objetos pero de forma vertical, o Panel, que es como Canvas pero con una barra de título, etc.
Width y Height Anchura y altura iniciales.
Como nombre introducimos FormularioCoche, y dejamos las demás opciones por defecto.
Se nos abrirá directamente el editor textual del MXML:
9
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
Ilustración 8: Editor textual MXML
De momento no nos interesa, ya que vamos a construir un formulario simple, por lo que
podemos utilizar directamente el editor visual; pulsamos la pestaña “Design” en la parte
superior del editor:
Ilustración 9: Editor visual
Podemos ver el elemento Canvas en el centro, vacío de momento, y a la derecha la ventana de
propiedades; si no se ve debemos hacer clic en Windows\Flex Properties.
Vamos a añadir los elementos necesarios para construir un formulario que nos permita
insertar coches, para ello debemos tener abierta la pestaña de componentes “Components”, si
no la vemos debemos hacer clic en Window\Components, y aparecerá algo como lo mostrado
en la imagen inferior:
10
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
Ilustración 10:Ventana de componentes
Los componentes que nos interesan son TextInput, que es como su nombre indica un campo
de texto y el componente Label, que es una etiqueta de texto. Añadimos los elementos hasta
tener algo parecido a lo mostrado en la siguiente imagen:
11
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
Ilustración 11: Formulario de inserción de coches
El código es el siguiente: <mx:Script>
<![CDATA[
import modelo.Coche;
private var coche:Coche;
public function getCoche():Coche
{
return new Coche(marca.text, modelo.text,
combustible.text, parseInt(cilindrada.text), parseInt(potencia.text),
parseInt(puertas.int));
}
]]>
</mx:Script>
<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="400"
height="316">
<mx:Label x="82.5" y="19" text="Formulario de inserción de
coches:" fontWeight="bold" fontSize="12"/>
<mx:Label x="100" y="62" text="Marca:"/>
<mx:TextInput x="150" y="60"/>
<mx:Label x="92" y="88" text="Modelo:"/>
<mx:TextInput x="150" y="86"/>
<mx:Label x="62" y="114" text="Combustible:"/>
<mx:TextInput x="150" y="112"/>
<mx:Label x="74" y="142" text="Nº Puertas:"/>
12
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
<mx:TextInput x="150" y="140"/>
<mx:Label x="76" y="168" text="Cilindrada:"/>
<mx:TextInput x="150" y="166"/>
<mx:Label x="85" y="194" text="Potencia:"/>
<mx:TextInput x="150" y="192"/>
</mx:Canvas>
Ya tenemos nuestro primer componente, pero de poco nos sirve ya que ni siquiera está
enlazado con el archivo principal de la aplicación, que se debería llamar
“FormularioVehiculos.mxml”.
6. Creando un componente complejo
Ahora vamos a abrir el archivo “Main” de nuestro proyecto, “FormularioVehiculos.mxml” y nos
colocamos en la vista de diseño (editor visual):
Vamos a añadir un componente denominado TabNavigator, que se encuentra en la carpeta
“Navigators” de la ventana “Components” y lo vamos a colocar en la posición (0,0). Además
vamos a asignarle los valores “width=100%” y “height=100%”:
Le damos el nombre “Inserción de coches” en el atributo Label de la ventana de propiedades,
deberíamos tener algo como esto:
13
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
Ahora vamos a colocarle el formulario que antes hemos creado, nos vamos a la ventana
“Components” y abrimos la carpeta “Custom”, ahí debe aparecer “FormularioCoches”; lo
arrastramos dentro:
14
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
Ilustración 12: Ejemplo de formulario
Ahora si pulsamos “Run” en la barra de herramientas
resultado.
ejecutar podremos ver el
Como hemos añadido un componente “TabNavigator” vamos a aprovechar y a crear una
nueva pestaña muy parecida pero en este caso un formulario para motos que llamaremos
“FormularioMoto”, el código es el siguiente:
<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="400"
height="316">
<mx:Label x="100" y="62" text="Marca:"/>
<mx:TextInput x="150" y="60"/>
<mx:Label x="92" y="88" text="Modelo:"/>
<mx:TextInput x="150" y="86"/>
<mx:Label x="62" y="114" text="Combustible:"/>
<mx:TextInput x="150" y="112"/>
<mx:Label x="50" y="142" text="Tiene marchas:"/>
<mx:Label x="76" y="168" text="Cilindrada:"/>
<mx:TextInput x="150" y="166"/>
<mx:Label x="85" y="194" text="Potencia:"/>
<mx:TextInput x="150" y="192"/>
<mx:Label x="82.5" y="19" text="Formulario de inserción de
motos:" fontWeight="bold" fontSize="12"/>
<mx:ComboBox x="150" y="140" cornerRadius="0">
<mx:Array>
<mx:String>Sí</mx:String>
15
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
<mx:String>No</mx:String>
</mx:Array>
</mx:ComboBox>
</mx:Canvas>
Ahora añadimos una nueva pestaña a FormularioVehiculos y añadiremos nuestro nuevo
componente:
Si volvemos a ejecutar podemos ver que tenemos un pequeño navegador que nos permite
viajar entre nuestros dos componentes:
El problema es que ahora mismo de poco nos sirve nuestra aplicación.
7. Creando el modelo en el cliente
Vamos a crear el modelo de nuestra aplicación, en este caso tenemos dos formularios, uno
para la inserción de coches y otro para la inserción de motos.
Primero creamos una nueva carpeta denominada “modelo” dentro de la carpeta “src” del
proyecto.
Hacemos clic en File\New\ActionScript class y nombramos a nuestra nueva clase “Vehiculo”.
El código de Vehiculo será así:
package modelo
{
public class Vehiculo extends Object
{
public var marca:String;
public var model:String;
16
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
public var combustible:String;
public var cilindrada:int;
public var potencia:int;
public function Vehiculo(marca:String, model:String,
combustible:String, cilindrada:int, potencia:int)
{
this.marca = marca;
this.model = model;
this.combustible = combustible;
this.cilindrada = cilindrada;
this.potencia = potencia;
}
public function getMarca():String
{
return this.marca;
}
public function setMarca(marca:String):void
{
this.marca = marca;
}
public function getModel():String
{
return this.model;
}
public function setModel(model:String):void
{
this.model = model;
}
public function getCombustible():String
{
return this.combustible;
}
public function setCombustible(combustible:String):void
{
this.combustible = combustible;
}
public function getCilindrada():int
{
return this.cilindrada;
}
public function setCilindrada(cilindrada:int):void
{
this.cilindrada = cilindrada;
}
public function getPotencia():int
{
return this.potencia;
}
public function setPotencia(potencia:int):void
{
17
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
this.potencia = potencia;
}
}
}
Ahora vamos a crear una nueva clase ActionScript “Coche” que herede de vehículo y que
añada el atributo nPuertas de tipo int y sus correspondientes get y set:
package modelo
{
public class Coche extends Vehiculo
{
public var puertas:int;
public function Coche(marca:String, model:String,
combustible:String, cilindrada:int, potencia:int, puertas:int)
{
super(marca, model, combustible, cilindrada,
potencia);
this.puertas = puertas;
}
public function getPuertas():int
{
return this.puertas;
}
public function setPuertas(puertas:int):void
{
this.puertas = puertas;
}
}
}
Finalmente añadimos una clase ActionScript “Moto” que herede también de vehículo y que
añada el atributo tieneMarchas de tipo Boolean y sus correspondientes get y set:
package modelo
{
public class Moto extends Vehiculo
{
public var marchas:Boolean = false;
public function Moto(marca:String, model:String,
combustible:String, cilindrada:int, potencia:int, marchas:Boolean)
{
super(marca, model, combustible, cilindrada,
potencia);
this.marchas = marchas;
}
public function getMarchas():Boolean
{
return this.marchas;
}
public function setPuertas(marchas:Boolean):void
{
this.marchas = marchas;
}
18
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
}
}
Como se puede suponer a priori, las clases del modelo se utilizarán para el manejo de los
datos.
8. Visualización de datos (DataGrid)
Hasta ahora hemos construido dos formularios, uno para coches y otro para motos, el modelo
correspondiente y un navegador para viajar entre los dos formularios, pero nuestra aplicación
todavía no tiene ninguna utilidad.
Para dotarle de utilidad vamos a añadir en FormularioVehiculos a la derecha de cada
formulario un DataGrid, que es un componente que muestra un conjunto de datos formateado
en forma de tabla. El componente DataGrid se encuentra en la carpeta “Controls” de la
ventana “Components”.
Por defecto el componente “DataGrid” se nos añadirá en el código de esta forma:
<mx:DataGrid>
<mx:columns>
<mx:DataGridColumn headerText="Column 1" dataField="col1"/>
<mx:DataGridColumn headerText="Column 2" dataField="col2"/>
<mx:DataGridColumn headerText="Column 3" dataField="col3"/>
</mx:columns>
</mx:DataGrid>
Pero eso no nos interesa, así que lo dejamos vacío:
<mx:DataGrid>
</mx:DataGrid>
Establecemos sus propiedades de altura y anchura al 100% y les damos a cada uno un nombre,
en el atributo ID de la ventana de propiedades; coches y motos respectivamente. Deberemos
tener algo como esto:
19
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
Ilustración 13: Formulario + Datagrid (1)
Ilustración 14: Formulario + DataGrid (2)
20
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
El código de FormularioVehiculos quedaría como se muestra a continuación:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute" xmlns:ns1="*">
<mx:TabNavigator x="0" y="0" width="100%" height="100%"
id="navegador">
<mx:Canvas label="Inserción de coches" width="100%"
height="100%">
<ns1:FormularioCoche id="formularioCoche">
</ns1:FormularioCoche>
<mx:DataGrid id="coches" x="408" y="0">
</mx:DataGrid>
</mx:Canvas>
<mx:Canvas label="Inserción de motos" width="100%"
height="100%">
<ns1:FormularioMoto id="formularioMoto">
</ns1:FormularioMoto>
<mx:DataGrid x="408" y="0">
</mx:DataGrid>
</mx:Canvas>
</mx:TabNavigator>
</mx:Application>
Ahora vamos a editar nuestros componentes “FormularioCoche” y “FormularioMoto” de
forma que cada vez que introduzcamos los datos creemos un objeto de tipo “Coche” y un
objeto de tipo “Moto” respectivamente.
Abrimos el componente “FormularioCoche” y a cada uno de los campos a rellenar le damos el
mismo ID que los atributos de la clase coche:
<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="400"
height="316">
<mx:Label x="100" y="62" text="Marca:"/>
<mx:TextInput x="150" y="60" id="marca"/>
<mx:Label x="92" y="88" text="Modelo:"/>
<mx:TextInput x="150" y="86" id="model"/>
<mx:Label x="62" y="114" text="Combustible:"/>
<mx:TextInput x="150" y="112" id="combustible"/>
<mx:Label x="74" y="142" text="Nº Puertas:"/>
<mx:TextInput x="150" y="140" id="puertas"/>
<mx:Label x="76" y="168" text="Cilindrada:"/>
<mx:TextInput x="150" y="166" id="cilindrada"/>
<mx:Label x="85" y="194" text="Potencia:"/>
<mx:TextInput x="150" y="192" id="potencia"/>
<mx:Label x="82.5" y="19" text="Formulario de inserción de
coches:" fontWeight="bold" fontSize="12"/>
</mx:Canvas>
Hacemos lo mismo con el componente “FormularioMoto”:
<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="400"
height="316">
<mx:Label x="100" y="62" text="Marca:"/>
<mx:TextInput x="150" y="60" id="marca"/>
<mx:Label x="92" y="88" text="Modelo:"/>
<mx:TextInput x="150" y="86" id="model"/>
<mx:Label x="62" y="114" text="Combustible:"/>
21
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
<mx:TextInput x="150" y="112" id="combustible"/>
<mx:Label x="50" y="142" text="Tiene marchas:"/>
<mx:Label x="76" y="168" text="Cilindrada:"/>
<mx:TextInput x="150" y="166" id="cilindrada"/>
<mx:Label x="85" y="194" text="Potencia:"/>
<mx:TextInput x="150" y="192" id="potencia"/>
<mx:Label x="82.5" y="19" text="Formulario de inserción de
motos:" fontWeight="bold" fontSize="12"/>
<mx:ComboBox x="150" y="140" cornerRadius="0" id="marchas">
<mx:Array>
<mx:String>Sí</mx:String>
<mx:String>No</mx:String>
</mx:Array>
</mx:ComboBox>
</mx:Canvas>
Ahora vamos a crear en cada uno de los formularios un método que nos devuelva un objeto
Coche o Moto respectivamente con los datos de cada uno de los campos. Para añadir código
ActionScript a un componente MXML debemos escribir lo siguiente y lo colocamos justo
encima de la última etiqueta de cierre del MXML:
<mx:Script>
<![CDATA[
]]>
</mx:Script>
Dentro podemos añadir código ActionScript.
El método que devuelve un coche sería así:
<mx:Script>
<![CDATA[
import modelo.Coche;
public function getCoche():Coche
{
return new Coche(marca.text, model.text, combustible.text,
parseInt(cilindrada.text), parseInt(potencia.text),
parseInt(puertas.int));
}
]]>
</mx:Script>
El método que devuelve una moto sería muy similar:
<mx:Script>
<![CDATA[
import modelo.Moto;
public function getMoto():Moto
{
var marchasAux:Boolean = false;
if(marchas.selectedItem == "Sí")
{
marchasAux = true;
}
return new Moto(marca.text, model.text, combustible.text,
parseInt(cilindrada.text), parseInt(potencia.text), marchasAux);
}
]]>
</mx:Script>
22
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
Para evitar introducir valores no numéricos en los campos numéricos introducimos \0-9\ en el
atributo “restrict” de potencia, cilindrada y puertas:
Ilustración 15: Ventana de propiedades A-Z de un componente (Flex Builder)
9. Programando con eventos
Ya hemos añadido la gestión con el modelo, pero nos falta la inserción y visualización de datos
en el cliente. Para poder insertar los datos vamos a añadir un botón de inserción justo debajo
de los formularios de coche y moto, pero no en sus respectivos componentes, sino en
“FormularioVehiculo”:
23
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
Añadiremos un evento clic a cada uno de los botones, de forma que cada vez que pulsemos
uno se devuelva un objeto Coche o un Objeto Moto, con los datos del formulario, además
añadimos un identificador al componente FormularioCoche y otro a FormularioMoto dentro
de FormularioVehiculo, y a cada uno de los DataGrid añadidos:
Abrimos el editor de texto de FormularioVehiculo y los cambios a realizar son:
<ns1:FormularioCoche id="formularioCoche">
</ns1:FormularioCoche>
<ns1:FormularioMoto id="formularioMoto">
</ns1:FormularioMoto>
<mx:DataGrid id="coches" x="408" y="0">
</mx:DataGrid>
<mx:DataGrid x="408" y="0" id="motos">
</mx:DataGrid>
<mx:Button label="Insertar" click="insertarCoche()"/>
<mx:Button label="Insertar" click="insertarMoto()"/>
El código nos debe quedar así:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute" xmlns:ns1="*">
<mx:TabNavigator x="0" y="0" width="100%" height="100%"
id="navegador">
<mx:Canvas label="Inserción de coches" width="100%"
height="100%">
<ns1:FormularioCoche id="formularioCoche">
</ns1:FormularioCoche>
24
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
<mx:Button label="Insertar" click="insertarCoche()"
x="182" y="233"/>
<mx:DataGrid id="coches" x="408" y="0">
</mx:DataGrid>
</mx:Canvas>
<mx:Canvas label="Inserción de motos" width="100%"
height="100%">
<ns1:FormularioMoto id="formularioMoto">
</ns1:FormularioMoto>
<mx:Button label="Insertar" click="insertarMoto()"
x="180" y="232"/>
<mx:DataGrid x="408" y="0" id="motos">
</mx:DataGrid>
</mx:Canvas>
</mx:TabNavigator>
</mx:Application>
Ahora añadimos la correspondiente etiqueta:
<mx:Script>
<![CDATA[
]]>
</mx:Script>
Justo encima de </mx:Application> y creamos los métodos insertarMoto() e insertarCoche(),
de forma que el código nos quede así:
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import modelo.Moto;
import modelo.Coche;
private var arrayCoches:Array = new Array();
private var arrayMotos:Array = new Array();
private function insertarCoche():void
{
// Obtenemos una variable coche
var coche:Coche =
this.formularioCoche.getCoche();
// La insertamos en el DataGrid de coches
arrayCoches.push(coche);
coches.dataProvider = arrayCoches;
}
private function insertarMoto():void
{
// Obtenemos una variable moto
var moto:Moto = this.formularioMoto.getMoto();
// La insertamos en el DataGrid de motos
arrayMotos.push(moto);
motos.dataProvider = arrayMotos;
}
]]>
</mx:Script>
Debido a que las clases Coche y Moto heredan de la clase Objeto, sus atributos quedan
directamente parseados en el DataGrid correspondiente:
25
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
Ilustración 16: Ejemplo inserción de datos (1)
Ilustración 17: Ejemplo inserción de datos (2)
Ya tenemos una aplicación cliente, con un modelo asignado y gestión de datos, pero no
tenemos conexión con un servidor donde guardar los datos de forma duradera. Como veremos
a continuación existen varias formas de crear una aplicación cliente – servidor en Flex.
10.
Arquitectura de una aplicación web con Adobe Flex
SDK
La arquitectura de cualquier aplicación web implementada con Adobe Flex SDK es a priori
como la de cualquier aplicación web, tenemos un cliente (implementado en shockwave/flash)
y un servidor implementado a priori en cualquier lenguaje (esto dependerá también de la
tecnología que queramos usar).
La principal diferencia es que gracias a Flex SDK y a su tecnología similar a AJAX, podemos
gestionar los datos recibidos desde el servidor sin necesidad de estar cambiando de página,
incluso podemos definir una compleja estructura basada en objetos con la que gestionar
nuestra información y cambiar el estado de nuestra interfaz de forma dinámica en el cliente
sin necesidad de invocar a una nueva vista.
10.1. Cliente
El cliente estará programado mediante Flex SDK, obteniendo como resultado un objeto swf
(shockwave\flash), que actuará como única interfaz, sin necesidad de estar construyendo un
conjunto de vistas diferente.
El cliente podrá hacer llamadas asíncronas al servidor, con las que actualizar sus datos, estas
llamadas se podrán realizar de varias formas, como veremos a continuación.
26
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
10.2. Servidor
El servidor se construirá como en cualquier otra aplicación web, excluyendo de su
programación cualquier clase de vista, y por lo tanto cualquier redirección a una vista. La
programación del servidor se limitará a la recepción, emisión y gestión de datos, ya que la base
de datos que utilicemos sólo podrá ser manipulada de esta forma.
10.3. Comunicación cliente – servidor (Intefaz Http)
La forma más común de acceso al servidor es mediante el uso de la interfaz Http que Flex SDK
nos ofrece mediante su clase HttpService.
HttpService nos permite realizar llamadas http GET, POST, PUT y DELETE, establecer tanto la
cabecera como el cuerpo de la llamada y recibir los datos de respuesta de forma asíncrona.
Como ejemplo vamos a construir una pequeña aplicación que consistirá en un sencillo
buscador
web
basado
en
la
API
de
yahoo
http://developer.yahoo.com/search/web/V1/webSearch.html
Primer, paso, crear la interfaz gráfica:
Vamos a crear una sencilla interfaz gráfica con la que poder introducir los parámetros de la
búsqueda, la interfaz tendrá los siguientes elementos:
1.
2.
3.
4.
5.
6.
Input de texto para introducir las palabras de búsqueda.
Lista en forma de “comboBox” con la que seleccionar el número de resultados.
Lista en forma de “comboBox” con la que seleccionar el idioma de los resultados.
Lista en forma de “comboBox” con la que seleccionar el formato de los resultados.
Botón para confirmar la búsqueda.
Un elemento “DataGrid” que se rellenará con los resultados obtenidos.
El resultado deberá ser algo como esto:
Ilustración 18: Buscador de Yahoo de prueba
Una vez que tenemos la interfaz gráfica implementada, tenemos que realizar la llamada al
servidor, que en este caso será el servidor de Yahoo. Para ello utilizaremos la interfaz http de
Flex SDK, HttpService.
Primero, añadimos un evento click al botón de búsqueda, de forma que al pulsar el botón
realicemos una llamada:
<mx:Button label="Buscar" click="buscar()"/>
27
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
Ahora implementamos el método buscar:
private function buscar():void
{
var servicio:HTTPService = new HTTPService();
servicio.url =
"http://search.yahooapis.com/WebSearchService/V1/webSearch?appid=Yahoo
Demo";
servicio.method = "GET";
servicio.request = {
query:palabrasClave.text,
laguage:languageCB.text,
results:nResultadosCB.selectedItem,
format:formatCB.selectedItem
};
servicio.resultFormat = "xml";
// Añadimos los manejadores para procesar la respuesta
servicio.addEventListener(ResultEvent.RESULT, manejadorObtener);
servicio.addEventListener(FaultEvent.FAULT,
manejadorErrorObtener);
// Enviamos
servicio.send();
}
En el método buscar estamos realizando dos cosas:
1. Creando un objeto HttpService y asignándole los parámetros de llamada:
URL http://search.yahooapis.com/WebSearchService/V1/webSearch?appid=YahooDemo
Method GET
ResultFormat text/xml
2. Añadiendo dos manejadores, ya que la respuesta es asíncrono y deberemos crear
manejadores que estén escuchando hasta que recibamos respuesta:
Uno para el resultado:
servicio.addEventListener(ResultEvent.RESULT, manejadorObtener)
Otro para el caso de error:
servicio.addEventListener(FaultEvent.FAULT, manejadorErrorObtener)
El siguiente paso es implementar los manejadores:
El manejador de error es muy sencillo, sólo sirve para indicarnos que se ha producido un error
en la llamada:
private function manejadorErrorObtener(event:FaultEvent):void
{
Alert.show("Error al obtener el listado de videos");
}
El manejador del resultado es algo más complejo, ya que debe recoger la respuesta, en
formato XML y procesarla de forma que se muestren los resultados correctamente:
private function manejadorObtener(event:ResultEvent):void
{
var response:String = event.result.toString();
var xmlDoc:XMLDocument;
try
{
// Comprobamos si el resultado es un XML
xmlDoc = new XMLDocument(response);
28
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
// Procesamos el XML
var decoder:SimpleXMLDecoder = new SimpleXMLDecoder(true);
var resultObj:Object = decoder.decodeXML(xmlDoc);
resultados.dataProvider = resultObj.ResultSet.Result;
}
catch(error:Error)
{
Alert.show("Error en el formato de la respuesta");
}
}
Lo que estamos haciendo con este método es capturar la respuesta, que viene en el objeto
event de entrada y procesarla como un XML.
Por defecto, en ActionScript, cualquier objeto cuyo contenido es un XML es tratado como un
Array, en este caso la estructura es:
<ResultSet>
<Result>…</Result>
…
<Result>…</Result>
</ResultSet>
Es decir, tenemos un nodo “ResultSet” con un conjunto de nodos hijos “Result”, por lo que si
accedemos a resultObj.ResultSet, lo que nos devuelve es un array de un solo elemento, el
nodo “ResultSet”, y si accedemos a “resultObj.ResultSet.Result”, lo que obtenemos es un array
con tantos elementos como nodos “Result” existan.
De hecho, podríamos recorrerlo de esta forma:
for(var i:int = 0; i < resultObj.ResultSet.Result.length; i++)
{
Alert.show(resultObj.ResultSet.Result[i]);
}
El ejemplo de buscador es un caso muy sencillo, pero puede ser extendido a cualquier modelo,
pudiendo crear cualquier aplicación web basada en la comunicación entre el cliente y el
servidor utilizando objetos HttpService.
El principal inconveniente de utilizar HttpService es que el servidor destino debe contener en
su directorio raíz un archivo crossdomain.xml como el siguiente:
<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM
"http://www.adobe.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
<site-control permitted-cross-domain-policies="master-only"/>
<allow-access-from domain="*" secure="false"/>
<allow-http-request-headers-from domain="*"
headers="SOAPAction"/>
</cross-domain-policy>
Esto es necesarios para que nuestro objeto shockwave/flash pueda recibir las respuestas del
servidor y viceversa.
Otra funcionalidad que puede ser necesaria en nuestra aplicación cliente-servidor, es la de
descarga y subida de archivos, esto se consigue fácilmente mediante la combinación de las
clases URLRequest y FileReference, la única particularidad es que el objeto FileReference
utilizado debe ser una variable de la clase.
29
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
10.4. BlazeDS
BlazeDS es una tecnología opensource desarrollada por Adobe y basada en servidor Java, de
hecho utilizada tomcat como base. BlazeDS permite la comunicación de aplicaciones Web y de
Escritorio (Adobe AIR) creadas con Flex con un servidor java de cuatro formas distintas:
•
•
•
Paso de mensajes (Message Service)
Objeto Remoto (Remoting Service)
Proxy Service
BlazeDS puede descargarse desde la página:
http://flexorg.wip3.adobe.com/blazeds/3.0.x/milestone/3978/blazeds-turnkey-3.2.0.3978.zip
Su instalación es como la de cualquier tomcat, sólo hace falta extraerlo en un directorio
destino.
10.4.1. Productor – Consumidor (Message Service)
La arquitectura productor consumidor se basa en un productor, que envía mensajes (pull) y un
consumidor que los recibe (push). Esta estructura es la utilizada para aplicaciones como chats,
en las que un consumidor, el servidor, recibe los mensajes de un conjunto de clientes, que son
los productores y que a su vez pueden acceder a los mensajes publicados por sus compañeros.
Si bien esta estructura puede tener otros usos, siendo el ejemplo más sencillo de modelo
productor – consumidor un chat, vamos a implementar uno utilizando BlazeDS y Flex Builder.
Primero crearemos la parte del servidor:
Si accedemos al directorio de BlazeDS, podemos observar que dentro hay una carpeta
“tomcat”. La estructura del tomcat se ha respetado y dentro podremos encontrar la carpeta
“webapps” donde se encuentran nuestras aplicaciones web.
En este caso podemos encontrar una carpeta con aplicaciones de ejemplo “samples” y una
carpeta denominada “blazeds” en la que se encuentra una estructura genérica que define
servicios para paso de mensajes, comunicación con objetos remotos y por proxy.
En este caso vamos a crear una nueva carpeta dentro de “webapps” que llamaremos “chat”.
Dentro de esa carpeta copiaremos el contenido del directorio “blazeds”.
Si accedemos a “WEB-INF/flex” podemos ver cuatro xmls:
•
•
•
•
messaging-config.xml para la definición del servicio de mensajes
proxy-config.xml para la definición del servicio de proxy
remoting-config.xml para la definición del servicio de objetos remotos
services-config.xml para la definición global de servicios
En nuestro caso, como queremos crear un servicio de mensajes, ya que vamos a implementar
una estructura de comunicación push/pull, deberemos editar los ficheros “messagingconfig.xml” y “services-config.xml”.
En “messaging-config.xml” añadimos lo siguiente:
<?xml version="1.0" encoding="UTF-8"?>
<service id="message-service"
class="flex.messaging.services.MessageService">
<adapters>
<adapter-definition id="actionscript"
class="flex.messaging.services.messaging.adapters.ActionScriptAdapter"
default="true" />
30
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
<!-- <adapter-definition id="jms"
class="flex.messaging.services.messaging.adapters.JMSAdapter"/> -->
</adapters>
<default-channels>
<channel ref="my-polling-amf"/>
</default-channels>
<destination id="chat"/>
</service>
Añadimos la línea <destination id="chat"/> justo encima de la etiqueta </service>. Esta línea
indica que el servicio destino se va a denominar chat. En el cliente se deberá especificar el id
de destino.
El canal de comunicación viene definido en el archivo services-config.xml, en este caso,
utilizaremos el definido por defecto.
<channel-definition id="my-amf"
class="mx.messaging.channels.AMFChannel">
<endpoint
url="http://{server.name}:{server.port}/{context.root}/messagebroker/a
mf" class="flex.messaging.endpoints.AMFEndpoint"/>
</channel-definition>
Ya tenemos la parte del servidor implementada, no necesitamos nada más, ya que de ello se
ocuparán las librerías definidas en BlazeDS.
Ahora debemos crear la parte del cliente:
Para ello creamos un nuevo proyecto con Flex Builder, presionamos File/New/Flex Project:
31
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
Ilustración 19: Proyecto Flex con BlazeDS
En “Application server type” marcamos J2EE y seleccionamos “Use remote object Access
service” y “LiveCycle Data Services”. Pulsamos “Next”.
Ahora es cuando necesitamos introducir los datos del servidor:
32
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
Ilustración 20: Proyecto Flex con BlazeDS
En Root folder introducimos el directorio de “blazeds” dentro de la carpeta “webapps”,
quedaría “BlazeDS_HOME/tomcat/webapps/blazeds”.
En Roo URL introducimos la URL destino, en este caso, como BlazeDS viene configurado en el
puerto 8400, la URL será: http://localhost:8400/blazeds.
Finalmente en Context root introducimos el directorio raiz de la aplicación web, en este caso
“/blazeds”.
Pulsamos “Finish” para terminar.
Ahora debemos editar el mxml principal de nuestra aplicación, en este caso “chat.mxml”. En el
que añadiremos lo siguiente:
Primero el productor y el consumidor de mensajes:
<mx:Consumer id="consumer" destination="chat"
message="messageHandler(event.message)"/>
<mx:Producer id="producer" destination="chat"/>
En el atributo destination, debemos añadir el destino que anteriormente hemos especificado,
en este caso “chat”.
33
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
Añadimos los controles que nos permitirán crear la interfaz gráfica del chat. Un panel de texto
donde visualizar los mensajes enviados. Un input de texto donde escribir nuestros mensajes y
un botón para el envío.
<mx:Panel title="Chat" width="100%" height="100%">
<mx:TextArea id="log" width="100%" height="100%"/>
<mx:ControlBar>
<mx:TextInput id="msg" width="100%" enter="send()"/>
<mx:Button label="Send B" click="send()"/>
</mx:ControlBar>
</mx:Panel>
En el botón añadimos al evento “click” el método “send()” que ahora definiremos, para ello
añadiremos al mxml código ActionScript:
<mx:Script>
<![CDATA[
import mx.messaging.messages.AsyncMessage;
import mx.messaging.messages.IMessage;
private function send():void{
var message:IMessage = new AsyncMessage();
message.body.chatMessage = msg.text;
producer.send(message);
msg.text = "";
}
private function messageHandler(message:IMessage):void{
log.text += message.body.chatMessage + "\n";
}
]]>
</mx:Script>
El método send enviará un mensaje asíncrono al servidor (AsyncMessage), por lo que
deberemos añadir un manejador para capturar la respuesta (messageHandler) y mostrarla en
el área de texto, ya que al ser asíncrono puede llegar en cualquier momento y se la
asignaremos al consumidor.
El último añadido será la siguiente sentencia “creationComplete="consumer.subscribe()”, que
deberemos añadir a la etiqueta mx:Application, y que suscribe inmediatamente la aplicación
como consumidora de datos en el momento en que se crea.
Finalmente tendremos que tener un mxml como el que se muestra a continuación:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute" creationComplete="consumer.subscribe()">
<mx:Script>
<![CDATA[
import mx.messaging.messages.AsyncMessage;
import mx.messaging.messages.IMessage;
private function send():void{
var message:IMessage = new AsyncMessage();
message.body.chatMessage = msg.text;
producer.send(message);
msg.text = "";
}
private function messageHandler(message:IMessage):void{
log.text += message.body.chatMessage + "\n";
}
]]>
34
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
</mx:Script>
<mx:Consumer id="consumer" destination="chat"
message="messageHandler(event.message)"/>
<mx:Producer id="producer" destination="chat"/>
<mx:Panel title="Chat" width="100%" height="100%">
<mx:TextArea id="log" width="100%" height="100%"/>
<mx:ControlBar>
<mx:TextInput id="msg" width="100%" enter="send()"/>
<mx:Button label="Send B" click="send()"/>
</mx:ControlBar>
</mx:Panel>
</mx:Application>
Ya sólo hace falta probar el chat, para lo que presionamos el botón de ejecución de Flex
Builder. Además debemos tener arrancado el servidor tomcat.
Para añadir funcionalidad en la parte del servidor, podemos crear una clase java que se
subscriba al canal, de forma que podamos modificar los datos en el servidor.
10.4.2. Objeto Remoto (Remoting Service)
Mediante el servicio de objeto remoto (Remoting Service) podemos invocar desde nuestro
cliente Flex a objetos java en el servidor, pudiendo llamar a métodos del objeto y pudiendo
obtener un tipo primitivo, un array, un objeto, una colección de objetos, etc.
Para ello debemos definir una intefaz común del objeto tanto en el cliente como en el servidor.
Vamos
a
observar
el
ejemplo
de
BlazeDS
en
“BlazeDS_HOME/tomcat/webapss/samples/inventory” en el que desde el cliente invocamos a
un objeto Producto, que contiene una serie de atributos (en este caso estáticos, aunque el
objeto Producto podría acceder a una base de datos).
Primero analizaremos la parte del servidor:
Dentro del directorio inventory, abrimos la carpeta “WEB-INF/flex” y observamos el archivo
“remoting-config.xml”, la parte importante es la siguiente:
<destination id="product">
<properties>
<source>ProductService</source>
</properties>
</destination>
En el XML se ha añadido un destino, al que referenciaremos desde Flex, llamado “product” y
añadimos una propiedad “source” llamada “ProductService”, que es una clase java con un
conjunto de métodos que utilizan la clase “Product”.
El canal utilizado en este caso está definido en “services-config.xml”, se utilizará el canal
creado por defecto para comunicación de objetos remotos:
<channel-definition id="my-amf"
class="mx.messaging.channels.AMFChannel">
<endpoint
url="http://{server.name}:{server.port}/{context.root}/messagebroker/a
mf" class="flex.messaging.endpoints.AMFEndpoint"/>
</channel-definition>
Una vez configurado el servidor vamos a analizar la implementación del mismo, tenemos dos
clases
“Product.java”
y
“ProductService.java”
dentro
de
la
carpeta
“BlazeDS_HOME\tomcat\webapps\samples\WEB-INF\src\flex\samples\product”.
35
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
Si abrimos Product.java podemos observar que la clase implementa la interfaz “Serializable”,
esto es necesario debido a que Product.java va a ser un objeto que se va a enviar entre el
cliente y el servidor, a través del servicio de objeto remoto.
Por otro lado si abrimos ProductService.java podemos ver que contiene un conjunto de
métodos públicos, estos métodos podrán ser invocados desde el cliente Flex. Los métodos
podrán devolver tipos primitivos, arrays, cadenas de texto o incluso objetos Product y
colecciones de objetos Product, para lo que tendremos que definir una clase Product.as
equivalente en el servidor.
Finalmente necesitamos dos clases auxiliares para la conexión con la base de datos de ejemplo
de
BlazeDS
que
no
vamos
a
analizar
y
que
se
encuentran
en
“BlazeDS_HOME\tomcat\webapps\inventory\WEB-INF\classes\flex\samples\”:
-
ConnectionHelper.java
DAOException.java
Con todo esto ya está definida por completo la parte del servidor.
Ahora vamos a analizar la parte del cliente:
Para poder analizar mejor la parte del cliente vamos a crar un proyecto llamado inventory de la
siguiente forma.
En la pantalla de creación de proyecto, en “Application server type” marcamos J2EE y
seleccionamos “Use remote object Access service” y “LiveCycle Data Services”. Pulsamos
“Next”.
Ahora es cuando necesitamos introducir los datos del servidor. Introducimos los mismos datos
que en la imagen mostrada a continuación, de acuerdo a la configuración de nuestro equipo:
36
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
El código del cliente se encuentra en BlazeDS_HOME\tomcat\webapps\samplesWEB-INF\flexsrc\flex-src.zip. Podemos extraer su contenido en el worspace de Flex Builder, o podemos
extraerlo y copiar el contenido de la carpeta “inventory” dentro de flex-src.zip en nuestro
proyecto Flex.
En inventory tenemos el siguiente contenido:
•
•
•
Directorio assets Contiene un conjunto de imágenes a utilizar en el cliente
styles.css Es una hoja de estilo utilizada en el cliente
Product.as Es la clase equivalente a Product.java y que utilizaremos para manejar los
objetos “Product” que recibamos del servidor, así como para enviar objetos “Product”
al servidor.
Si observamos el código de product podemos ver lo siguiente:
package
{
[Bindable]
[RemoteClass(alias="flex.samples.product.Product")]
public class Product
{
public function Product()
{
37
Adobe Flex SDK y Flex Builder 3
}
public
public
public
public
public
public
var
var
var
var
var
var
Universidad de Cádiz
productId:int;
name:String;
category:String;
price:Number = 0;
description:String;
qtyInStock:int = 0;
}
}
Hemos añadido una etiqueta [Bindable], lo que conseguimos con esto es que si el objeto
Product cambia, todos los demás objetos que lo tengan asociados, estarán escuchando para
actualizar también los datos.
También se ha añadido una etiqueta [RemoteClass(alias="flex.samples.product.Product")], lo
que se consigue con esto es asociar la clase Product.as a la clase Product.java. Lo único que
necesitamos es que en ambas clases exista un conjunto de atributos equivalente.
•
•
Inventory.mxml Es el mxml de la aplicación
ProductForm.mxml Es un formulario con un conjunto de campos que permiten
visualizar un producto.
Vamos a analizar el código de la clase ProductForm.mxml:
Vemos que la clase tiene asociada una variable Product con una etiqueta [Bindable]
[Bindable]
public var product:Product;
Con esto conseguimos que cuando se realice un cambio sobre la variable Product, se actualice
inmediatamente en ProductForm.mxml.
private function save():void
{
if (nameValidator.validate().type ==
ValidationResultEvent.INVALID) return;
product.name = productName.text;
product.category = category.text;
product.price = Number(price.text);
product.qtyInStock = parseInt(qtyInStock.text);
product.description = description.text;
if (product.productId > 0)
srv.update(product);
else
srv.create(product);
}
private function createResult(event:ResultEvent):void
{
product = event.result as Product;
label = product.name;
}
private function removeResult(event:ResultEvent):void
{
parent.removeChild(this);
}
En el método save, cogemos los campos del formulario y llamamos a los métodos
srv.update(product) ó srv.create(product), siendo srv una referencia a una variable
38
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
“RemoteObject”, en este caso será un objeto remoto ProductService.java como veremos más
adelante, y los métodos create y update, métodos de la interfaz de ProductService.java.
También tenemos dos métodos que reciben un evento como parámetro, createResult y
removeResult; estos métodos son utilizados cuando se realiza una llamada “create” o
“remove” sobre el objeto remoto “srv” (métodos implementados en ProductService.java), de
forma que actualicemos el estado del formulario actual.
Finalmente, tenemos el objeto remoto:
<mx:RemoteObject id="srv" destination="product">
<mx:method name="create" result="createResult(event)"/>
<mx:method name="remove" result="removeResult(event)"/>
</mx:RemoteObject>
El atributo “destination” hace referencia al destino que anteriormente habíamos añadido en
“remoting-config.xml”.
También se han añadido dos métodos: create y remove, que hacen referencia a los métodos
create y remove de ProductService.java, y que tienen asociados dos manejadores de eventos,
“createResult” y “removeResult”.
•
SearchPopup.mxml Es una lista que muestra de forma dinámica los productos que
coinciden con los parámetros de búsqueda, en este caso se ha implementado una
búsqueda por nombre.
Vamos a analizar el código de SearchPopup.mxml:
Básicamente SearchPopup.mxml es un objeto List, que tiene asociado un manejador para
tratar los eventos click y keydown:
<mx:List xmlns:mx="http://www.adobe.com/2006/mxml"
dropShadowEnabled="true"
currentState="hidden"
labelField="name"
keyDown="searchKeyDownHandler(event)"
click="openSelectedItem()">
Como anteriormente, también tenemos un objeto remoto con el atributo “destination”
apuntando a “product”:
<mx:RemoteObject id="srv" destination="product"
result="resultHandler(event)"/>
El único método que invoca al objeto remoto es el método público “search”:
public function search(searchStr:String):void
{
dataProvider = null;
srv.getProduct(searchStr);
if (currentState == "hidden") currentState = "";
}
Lo que se hace aquí es invocar al método “getProduct” de “ProductService.java”, y actualizar el
contenido del objeto List por medio del manejador “resultHandler”:
private function resultHandler(event:ResultEvent):void
{
dataProvider = event.result as ArrayCollection;
if (dataProvider && dataProvider.length > 0)
{
selectedIndex = 0;
}
39
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
}
El contenido de la lista se actualiza siempre que actualizamos el atributo “dataprovider”.
10.4.3. Proxy Service
El servicio de proxy es similar a la interfaz HttpService mostrada anteriormente pero con la
ventaja de que el servidor llamado no necesita incluir un archivo crossdomain.xml, esto se
soluciona principalmente utilizando un proxy entre la llamada HttpService y el servidor, cosa
que se puede hacer fácilmente en cualquier servidor.
En BlazeDS tenemos un pequeño ejemplo de utilización del proxy service en la carpeta
BlazeDS_HOME/tomcat/webapps/samples/testdrive-httpservice. Vamos a analizarlo.
Parte del servidor:
Vamos a analizar los archivos de configuración del servidor en “WEB-INF\flex”. Primero
analizaremos el archivo “proxy-config.xml”, la parte que nos interesa es la siguiente:
<destination id="catalog">
<properties>
<url>/{context.root}/testdrive-httpservice/catalog.jsp</url>
</properties>
</destination>
La URL hace referencia a un archivo jsp que se encuentra en el mismo servidor y que llama a la
base de datos devolviendo un XML con una lista de productos.
La referencia al canal http la encontramos en:
<default-channels>
<channel ref="my-http"/>
<channel ref="my-amf"/>
</default-channels>
El canal http para la comunicación se encuentra definido en el archivo “services-config.xml”
que es donde se encuentran definidos todos los canales para los diferentes servicios, en este
caso el canal http presenta el siguiente aspecto:
<channel-definition id="my-http"
class="mx.messaging.channels.HTTPChannel">
<endpoint
url="http://{server.name}:{server.port}/{context.root}/messagebroker/h
ttp" class="flex.messaging.endpoints.HTTPEndpoint"/>
</channel-definition>
Al igual que en el ejemplo anterior se utilizan las clases “Product.java” que será el modelo, y la
clase “ProductService.java” que contendrá la interfaz del servicio.
Ambas clases se pueden encontrar dentro de BlazeDS, en la carpeta:
BlazeDS_HOME\tomcat\webapps\samples\WEB-INF\src\flex\samples\product
Cliente:
El cliente va a consistir en dos archivos, un MXML que muestra la lista de productos utilizando
un componente “DataGrid” y un jsp que como hemos mencionado antes devuelve un XML con
los productos que se encuentran en la base de datos.
El código del cliente se encuentra en BlazeDS_HOME\tomcat\webapps\samplesWEB-INF\flexsrc\flex-src.zip, en la carpeta “testdrive-httpservice”. Vamos a crear un proyecto en Flex
Builder al que nombraremos “testdrive-httpservice”.
40
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
En la pantalla de creación de proyecto, en “Application server type” marcamos J2EE y
seleccionamos “Use remote object Access service” y “LiveCycle Data Services”. Pulsamos
“Next”.
En la siguiente pantalla introducimos los datos tal como aparece en la imagen, pero adaptados
a nuestro equipo:
Ahora podemos copiar el contenido de la carpeta “testdrive-httpservice” de
BlazeDS_HOME\tomcat\webapps\samplesWEB-INF\flex-src\flex-src.zip en nuestro proyecto o
extraerlo en el directorio del mismo.
Vamos a analizar el código del cliente:
Vemos que hay dos archivos, el jsp (catalog.jsp) que mencionamos antes, cuyo código es:
<%@page import="flex.samples.product.ProductService,
flex.samples.product.Product, java.util.List"%>
<?xml version="1.0" encoding="utf-8"?>
<catalog>
<%
ProductService srv = new ProductService();
List list = null;
list = srv.getProducts();
Product product;
41
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
for (int i=0; i<list.size(); i++)
{
product = (Product) list.get(i);
%>
<product productId="<%= product.getProductId()%>">
<name><%= product.getName() %></name>
<description><%= product.getDescription() %></description>
<price><%= product.getPrice() %></price>
<image><%= product.getImage() %></image>
<category><%= product.getCategory() %></category>
<qtyInStock><%= product.getQtyInStock() %></qtyInStock>
</product>
<%
}
%>
</catalog>
El XML devuelto tiene la estructura:
<catalog>
<product>…</product>
…
<product>…</product>
</catalog>
Es decir, un objeto “catalog” compuesto por n objetos “product”.
El código archivo MXML (main.mxml) es el siguiente:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
backgroundColor="#FFFFFF">
<mx:HTTPService id="srv" destination="catalog" useProxy="true"/>
<mx:DataGrid dataProvider="{srv.lastResult.catalog.product}"
width="100%" height="100%"/>
<mx:Button label="Get Data" click="srv.send()"/>
</mx:Application>
Vemos que sólo está compuesto por un elemento HTTPService (srv), con el atributo
destination igual a “catalog” que como hemos visto antes en el archivo de configuración del
proxy “proxy-config.xml” apunta a catalog.jsp; y el atributo useProxy a “true”, de forma que no
sea necesario un archivo crossdomain.xml en el servidor.
El objeto DataGrid se rellena automáticamente debido a que el atributo dataprovider apunta
directamente al conjunto de productos en forma de XML devuelto por catalog.jsp:
dataProvider="{srv.lastResult.catalog.product}"
Ya que como hemos visto en ejemplos anteriores, el componente “Object” de ActionScript, al
recibir un XML, lo parsea automáticamente, en este caso srv.lastResult devuelve un objeto de
tipo “Object” que se puebla directamente con los datos devueltos por la respuesta.
10.5. Localización de aplicaciones
Las aplicaciones creadas con Flex SDK disponen de gestión de localización, es decir, podemos
adaptar nuestras aplicaciones a distintos idiomas.
Las localizaciones disponibles por defecto son en_US y jp_JP. Si queremos añadir nuevas
localizaciones a Flex SDK debemos crear una carpeta con el nombre de la localización en
Flex_SDK_HOME\frameworks\locale, en nuestro caso vamos a añadir la carpeta es_ES
(español de España).
42
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
El
siguiente
paso
es
ejecutar
el
comando
copylocale
desde
Flex_SDK_HOME\frameworks\locale, que se encuentra en Flex_SDK_HOME\bin, de la
siguiente forma:
>copylocale en_US es_ES
Una vez que tenemos nuestra carpeta, debemos añadirla a los parámetros de compilación del
proyecto en Flex Builder. En este caso vamos a abrir nuestro proyecto “yahoo”, hacemos clic
derecho sobre el proyecto y abrimos la ventana de propiedades, y en la ventana de
propiedades nos colocamos en “Flex Compiler”:
Ilustración 21: Ventana de propiedades de compilación (Flex Builder)
Podemos ver que en el atributo “Additional compiler arguments” se ha añadido el parámetro
“–locale en_US”, para que a la hora de compilar reconozca el castellano, debemos añadir:
es_ES -source-path=../locale/{locale}
De forma que nos quede así:
43
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
Nota: Si estamos usando directamente Adobe Flex SDK, cada vez que compilemos con mxmlc
debemos pasar los parámetros de localización:
>mxmlc –locale=en_US,es_ES -source-path=../locale/{locale} Ejemplo.mxml
El siguiente paso es crear una carpeta denominada locale en el directorio de nuestro proyecto.
En esa carpeta debemos por cada idioma, una carpeta con su nombre, en nuestro caso la
estructura sería:
>Directorio del Proyecto
>locale
>en_US
>es_ES
Dentro de cada carpeta de localización debemos añadir un archivo .properties (los dos con el
mismo nombre), por ejemplo, myBundle.properties:
>Directorio del Proyecto
>locale
>en_US
>myBundle.properties
>es_ES
>myBundle.properties
En estos archivo tendremos los mensajes de nuestra aplicación en cada uno de los idiomas, en
nuestro caso queremos que los siguiente mensajes aparezcan en ambos idiomas:
“Buscar”, “NºResultados”, “Idioma”, “Formato”, “DEMO BUSCADOR DE YAHOO”:
En la carpeta, es_ES editamos myBundle.properties:
44
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
buscar=buscar
idioma=idioma
nResultados=NºResultados
formato=Formato
titulo=DEMO BUSCADOR DE YAHOO
En la carpeta en_US editamos myBundle.properties:
buscar=search
idioma=language
nResultados=NºResults
formato=Format
titulo=YAHOO SEARCH ENGINE DEMO
Debemos tener cuidado con la codificación de los archivos de propiedades, ya que puede que
no nos reconozca los acentos u otros caracteres especiales, para evitar problemas, nos
metemos en las propiedades de cada uno y seleccionamos en “Text file enconding” UTF-8:
Ilustración 22: Ventana de propiedades de archivo (Flex Builder)
Ahora debemos añadir a nuestro mxml principal, la siguiente etiqueta, justo debajo de
<mx:Application>:
<mx:Metadata>
[ResourceBundle("myBundle")]
</mx:Metadata>
El último paso es editar los label de nuestra aplicación para que aparezcan en el idioma
adecuado, de forma que sustituyamos el texto de cada una por lo siguiente, por ejemplo para
“Buscar”:
@Resource(bundle='myBundle', key='buscar')
45
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
ó para idioma:
@Resource(bundle='myBundle', key=’idioma’)
La estructura @Resource(bundle=’archivo de propiedades’, key=’key’) se utiliza dentro de las
etiquetas en un archive mxml, si queremos hacerlo en un archive ActionScript (.as) debemos
utilizar los siguiente:
resourceManager.getString("archivo de propiedades", "key")
Si editamos todas nuestras etiquetas, el código resultante es el siguiente:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute" backgroundGradientAlphas="[1.0, 1.0]"
backgroundGradientColors="[#D2E0FA, #F1F290]">
<mx:Metadata>
[ResourceBundle("myBundle")]
</mx:Metadata>
<mx:Text x="10" y="10" text="@Resource(bundle='myBundle',
key='titulo')" fontWeight="bold" fontSize="15"/>
<mx:HBox x="10" y="42" width="100%">
<mx:TextInput id="palabrasClave"/>
<mx:Button label="@Resource(bundle='myBundle',
key='buscar')" click="buscar()"/>
</mx:HBox>
<mx:HBox x="10" y="72" width="100%" backgroundColor="#6F98F4">
<mx:Label text="@Resource(bundle='myBundle',
key='nResultados')" fontWeight="bold"/>
<mx:ComboBox id="nResultadosCB" cornerRadius="0">
<mx:Array>
<mx:String>10</mx:String>
<mx:String>20</mx:String>
<mx:String>30</mx:String>
<mx:String>40</mx:String>
<mx:String>50</mx:String>
</mx:Array>
</mx:ComboBox>
<mx:Label text="@Resource(bundle='myBundle', key='idioma')"
fontWeight="bold"/>
<mx:ComboBox cornerRadius="0" id="languageCB">
<mx:Array>
<mx:String>es</mx:String>
<mx:String>en</mx:String>
<mx:String>fr</mx:String>
<mx:String>de</mx:String>
</mx:Array>
</mx:ComboBox>
<mx:Label text="@Resource(bundle='myBundle',
key='formato')" fontWeight="bold"/>
<mx:ComboBox id="formatCB">
<mx:Array>
<mx:String>any</mx:String>
<mx:String>html</mx:String>
<mx:String>msword</mx:String>
<mx:String>pdf</mx:String>
<mx:String>ppt</mx:String>
<mx:String>rrs</mx:String>
<mx:String>txt</mx:String>
<mx:String>xls</mx:String>
</mx:Array>
46
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
</mx:ComboBox>
</mx:HBox>
<mx:DataGrid x="10" y="102" id="resultados" width="100%"
height="100%">
</mx:DataGrid>
<mx:Image x="264" y="10" source="img/logoyahoo.png"/>
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.rpc.xml.SimpleXMLDecoder;
import mx.rpc.events.FaultEvent;
import mx.controls.Alert;
import mx.rpc.events.ResultEvent;
import mx.rpc.http.HTTPService;
private function buscar():void
{
// Debemos obtener la estructura por http
var servicio:HTTPService = new HTTPService();
servicio.url =
"http://search.yahooapis.com/WebSearchService/V1/webSearch?appid=Yahoo
Demo";
servicio.method = "GET";
var adult_ok:int = 0;
servicio.request = {
query:palabrasClave.text,
laguage:languageCB.text,
results:nResultadosCB.selectedItem,
format:formatCB.selectedItem
};
servicio.resultFormat = "xml";
// Añadimos los manejadores para procesar la
respuesta
servicio.addEventListener(ResultEvent.RESULT,
manejadorObtener);
servicio.addEventListener(FaultEvent.FAULT,
manejadorErrorObtener);
// Enviamos
servicio.send();
}
private function
manejadorObtener(event:ResultEvent):void
{
var response:String = event.result.toString();
var xmlDoc:XMLDocument;
try
{
// Comprobamos si el resultado es un XML
xmlDoc = new XMLDocument(response);
// Procesamos el XML
var decoder:SimpleXMLDecoder = new
SimpleXMLDecoder(true);
var resultObj:Object =
decoder.decodeXML(xmlDoc);
resultados.dataProvider =
resultObj.ResultSet.Result;
}
catch(error:Error)
{
Alert.show("Error en el formato de la
respuesta");
47
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
}
}
private function
manejadorErrorObtener(event:FaultEvent):void
{
Alert.show("Error al obtener el listado de
videos");
}
]]>
</mx:Script>
</mx:Application>
Si ejecutamos nuestra aplicación, veremos que se muestra en español, esto es debido a que el
swf reconoce la región donde nos encontramos. Más adelante, veremos como poder
seleccionar el idioma del swf pasándole parámetros http.
10.6. Paso de parámetros http a un swf
Un objeto shockwave/flash puede recibir parámetros http por medio del método GET, ya que
solamente los puede recibir leyéndolos de la URL por la que es invocado.
En nuestro caso vamos a añadir un parámetro lang a nuestra demo de buscador de yahoo con
el fin de poder seleccionar el idioma que muestre la aplicación.
Vamos a crear un método init dentro de yahoo.mxml que se lance inmediatamente después
que la aplicación se haya cargado en el navegador, para ello tenemos que hacer dos cosas:
1. Asociar al evento “creationComplete” el método “init()”. Esto lo hacemos en la
etiqueta <mx:Application> añadiendo creationComplete=”init()”, de forma que
tengamos:
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute" creationComplete="init()">
2. Ahora debemos crear un método init() dentro del espacio para añadir código
ActionScript, el método init comprobará que existe un parámetro lang y
posteriormente comprobará su valor:
private function init():void
{
// Variables flashVars
var params:Object = this.parameters;
// Si nos han pasado un parámetro con el lenguaje
if(params.lang)
{
var language:String = params.lang;
if(language == "en" || language.substr(0,2) == "en")
{
language = "en_US";
}
else if(language == "es" || language.substr(0,2) ==
"es")
{
language = "es_ES";
}
// Recorremos todos los lenguages que se encuentran
en el gestor de recursos
for(var i:int = 0; i <
resourceManager.localeChain.length; i++)
{
48
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
// Si el lengauge está contenido dentro de nuestro
gestor de recursos
if(language == resourceManager.localeChain[i])
{
// Establecemos el lenguage de la aplicación
resourceManager.localeChain = [language];
}
}
}
}
Las variables recibidas en el swf, llamadas FlashVars, se acceden a través del atributo de la
aplicación “parameters”. Fuera del “main” podemos acceder a las variables invocando
“Application.application.parameters”. Las variables se devuelven en forma de “Object” flash,
es decir es un objeto con un conjunto de atributos del que no sabemos a priori los nombres.
Podríamos obtener los nombres de todas las variables y sus valores de la siguiente forma:
var item:String;
var arrColl:ArrayCollection = new ArrayCollection();
/* Populate the ArrayCollection object with the FlashVars. */
for (item in params) {
Alert.show("Parámetro: " + item + " Valor: " + params[item]);
}
Este código, añadido al final del método “init”, muestra en ventanas de aviso, los parámetros
recibidos y sus correspondientes valores.
Si abrimos directamente el swf del buscador con un navegador y añadimos al final parámetros
http, veremos cómo se nos muestran en pantalla. Además, si pasamos un parámetro lang con
un valor correcto podremos seleccionar el idioma de la interfaz.
Pero esto no es del todo útil, ya que normalmente los objetos shockwave/flash vienen
embebidos en archivos html, o archivos jsp, php, etc. En este caso, lo que tenemos que hacer
es pasar los parámetros recibidos en el html, a nuestro swf. Esto se consigue capturando las
variables a través de código java o php dentro del html que envuelve al swf, como veremos a
continuación.
11.
Creación de un html que envuelva a el swf
El html que envuelve un swf, tiene tres funciones principales:
1. Añadir más contenido a la página.
2. Comprobar si el usuario tiene una versión adecuada de Flash player.
3. Pasar variables al objeto swf.
Por defecto, Flex Builder nos genera un html que envuelve el objeto swf generado. El html
tiene código javascript que nos permite comprobar si el usuario tiene una versión compatible
de Flash player, y en caso de que lo tenga lanza el swf.
También tiene código no javascript que permite embeber un swf en un html:
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
id="yahoo" width="100%" height="100%"
codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swf
lash.cab">
<param name="movie" value="yahoo.swf" />
<param name="quality" value="high" />
<param name="bgcolor" value="#869ca7" />
<param name="allowScriptAccess" value="sameDomain" />
49
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
<embed src="yahoo.swf" quality="high" bgcolor="#869ca7"
width="100%" height="100%" name="yahoo" align="middle"
play="true" loop="false" quality="high" allowScriptAccess="sameDomain"
type="application/x-shockwave-flash"
pluginspage="http://www.adobe.com/go/getflashplayer">
</embed>
</object>
El problema de este código html, es que no detecta que no tengamos instalado Flash player o
que no tengamos instalada la versión adecuada.
11.1. Paso de variables
Como se ha comentado antes, se pueden enviar variables a nuestro objeto shockwave/flash
desde el archivo que lo envuelve, si lo hacemos en un archivo html sólo podremos pasarle
variables estáticas previamente definidas, pero si lo hacemos en un archivo con capacidades
dinámicas, por ejemplo un .jsp o un php, podemos pasarle las variables que queramos, por
ejemplo, vamos a crear un .jsp que envie el parámetro lang a nuestro swf:
<html>
<head>
<style>
body { margin: 0px; overflow:hidden }
</style>
</head>
<%
String lang = (String) request.getParameter("lang");
%>
<body scroll="no">
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8444553540000" id="yahoo" width="100%" height="100%"
codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swf
lash.cab">
<param name="movie" value="yahoo.swf?lang=<%= lang%>" />
<param name="quality" value="high" />
<param name="bgcolor" value="#869ca7" />
<param name="allowScriptAccess" value="sameDomain" />
<embed src="yahoo.swf?lang=<%= lang%>" quality="high"
bgcolor="#869ca7" width="100%" height="100%" name="yahoo"
align="middle" play="true"loop="false" quality="high"
allowScriptAccess="sameDomain" type="application/x-shockwave-flash"
pluginspage="http://www.adobe.com/go/getflashplayer">
</embed>
</object>
</body>
</html>
Las variables que pasamos a un swf nos pueden servir para configurarlo o para instanciarlo,
por ejemplo, si tenemos un reproductor de video flash player, podemos enviarle una variable
para indicarle que vídeo debe reproducir, el reproductor se encargará más delante de
recuperar el video del servidor y reproducirlo
12.
Otras características de Adobe Flex SDK
12.1. Comunicación con interfaces externas (javascript)
Un objeto shockwave/flash puede utilizar código javascript del html que lo envuelve, e
invocarlo desde su código, pudiendo enviarle información y recuperarla de la misma forma a
través de su interfaz de comunicación.
50
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
Por ejemplo, podemos crear un método javascript que abra un popup y detectar si el
navegador lo ha bloqueado o no a través del valor devuelto por el método javascript, todo esto
desde nuestro código ActionScript.
Este sería el código javascript:
function abrirPopup( url )
{
try
{
var opciones="toolbar=no, Location=no, directories=no,
status=no, menubar=no, scrollbars=auto, resizable=yes,
fullscreen=yes";
var popup = window.open( url, “”, opciones );
if ( popup == null )
return false;
if ( window.opera )
if (!popup.opera)
return false;
}
catch(err)
{
return false;
}
return true;
}
Recibe como parámetro la url a abrir y devuelve un valor verdadero o falso en función de si lo
ha podido abrir o no.
Vamos a probrarlo en nuestro proyecto “yahoo”. Añadimos a la imagen o al título un evento
clic y le asignamos un método “abrirPopup()”.
El código del método abrirPopup() es el siguiente:
private function abrirPopup():void
{
var url:String = "http://www.google.es";
var exito:Boolean = ExternalInterface.call("abrirPopup", url,
"_self");
if (!exito)
{
Alert.show("Ventana emergente bloqueada, por favor habilite
las ventanas emergementes para este sitio en su navegador", "Aviso" );
}
}
La llamada “ExternalInterface.call” es la que se comunica con el código javascript, el primer
parámetro es el nombre del método, y los siguientes los parámetros a recibir (tantos como
sean necesarios, admitiendo también arrays de datos).
13.
SharedObjects
Los SharedObjects son objetos parecidos a las cookies, son pequeños archivos en los que se
pueden almacenar datos en el equipo del cliente para luego recuperarlos en esa misma sesión
o en otra.
51
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
Su tamaño está limitado a 100KB y sólo son accesibles por la aplicación que los creo, si bien,
tienen ciertos inconvenientes:
1. Se guardan en una ruta fija, por lo que es fácil encontrarlos.
2. Los datos se guardan en claro, si bien siempre se pueden cifrar en la aplicación antes
de escribirlos.
Vamos a crear un pequeño ejemplo extendiendo un poco la funcionalidad del chat que hemos
creado anteriormente, utilizando un SharedObject que guarde los mensajes que el propio
usuario ha ido enviando.
Abrimos el proyecto “chat1” y creamos un nuevo componente llamado “Historico”. El
componente va a estar basado en un “TitleWindow” y va a contener un “TextArea” donde se
mostrarán las conversaciones y al que asignaremos el identificador “areaTexto”.
Ilustración 23: Vista de diseño del componente Historico.mxml
En el “TitleWindow” establecemos el atributo “showCloseButton” a “true” y añadimos y
asignamos el evento “close” a un método llamado “cerrar()”; esto nos servirá para cerrar el
componente una vez abierto. El código resultante con el método cerrar incluido es el
siguiente:
<?xml version="1.0" encoding="utf-8"?>
<mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml"
layout="vertical" width="400" height="300" title="Histórico de
conversaciones" showCloseButton="true" close="cerrar()">
<mx:TextArea width="100%" height="100%" id="areaTexto"/>
<mx:Script>
<![CDATA[
import mx.managers.PopUpManager;
52
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
public function setTexto(texto:String):void
{
areaTexto.text = texto;
}
private function cerrar():void
{
PopUpManager.removePopUp(this);
}
]]>
</mx:Script>
</mx:TitleWindow>
Ahora nos vamos al componente chat1, debemos añadir un botón que lance un evento que
nos permita ver el histórico, por lo que añadimos un botón justo al lado del de envío de
mensajes, tal como muestra la siguiente imagen:
Ilustración 24: Componente chat1.mxml modificado
Ahora editamos el método “send()” del componente de forma que escriba en un SharedObject
el mensaje enviado más la fecha actual, de forma que tengamos algo parecido a lo mostrado a
continuación:
private function send():void{
var message:IMessage = new AsyncMessage();
message.body.chatMessage = msg.text;
producer.send(message);
var msgAux:String = msg.text;
msg.text = "";
// Escribimos el mensaje en el historial
var soHistorico:SharedObject =
SharedObject.getLocal("historico");
if(soHistorico.data.conversaciones != null)
53
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
{
soHistorico.data.conversaciones += msgAux + " enviado el "
+ (new Date()).toDateString() + "\n";
soHistorico.flush();
}
else
{
soHistorico.data.conversaciones = msgAux + " enviado el " +
(new Date()).toDateString() + "\n";
soHistorico.flush();
}
}
Ahora nos vamos al nuevo botón del componente y le añadimos un evento “click” al que
asignaremos un método “verConversaciones()”, cuyo código es el siguiente:
private function verConversaciones():void
{
var soHistorico:SharedObject =
SharedObject.getLocal("historico");
var his:Historico = Historico(PopUpManager.createPopUp(this,
Historico, false));
PopUpManager.centerPopUp(his);
his.setTexto(soHistorico.data.conversaciones);
}
El método “verConversaciones()” lee del SharedObject en el que hemos escrito previamente,
crea un objeto “Historico” mediante el gestor de “popups”, de forma que se muestre como
una ventana emergente, y le asigna el contenido leído.
Podemos probar el chat modificado y comprobar cómo las conversaciones se guardan a pesar
de haber el navegador o incluso después de reiniciar el servidor.
14.
Adobe AIR
Adobe AIR es una extensión de Flex SDK que nos permite crear aplicaciones de escritorio.
Funciona de forma similar a las aplicaciones flash para la web, pero en este caso se utiliza un
reproductor diferente al flash player, el reproductor Adobe AIR, que puede descargarse de la
siguiente página:
http://get.adobe.com/es/air/
Las aplicaciones se construyen de forma similar a las aplicaciones Flex, pero con la
particularidad de que podemos acceder al sistema de ficheros de nuestro ordenador, además
cada aplicación Adobe AIR puede acceder a su base de datos SQLite.
El principal problema que presenta Adobe AIR es su incapacidad para comunicarse
directamente con otras aplicaciones del sistema, aunque actualmente se están desarrollando
soluciones para paliar esta deficiencia, no son especialmente sencillas ni eficientes.
14.1. Creando una aplicación con Adobe AIR
Vamos a crear una sencilla aplicación con Adobe AIR, un editor de texto que nos permita
guardar y cargar nuestros ficheros de texto.
Para ello vamos a crear un nuevo proyecto Adobe AIR. Hacemos clic en File\New\Flex Project y
marcamos “Desktop Application”:
54
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
Ilustración 25: Ventana de creación de proyecto Adobe AIR
Le damos como nombre Editor. En la casilla “Application server type”, debemos tener puesto
“none”. Pulsamos “Finish”.
Como un editor de texto consta de una interfaz muy simple, podemos añadir directamente los
elementos en nuestro fichero “Editor.mxml”.
Añadimos un componente VBox que ocupe todo el espacio (altura y anchura al 100%), y
dentro un HBox y un TextArea, de forma que nos quede así:
55
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
Añadimos tres botones al HBox, uno para guardar, otro para “guardar como” y otro para abrir:
56
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
A los botones les llamaremos: botonGuardar, botonGuardarComo y botonAbrir y al TextArea,
areaTexto. De forma que el código nos quede así:
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute">
<mx:VBox x="0" y="0" width="100%" height="100%">
<mx:HBox width="100%">
<mx:Button label="Abrir" id="botonAbir"/>
<mx:Button label="Guardar" id="botonGuardar"/>
<mx:Button label="Guardar como"
id="botonGuardarComo"/>
</mx:HBox>
<mx:TextArea width="100%" height="100%" id="areaTexto"/>
</mx:VBox>
</mx:WindowedApplication>
Si arrancamos nuestra aplicación y vemos el resultado hasta ahora.
Vamos a crear una nueva clase ActionScript, denominada EntradaSalida, para gestionar la
lectura y escritura de nuestros ficheros en el sistema. Pulsamos File\New\ActionScript class.
Primero vamos a crear dos atributos en nuestra clase EntradaSalida, un atributo “buffer” de
tipo String y un atributo “fichero” de tipo File y sus correspondientes get y set:
57
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
package
{
import flash.filesystem.File;
public class EntradaSalida
{
private var buffer:String = null;
private var fichero:File = null;
public function EntradaSalida()
{
}
public function getBuffer():String
{
return this.buffer;
}
public function setBuffer(buffer:String):void
{
this.buffer = buffer;
}
public function getFichero():File
{
return this.fichero;
}
public function setFichero(fichero:File):void
{
this.fichero = fichero;
}
}
}
Ahora crearemos el método para “guardar como”:
public function guardarComo(texto:String):void
{
var file:File = File.desktopDirectory;
file.browseForSave("Guardar como:");
buffer = texto;
file.addEventListener(Event.SELECT, manejadorGuardarComo);
}
El método guardarComo recibe como parámetro de entrada una cadena de texto y crea un
objeto File que nos permite abrir el explorador del sistema para elegir la ubicación donde
guardar el fichero. Guardamos el texto en la variable auxiliar “buffer” de la clase y añadimos a
nuestra variable “file” un “listener” (manejadorGuardarComo) que escucha cuando el usuario
selecciona la ruta donde almacenar el fichero.
Ahora debemos implementar el “listener” que se llamará manejadorGuardarComo y que
recibe un evento como parámetro:
private function manejadorGuardarComo(event:Event):void
{
//Cogemos el nombre del fichero desde la ruta completa
var tmpArr:Array =
File(event.target).nativePath.split(File.separator);
//Creamos un nuevo fichero con la extensión por defecto
58
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
fichero = new File("file:///" + tmpArr.join(File.separator));
//Guardamos
var stream:FileStream = new FileStream();
stream.open(fichero, FileMode.WRITE);
stream.writeUTFBytes(buffer);
buffer = null;
stream.close();
}
El método manejadorGuardarComo crea un nuevo fichero (en una variable de la clase fichero),
lo guarda y a continuación escribe el contenido en el destino elegido.
Vamos ahora a implementar el método guardar:
public function guardar(texto:String):void
{
if(this.fichero == null)
{
guardarComo(texto);
}
else
{
//Guardamos
var stream:FileStream = new FileStream();
stream.open(this.fichero, FileMode.WRITE);
stream.writeUTFBytes(texto);
buffer = null;
stream.close();
}
}
El método “guardar” comprueba si existe un fichero asignado ya en nuestra clase, si lo hay
guarda directamente y si no lo hay, llamará al método “guardarComo”.
Finalmente crearemos el método “abrir”. El método abrir recibirá como parámetro un
“TextArea” que es el área de texto de nuestro editor, para poder cargar allí el contenido el
fichero abierto:
public function abrir(areaTexto:TextArea):void
{
// Almacenamos el área de texto
this.areaTexto = areaTexto;
// Lanzamos el explorador
var file:File = new File();
file.browseForOpen("Abrir");
file.addEventListener(Event.SELECT, manejadorAbrir);
}
Debido a que necesitamos añadir un listener que escuche cuando el usuario pulse abrir en el
explorador, tendremos que crear una variable auxiliar en la clase que almacene nuestra área
de texto entre ambas llamadas, ya que no se puede pasar parámetros entre un método y su
listener, lo que supone uno de los principales inconvenientes de los eventos.
private function manejadorAbrir(event:Event):void
{
//Cogemos la ruta del fichero y abrimos
fichero = new File(File(event.target).nativePath);
var stream:FileStream = new FileStream();
// Abrimos el fichero y cogemos su contenido
stream.open(fichero, FileMode.READ);
// Cargamos el texto leído en el área de texto
59
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
areaTexto.text = stream.readUTFBytes(fichero.size);
}
Ya tenemos nuestra clase “EntradaSalida” terminada, ahora sólo nos falta asociarla a la vista
gráfica de forma que cuando pulsemos los botones seamos capaces de abrir, editar y guardar
nuestros ficheros.
Abrimos el fichero “Editor.mxml”, y añadimos a cada botón un evento asociado al clic:
<mx:Button label="Abrir" id="botonAbir" click="abrir()"/>
<mx:Button label="Guardar" id="botonGuardar" click="guardar()"/>
<mx:Button label="Guardar como" id="botonGuardarComo"
click="guardarComo()"/>
Ahora debemos implementar los métodos asociados a los clic, primero añadimos las etiquetas
de script que nos permiten añadir código a nuestro mxml:
<mx:Script>
<![CDATA[
]]>
</mx:Script>
Justo encima de la etiqueta </mx:WindowedApplication>.
Dentro creamos una variable “EntradaSalida” y los tres métodos:
<mx:Script>
<![CDATA[
private var entradaSalida:EntradaSalida = new EntradaSalida();
private function abrir():void
{
}
private function guardar():void
{
}
private function guardarComo():void
{
}
]]>
</mx:Script>
Añadimos el contenido a los métodos invocando a nuestra variable “entradaSalida”, de forma
que el código completo nos quede de esta forma:
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute">
<mx:VBox x="0" y="0" width="100%" height="100%">
<mx:HBox width="100%">
<mx:Button label="Abrir" id="botonAbir"
click="abrir()"/>
<mx:Button label="Guardar" id="botonGuardar"
click="guardar()"/>
<mx:Button label="Guardar como" id="botonGuardarComo"
click="guardarComo()"/>
</mx:HBox>
<mx:TextArea width="100%" height="100%" id="areaTexto"/>
</mx:VBox>
<mx:Script>
60
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
<![CDATA[
private var entradaSalida:EntradaSalida = new
EntradaSalida();
private function abrir():void
{
this.areaTexto.text = entradaSalida.abrir();
}
private function guardar():void
{
entradaSalida.guardar(this.areaTexto.text);
}
private function guardarComo():void
{
entradaSalida.guardarComo(this.areaTexto.text);
}
]]>
</mx:Script>
</mx:WindowedApplication>
Ya tenemos nuestro editor multiplataforma implementado:
Ilustración 26: Prueba del editor de texto
Ahora sólo nos faltaría crear un instalable que nos permita instalarlo en nuestros equipos y
configurar las opciones de instalación, como serían asociar una extensión de fichero
determinados a nuestro programa, añadir un icono de instalación, etc. Todo esto se puede
configurar en el archivo “Editor-app.xml” que se ha creado automáticamente en nuestro
proyecto, para más información sobre el fichero de configuración consultar:
http://help.adobe.com/en_US/AIR/1.5/devappsflex/WS5b3ccc516d4fbf351e63e3d118666ade
46-7ff1.html
61
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
Cuando hayamos añadido todas las características de instalación que queramos, podemos
crear un instalable pulsando en “File\Export\Release Build”, aunque sólo nos permitirá
instalarlo en sistemas con Adobe AIR previamente instalado.
Anexo I: Instalación de Adobe Flex SDK
Flex
SDK
es
opensource,
se
puede
descargar
http://www.adobe.com/cfusion/entitlement/index.cfm?e=flex3sdk
en
la
dirección
Lo descargamos y extraemos en una nueva carpeta, por ejemplo “C:\Flex_HOME”
Lo primero es configurar Adobe Flex SDK, por lo que añadimos a las variables de entorno el
directorio bin (Flex_HOME/bin)
Existen dos comandos principales: compc y mxmlc
•
mxmlc se utiliza para construir los ficheros .swf, que pueden ser reproducidos por
Flash Player. Un ejemplo de compilación podría ser
>mxmlc Clase.as (Si se trata de una clase ActionScript)
>mxmlc Clase.mxml (Si se trata de un mxml)
Se generará un archivo .swf cada vez que compilemos y que podremos utilizar ya como
cliente, ya que se reproducirá con flash player.
•
compc se utiliza para construir bibliotecas, obteniendo ficheros .swc
Con Adobe Flex SDK y el comando mxmlc podemos crear cualquiera de los ejemplos del
manual, simplemente creando un directorio con los ficheros fuentes y compilando el fichero
Main del proyecto.
Anexo II: Creando y compliando una aplicación AIR con Adobe
Flex SDK
Adobe AIR viene incluido en Adobe Flex SDK, las aplicaciones Adobe AIR se pueden crear
utilizando Flex Builder, o creando directamente los proyectos en nuestro equipo y compilando
los ficheros de la siguiente forma.
Utilizando el comando amxmlc de Flex_HOME\bin podemos compilar nuestros proyectos AIR,
por ejemplo:
>amxmlc Editor.mxml
Se generará un archivo Editor.swf, pero no podremos reproducirlo ya que se trata de un .swf
para Adobe AIR. Para reproducirlo o para crear el instalador de la aplicación debemos crear un
archivo xml con la definición de los parámetros de la aplicación, en este caso se llamará Editorapp.xml:
<?xml version="1.0" encoding="UTF-8"?>
<application xmlns="http://ns.adobe.com/air/application/1.5">
<id>Editor</id>
<version>0.1</version>
<filename>Editor</filename>
<initialWindow>
<content>Editor.swf</content>
<visible>true</visible>
<systemChrome>none</systemChrome>
<transparent>true</transparent>
62
Adobe Flex SDK y Flex Builder 3
Universidad de Cádiz
<width>400</width>
<height>200</height>
</initialWindow>
</application>
Este archivo básicamente sirve para configurar la aplicación y la instalación de la misma, ya
que las aplicaciones Adobe AIR pueden instalarse, es importante que el xml contenga
correctamente la referencia al .swf generado. El xml puede configurar más opciones, una
descripción se encuentra en:
http://help.adobe.com/en_US/AIR/1.5/devappsflex/WS5b3ccc516d4fbf351e63e3d118666ade
46-7ff1.html
Para probar nuestra aplicación debemos ejecutar el comando adl de Flex_HOME\bin, de la
forma:
>adl Editor-app.xml
De esta forma se lanzará la aplicación y podremos probarla.
Para crear el instalador de nuestra aplicación debemos hacer dos cosas utilizando el comando
adt de Flex_HOME\bin:
1. Crear un certificado:
>adt -certificate -cn SelfSigned 1024-RSA sampleCert.pfx
samplePassword
2. Crear el instalador:
>adt -package -storetype pkcs12 -keystore sampleCert.pfx
Editor.air Editor-app.xml Editor.swf
63

Documentos relacionados

Desarrollo de Rich Entreprise Applications con Flex

Desarrollo de Rich Entreprise Applications con Flex Flex garantiza la compatibilidad entre navegadores, al ejecutarse sobre el FlashPlayer. Javascript puede tener comportamientos distintos dependiendo del navegador. Flex es compilado: ¾ Permite dete...

Más detalles