You are on page 1of 57

Flex 4

HTTPService y XML
Datos en Aplicaciones Flex
• Las aplicaciones Flex
– presentan datos a los usuarios
– permiten modificar estos datos
• importados en tiempo de ejecución
– de un almacén de datos desde un servidor
– de una base de datos local en caso de Adobe AIR
• Flash Player y Adobe AIR no pueden
comunicarse directamente con datos de
servidor.
• Están diseñados para utilizar aplicaciones
servidoras intermedias usando otros
protocolos.
Acceso a DAtos

Flash Player
NO DIRECTAMENTE Datos de Servidor
Datos en
servidores LDAP
(Lightweight
Adobe AIR Aplicaciones middelware Diretory Access
a través de protocolos Protocol)
RPC
• Flex incluye tres componentes RPC
– Remote Procedure Call (RPC)
• permiten integrar aplicaciones Flex con aplicaciones de
servidor
– HTTPService
» el más flexible
• formato de mensaje que pueden intercambiarse
entre cliente y servidor en runtime
• intercambia datos como HTTP y XML
– RemoteObject
– WebService
Arquitectura REST
• Representational State Transfer.
• Es una arquitectura que permite implementar con varias
plataformas
– basadas en cliente
– basadas en servidor
• Una arquitectura RESTful permite a un sistema cliente local
recibir recursos almacenados en un sistema remota sin
necesitar una aplicación remota dinámica de servidor
• Podemos usar componentes HTTPService en una aplicación
REST porque puede comunicarse con sus peticiones como
un simple URL
Arquitectura Remote Procedure Call
• Arquitectura de software que permite operar
en un entorno remoto con funciones que
pueden ser ejecutadas por separado en varios
entornos.
• Esta arquitectura está implementada en Flex
con un servidor Web dinámico que responde a
peticiones HTTP
• Los tres componentes RPC se comunican con
el servidor con el protocolo HTTP
• Su diferencia está en el formato de los
mensajes
HTTPService
• Hace peticiones HTTP estándar a un servidor
Web
• Utiliza texto plano o XML como formato de
mensaje
• Podemos usar el componente HTTPSErvice
para crear aplicaciones RPC con cualquier
servidor, porque usando XML como formato
de mensaje es universal
RemoteObject
• Se comunica con aplicaciones servidor usando binario
AMF
• Sólo pueden funcionar con servidores que implementan
AMF
– Productos Adobe
• ColdFusion
• LiveCycle Data Services
• BlazeDS
– ASP.NET
– PHP
– Java Enterprise Edition (J2EE)
WebService
• Realiza peticiones y maneja las respuestas de
las aplicaciones servidoras con mensajes en
formato SOAP
• Sólo puede trabajar con servidores que usan
protocolo SOAP
– ColdFusion
– ASP.NET
– J2EE
Crear Aplicaciones de datos
• Tareas a realizar:
– Conectar a servicios alojados en servidores
remotos
– Convertir datos devueltos a clases value object
fuertemento tipados
– Enlazar datos devuletos a controles visuales como
DataGrid o List
– Gestionar entrada de datos en formularios
• Estas características están disponibles en los
servidores:
– Adobe ColdFusion
– LiveCycle Data Services
– BlazeDS
– PHP
– proveedores de servicios Web basados en SOAP
– proveedores de datos REST que devuelven datos
XML
Conectar a datos
• La fuente de datos será un fichero XML de
nuestra aplicación
Solución – UseDataConnection.mxml

• menú Data – Connect HTTP


• en Operations selecciona el fichero XML
• el código generado está creado en el paquete
Services
Vista Data/Services
• las conexiones de datos se gestionan en la
vista Data/Service
• Nos permite
– seleccionar el servicio
– modificar sus propiedades
– configurar el tipo de datos devueltos
– enlazar los datos a un control visual
• boton derecho en el control y enlazar a datos
objeto HTTPService
• Además de las opciones de generar el código,
podemos tb declarar y configurar el objeto
HTTPService
• Como siempre, un objeto HTTPService puede
ser declarado
– MXML
– código AS
Crear un objeto HTTPService
• <fx:Declarations>
• <s:HTTPService id=”myService”
url=”data/contacts.xml”/>
• </fx:Declarations>

– debemos declarar el HTTPService en la zona de


componentes no visuales
Declarar con AS
• import mx.rpc.http.HTTPService;
• private var myService:HTTPService =
• new HTTPService(“data/contacts.xml”);
Propiedades y métodos de HTTPService
• concurrency:String.
– regla que determina cómo gestionar múltiples llamadas
concurrentes
• method:String.
– método HTTP usado
• resultFormat:String.
– formato en el que los datos serán retornados
• showBusyCursor:Boolean.
• url:String.
– dirección a donde la petición se envia
url
• myHTTPService.url = “data/contacts.xml”;
• myHTTPService.url =
“http://www.myserver.com/data/contacts.xml”;
resultFormat
• array.
• e4x.
– XML bien formado que puede ser modificado con sintaxys EcmaScript para
XML (E4X)
• flashvars.
– datos con formato de par nombre/valor
– firstName=Joe&lastName=Smith
• object (por defecto).
– XML bien formado se retornan como un arbol de objetos AS
• text.
• xml.
– XML bien formato es retornado como un objeto XMLNode de AS que puede ser
gestionado con codigo Document Object Model (DOM).
Enviar y Recibir datos
• Enviamos una petición HTTP con el método
send() del objeto HTTPRequest
Solución
<s:Application
xmlns:fx=”http://ns.adobe.com/mxml/2009”
xmlns:s=”library://ns.adobe.com/flex/spark”
xmlns:mx=”library://ns.adobe.com/flex/mx”
creationComplete=»myService.send()»>
<fx:Declarations>
<s:HTTPService id=”myService” url=”data/contacts.xml”/>
</fx:Declarations>
</s:Application>
• También podemos enviar la petición con un
botón

• <s:Button label=”Make request”


click=”service.send()”/>
Comunicaciones Asíncronas
• Los componentes RPC envían y reciben datos
asíncronos.
– Cuando envias una petición, la máquina virtual de
Flash Player NO para la ejecución del código y
espera que los datos sean devueltos.
– Las peticiones se envían y las respuestas se
gestionan con event listeners.
Gestionar respuestas HTTPService
• con binding expression que hacen referencia a
los datos devueltos
– propiedad lastResult
• si resultFormat es por defecto un objeto, la propiedad
lastResult hace referencia a la clase ObjectProxy que
representa el documento XML
• con event listeners que ejecutan código As
cuando los datos son devueltos
• <mx:DataGrid
dataProvider=”{contactService.lastResult.data.
row}”/>

• el nodo row se repite varias veces en el fichero


XML (fichero contacts.xml)
Ejemplo
• Rellenar un DataGrid con los datos del fichero
contacts.xml
Solución – HTTPServiceWithBindings.mxml
<?xml version=”1.0” encoding=”utf-8”?>
<s:Application xmlns:fx=”http://ns.adobe.com/mxml/2009”
xmlns:s=”library://ns.adobe.com/flex/spark”
xmlns:mx=”library://ns.adobe.com/flex/mx”>
<s:layout>
<s:VerticalLayout horizontalAlign=”center” paddingTop=”20”/>
</s:layout>
<fx:Declarations>
<s:HTTPService id=”contactService” url=”data/contacts.xml”/>
</fx:Declarations>
<s:Button label=”Get Data” click=”contactService.send()”/>
<mx:DataGrid
dataProvider=”{contactService.lastResult.contacts.row}”/>
</s:Application>
Gestionar respuestas con event listener

• Gestionar result event


– Cuando los datos se devuelven de un servidor
• objeto HTTPService dispara un evento result
– mx.rpc.events.ResultEvent. This ResultEvent
• Podemos gestionar y guardar datos usando el evento result:
– Declarar bindable una variable fuera de cualquier función para que
actúe como referencia persistente en la devolución de datos.
– Podemos cast la variable a ArrayCollection si esperamos elementos
repetidos en los datos.
• import mx.collections.ArrayCollection;
• [Bindable]
• private var myData:ArrayCollection
– Crea un función que maneje el evento y será llamada cuando se
despecha el evento.
– Esta función recibe un argumento event de tipo ResultEvent
– private function resultHandler(event:ResultEvent):void
»{
»}
• En la función manejadora del evento,
podemos usar la expresión event.result para
referirnos a los datos enviados desde el
servidor.
• Nos movemos por la jerarquía XML para
conseguir los datos repetidos deseados y los
asignamos a la variable AC
– myData = event.result.contacts.row;
addEventListener
• Podemos escuchar el evento result cuando se llame a un
método addEventListener

<s:HTTPService id=”contactService”
url=”http://localhost/contacts.xml”
result=”resultHandler(event)”/>

var myService:HTTPService = new HTTPService();


myService.url = “data/contacts.xml”;
myService.addEventListener(ResultEvent.RESULT, resultHandler);
Ejemplo
• Aplicación que recibe datos usando el objeto
HTTPService con event result.
• Los datos se almacenan de forma persistente
con AC en una variable Bindable que aparece
en un DG usando binding expression.
Solución - HTTPResultEvent
<?xml version=”1.0” encoding=”utf-8”?>
<s:Application xmlns:fx=”http://ns.adobe.com/mxml/2009”
xmlns:s=”library://ns.adobe.com/flex/spark”
xmlns:mx=”library://ns.adobe.com/flex/mx”>
<s:layout>
<s:VerticalLayout horizontalAlign=”center” paddingTop=”20”/>
</s:layout>
<fx:Script>
<![CDATA[
import mx.rpc.events.ResultEvent;
import mx.collections.ArrayCollection;
[Bindable]
private var myData:ArrayCollection
protected function contactService_resultHandler(
event:ResultEvent):void
{
myData = event.result.contacts.row;
}
]]>
</fx:Script>
<fx:Declarations>
<s:HTTPService id=”contactService” url=”data/contacts.xml”
result=”contactService_resultHandler(event)”/>
</fx:Declarations>
<s:Button label=”Get Data” click=”contactService.send()”/>
<mx:DataGrid dataProvider=”{myData}”/>
</s:Application>
Evento fault
• Si el request HTTPService da error, se dispara
el evento fault.
– mx.rpc.events.FaultEvent.
• Su propiedades son:
– faultCode:String.
– faultDetail:String.
– faultString:String.
• mensaje de error
– message:String.
Gestionar error fault
<s:HTTPService id=”contactService”
url=”data/contactsMalformed.xml”
result=”resultHandler(event)”
fault=”faultHandler(event)”/>

var myService:HTTPService = new HTTPService();


myService.url = “data/contacts.xml”;
myService.addEventListener(ResultEvent.RESULT,
resultHandler);
myService.addEventListener(FaultEvent.FAULT, faultHandler);
Ejemplo
• Uso de evento fault en un objeto HTTPService
Solución - HTTPFaultEvent
<?xml version=”1.0” encoding=”utf-8”?>
<s:Application xmlns:fx=”http://ns.adobe.com/mxml/2009”
xmlns:s=”library://ns.adobe.com/flex/spark”
xmlns:mx=”library://ns.adobe.com/flex/mx”>
<s:layout>
<s:VerticalLayout horizontalAlign=”center” paddingTop=”20”/>
</s:layout>
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.controls.Alert;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
[Bindable]
private var myData:ArrayCollection
private function resultHandler(event:ResultEvent):void
{
myData = event.result.contacts.xml;
}
private function faultHandler(event:FaultEvent):void
{
Alert.show(event.fault.faultString, event.fault.faultCode);
}
]]>
</fx:Script>
<fx:Declarations>
<s:HTTPService id=”contactService” url=”data/contactsMalformed.xml”
result=”resultHandler(event)”
fault=”faultHandler(event)”/>
</fx:Declarations>
<s:Button label=”Get Data” click=”contactService.send()”/>
<mx:DataGrid dataProvider=”{contactService.lastResult.contacts.row}”/>
</s:Application>
Value Objects
• Datos recibidos con formato XML con el
componente HTTPService siempre se
almacenan como AC.
• Pero podemos trabajar con clases de value
objects fuertemente tipados.
• Debemos entonces, crear un código que
transforme las instancias Object en value
objects.
Convertir a value objects
• Crear una clase value object con las propiedades adecuadas y el método constructor
para aceptar como argumento un tipo de dato como la clase Object de AS.
• Dentro del método constructor, pasar los valores de sus propiedades a las
propiedades equivalentes de la instancia actual en el value object.

public function Contact(data:Object = null)


{
if (data != null)
{
this.contactid = Number(data.contactid);
this.firstname = data.firstname;
this.lastname = data.lastname;
... set additional properties ...
}
}
• En tiempo de ejecución, cuando manejamos el evento result, recorremos el
AC creando una nueva instancia de value object para cada elemento
• Reemplazamos el objeto original con el método setItemAt()

private function resultHandler(event:ResultEvent):void


{
var obj:Contact;
myData = event.result.contacts.row;
for (var i:int=0; i<myData.length; i++)
{
obj = new Contact(myData.getItemAt(i));
myData.setItemAt(obj, i);
}
}
Ejemplo
• Recibir datos del servidor y recorrer el AC para
reemplazar el Object con value object.
• Cuando seleccionemos una fila del DG, una
instancia bindable del value object se rellena
con los datos seleccionados y se muestran en
un Panel
Solución - HTTPValueObjects
• <?xml version=”1.0” encoding=”utf-8”?>
• <s:Application xmlns:fx=”http://ns.adobe.com/mxml/2009”
• xmlns:s=”library://ns.adobe.com/flex/spark”
• xmlns:mx=”library://ns.adobe.com/flex/mx”
• creationComplete=”contactService.send()”>
• <s:layout>
• <s:VerticalLayout horizontalAlign=”center” paddingTop=”20”/>
• </s:layout>
• <fx:Script>
• <![CDATA[
• import mx.collections.ArrayCollection;
• import mx.events.ListEvent;
• import mx.rpc.events.ResultEvent;
• import vo.Contact;
• [Bindable]
• private var myData:ArrayCollection
• [Bindable]
• private var currentContact:Contact;
• private function contactService_resultHandler(event:ResultEvent):void
• {
• var obj:Contact;
• myData = event.result.contacts.row;
• for (var i:int=0; i<myData.length; i++)
• {
• obj = new Contact(myData.getItemAt(i));
• myData.setItemAt(obj, i);
• }
• }
• protected function datagrid1_changeHandler(event:ListEvent):void
• {
• currentContact = event.target.selectedItem as Contact;
• }
• ]]>
• </fx:Script>
• <fx:Declarations>
• <s:HTTPService id=”contactService” url=”data/contacts.xml”
• result=”contactService_resultHandler(event)”/>
• </fx:Declarations>
• <mx:DataGrid dataProvider=”{myData}”
• change=”datagrid1_changeHandler(event)”>
• <mx:columns>
• <mx:DataGridColumn dataField=”firstname” headerText=”First Name”/>
• <mx:DataGridColumn dataField=”lastname” headerText=”Last Name”/>
• </mx:columns>
• </mx:DataGrid>
• <s:Panel title=”Current Contact” width=”300”>
• <mx:Form>
• <mx:FormItem label=”First Name:”>
• <s:Label text=”{currentContact.firstname}”/>
• </mx:FormItem>
• <mx:FormItem label=”Last Name:”>
• <s:Label text=”{currentContact.lastname}”/>
• </mx:FormItem>
• <mx:FormItem label=”City:”>
• <s:Label text=”{currentContact.city}”/>
• </mx:FormItem>
• </mx:Form>
• </s:Panel>
• </s:Application>
Pasar parámetros
• Con el componente HTTPService podemos
hacer llamadas a páginas dinámicas
gestionadas por una aplicación server.
• El sintaxis para pasar parámetros es igual si
usamos peticiones GET o POST
– parámetros empaquetado en un objeto AS
– parámetros vinculados (bound) que se envian en
la declaración del objeto HTTPService
Parámetros nombrados
• En primer lugar, creamos una instancia de un
Object AS.
• El Object es dinámico y pueden añadirse
propiedades en tiempo de ejecución.
• Establecemos cada parámetro con el nombre
de la propiedad y usamos el método send()
private function sendData():void
{
var params:Object = new Object();
params.firstname=”Joe”;
params.lastname=”Smith”;
contactService.send(params);
}
• Otra opción

private function sendData():void


{
contactService.send({firstname:”Joe”,
lastname:”Smith”});
}
• Si usamos Get, los parámetros se ven en la
dirección
• Si usas Post, los parametros se añaden al final
del request
Parámetros enlazados (bound)
• Podemos crear parametros bound en la
declaración HTTPServicey enviarlas en el
código.
• Declaramos una variable value object bindable
para almacenar los datos

[Bindable]
private var myContact:Contact;
• Podemos enviar los parámetros con sus valores
usando binding expressions

– <s:HTTPService id=”contactService” url=”myAppPage.php”


– result=”resultHandler(event)”>
– <s:request>
– <firstname>{myContact.firstname}</firstname>
– <lastname>{myContact.lastname}</lastname>
– </s:request>
– </s:HTTPService>
Ejemplo
• Necesitamos una aplicación servidor que
puede recibir y responder peticiones
parametrizadas
Cross-domain
• Si Flash Player necesita hacer request a otro
dominio diferente de donde se ha descargado
el actual fichero Flash, necesita permisos.
• Si esto sucede, Flash Player busca las politicas
de cross-domain.
• Permisos Cross-domain son necesarios para
todas las peticiones HTTP a dominios remotos
– HTTPService
– RPC (remote procedure calls) con Web Service y
RemoteObject
– descargar imágenes con componentes Image o
SWFLoader
– URLLoader o XMLSocket
• El fichero cross-domain es un fichero XML que
se llama crossdomain.xml .
• Está colocado en root del dominio remoto.
• Si cuando lo necesita, FP encuentra el fichero,
mira sus permisos.
cross-domain.xml
<?xml version=”1.0”?>
<!DOCTYPE cross-domain-policy SYSTEM
“http://www.adobe.com/xml/dtds/cross-domain-
policy.dtd”>
<cross-domain-policy>
<allow-access-from domain=”www.domain1.com” />
<allow-access-from domain=”domain2.com” />
<allow-access-from domain=”*.domain3.com” />
</cross-domain-policy>

You might also like