Manual Flex

63
Universidad de Cádiz Adobe Flex SDK y Flex Builder 3 Álvaro Martínez del Val 23/03/2010

Transcript of Manual Flex

Page 1: Manual Flex

Universidad de Cádiz

Adobe Flex SDK y

Flex Builder 3

Álvaro Martínez del Val 23/03/2010

Page 2: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

2

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. Paso de variables ..................................................................................................... 50

12. 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

Page 3: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

3

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

Page 4: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

4

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:

Page 5: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

5

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:

Page 6: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

6

• 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.

Page 7: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

7

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”:

Page 8: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

8

Ilustración 6: Proyecto FormularioVehiculos

Vamos a añadir un componente MXML al proyecto, por lo que pulsamos File\New\MXML

Component:

Page 9: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

9

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:

Page 10: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

10

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:

Page 11: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

11

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:

Page 12: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

12

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:"/>

Page 13: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

13

<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:

Page 14: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

14

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:

Page 15: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

15

Ilustración 12: Ejemplo de formulario

Ahora si pulsamos “Run” en la barra de herramientas ejecutar podremos ver el

resultado.

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>

Page 16: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

16

<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;

Page 17: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

17

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 {

Page 18: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

18

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; }

Page 19: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

19

}

}

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:

Page 20: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

20

Ilustración 13: Formulario + Datagrid (1)

Ilustración 14: Formulario + DataGrid (2)

Page 21: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

21

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:"/>

Page 22: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

22

<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>

Page 23: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

23

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”:

Page 24: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

24

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>

Page 25: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

25

<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:

Page 26: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

26

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.

Page 27: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

27

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. Input de texto para introducir las palabras de búsqueda.

2. Lista en forma de “comboBox” con la que seleccionar el número de resultados.

3. Lista en forma de “comboBox” con la que seleccionar el idioma de los resultados.

4. Lista en forma de “comboBox” con la que seleccionar el formato de los resultados.

5. Botón para confirmar la búsqueda.

6. 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()"/>

Page 28: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

28

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);

Page 29: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

29

// 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.

Page 30: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

30

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 “messaging-

config.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" />

Page 31: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

31

<!-- <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/amf" 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:

Page 32: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

32

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:

Page 33: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

33

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”.

Page 34: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

34

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"; } ]]>

Page 35: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

35

</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/amf" 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”.

Page 36: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

36

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:

Page 37: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

37

El código del cliente se encuentra en BlazeDS_HOME\tomcat\webapps\samplesWEB-INF\flex-

src\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() {

Page 38: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

38

} public var productId:int; public var name:String; public var category:String; public var price:Number = 0; public var description:String; public var 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

Page 39: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

39

“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; }

Page 40: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

40

}

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/http" 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\flex-

src\flex-src.zip, en la carpeta “testdrive-httpservice”. Vamos a crear un proyecto en Flex

Builder al que nombraremos “testdrive-httpservice”.

Page 41: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

41

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;

Page 42: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

42

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).

Page 43: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

43

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í:

Page 44: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

44

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:

Page 45: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

45

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')

Page 46: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

46

ó 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>

Page 47: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

47

</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");

Page 48: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

48

} } 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++) {

Page 49: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

49

// 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/swflash.cab"> <param name="movie" value="yahoo.swf" /> <param name="quality" value="high" /> <param name="bgcolor" value="#869ca7" /> <param name="allowScriptAccess" value="sameDomain" />

Page 50: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

50

<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-96B8-444553540000" id="yahoo" width="100%" height="100%" codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swflash.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.

Page 51: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

51

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.

Page 52: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

52

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;

Page 53: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

53

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)

Page 54: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

54

{ 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”:

Page 55: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

55

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í:

Page 56: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

56

Añadimos tres botones al HBox, uno para guardar, otro para “guardar como” y otro para abrir:

Page 57: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

57

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:

Page 58: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

58

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

Page 59: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

59

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

Page 60: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

60

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>

Page 61: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

61

<![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

Page 62: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

62

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 en la dirección

http://www.adobe.com/cfusion/entitlement/index.cfm?e=flex3sdk

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á Editor-

app.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>

Page 63: Manual Flex

Adobe Flex SDK y Flex Builder 3 Universidad de Cádiz

63

<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