En el artículo anterior vimos una introducción a Flex 3, con un pequeño ejemplo para dar los primeros pasos.
En esta segunda nota de introducción veremos que las aplicaciones Flex pueden comunicarse con servicios y aplicaciones en servidores para el acceso a datos. Más que esto, pueden implementar toda su lógica de negocio en objetos deplegados en un servidor de aplicaciones. Analizaremos cuáles son los mecanismos y lenguajes soportados y un ejemplo paso a paso de una implementación con Java en el servidor usando Spring como framework de aplicación.
Mecanismos de comunicación
Existen 3 mecanismos de comunicación posibles entre un cliente Flex y aplicaciones u objetos en un servidor:
- Servicios HTTP: se basa en intercambio de XMLs entre la aplicación flash que se ejecuta en el browser del cliente y el servidor de información que se quiera acceder. Con este mecanismo, cualquier tecnología de software que se ejecute en el servidor (php, asp, jsp, etc) puede proveer información o servir de backend para una aplicación flex.
- Web Services: Flex es compatible con el estandar SOAP de Webservices, por lo que puede acceder a cualquier aplicación en el servidor con esta tecnología.
- Remote Object Services: Utilizando un mecanismo de acceso al servidor que solo requiere de configuración, se puede acceder a los objetos remotos que se encuentran en un servidor (objetos Java, componentes ColdFusion, objetos PHP y objetos .NET) e invocar sus métodos. Esto evita que se deban exponer las funcionalidades con webservices o HTTPservices disminuyendo el costo de programación.
Remote Object Services con Java
Para acceder a Objetos Java en el servidor, debe instalarse un servicio de acceso a datos. Actualmente existen 2 implementaciones:
- BlazeDS : Permite la comunicación entre aplicaciones Flex y objetos remotos JAVA en el servidor. Es open source.
- Adobe LiveCicle Data Services: Al igual que BlazeDS permite la comunicación con aplicaciones Flex pero además incorpora diversas utilidades para la creación de servicios del lado del servidor. Mas información se puede encontrar en esta nota. Esta versión es comercial.
De esta manera, utilizando cualquiera de estas tecnologías, se pueden crear aplicaciones Flex con un modelo de negocio creado en Java ejecutandose en el servidor.
Aquí se puede ver un esquema de cómo sería la arquitectura:
Creando una aplicacion Flex/Java utilizando BlazeDS y Spring.
En la siguiente guía crearemos una aplicación que utiliza Java, Spring y BlazeDS en conjunto. La integración de estas tecnologías se hace por medio de la configuración de una clase factory (SpringFactory) creada por el equipo de Flex. Al momento de escribirse esta nota, la gente de Spring y la gente de Adobe están creando un framework de integración llamado Spring BlazeDS Integration que promete más posibilidades a esta integración.
¿Qué necesitamos descargar?
Para poder realizar los pasos siguientes es necesario descargar:
- Distribución de BlazeDS
- Distribución de Spring
- Archivos de SpringFactory
Creacion del Proyecto Flex/BlazeDS en FlexBuilder 3
Creamos el proyecto Flex con el nombre "demo1-HolaMundoBlazeDSSpring", elegimos application server Type: J2EE y tildamos la casilla "Use remote Object access service". Esto último permitirá especificar el path al war de blazeds que será incluido en el paquete de la aplicación. Click en Next.
En la siguiente pantalla, se debe indicar el servidor que se utilizará para probar la aplicación, en la opción "Target Runtime". Seleccionaremos el servidor Tomcat que tenemos instalado. Si no hubiera ninguno instalado, debe crearse uno con el botón "new".
En la opción "Flex War File" seleccionamos la ruta al war de blazeDS que descargamos previamente. Podemos dejar las demás opciones por defecto y terminamos con "Finish".
Creación de la aplicación Flex
El siguiente es el código de la aplicacion main.mxml. Es muy sencillo y nos sirve para ver el funcionamiento de la llamada a objetos remotos. Con aplicaciones de gran tamaño lo mejor es optar por un modelo MVC, donde los accesos a los datos o a servicios en el servidor se implementen fuera de la capa de presentación, accediendo a una clase controladora que se encargue de estas llamadas.
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="horizontal" width="582" height="326" horizontalAlign="center" verticalAlign="middle" borderStyle="outset"> <mx:Script> <![CDATA[ import mx.rpc.events.ResultEvent; import mx.rpc.events.FaultEvent; import mx.utils.ObjectUtil; import mx.controls.Alert; import mx.utils.StringUtil; /** * Manejador del resultado de la llamada al servicio */ private function resultHandler(event:ResultEvent):void{ Alert.show( ObjectUtil.toString(event.result) ); } /** * Manejador del fault que pueda causar la llamada al servicio */ private function faultHandler(event:FaultEvent):void{ Alert.show( ObjectUtil.toString(event.fault) ); } ]]> </mx:Script> <!-- Objeto remoto que se accede en el servidor.--> <mx:RemoteObject id="ro" destination="hola-mundo-java-spring" result="resultHandler(event)" fault="faultHandler(event)" endpoint="http://localhost:8080/demo1-HolaMundoFlexJava-Java/messagebroker/amf"/> <mx:Panel width="457" height="228" layout="vertical" title="Demo 1 - Flex 3 con Java en el servidor." borderColor="#A7FAFF" fontFamily="Arial" fontWeight="bold" fontSize="13" horizontalAlign="center"> <mx:Text text="Click para obtener un mensaje desde una clase Java" fontWeight="bold" width="250"/> <mx:Spacer height="10"/> <mx:Button label="Hola Mundo!" click="ro.getHolaMundoJava()"/> </mx:Panel> </mx:Application>
El siguiente fragmento de código es el que indica cómo se accederá al servicio en el servidor:
<!-- Objeto remoto que se accede en el servidor.--> <mx:RemoteObject id="ro" destination="hola-mundo-java-spring" result="resultHandler(event)" fault="faultHandler(event)" endpoint="http://localhost:8080/demo1-HolaMundoFlexJava-Java/messagebroker/amf"/>
El elemento RemoteObject define el acceso a un objeto remoto con los siguientes atributos:
- id: identificación para ser invocado.
- destination: servicio al que se quiere acceder en el servidor.
- result: funcion de actionscript que manejará el resultado de la invocación.
- fault: funcion de actionscript que manejará un eventual fallo (fault) de la invocación.
- endpoint: url de destino, donde se encuentra el servicio que se quiere acceder.
En esta aplicacion de ejemplo, ambos handlers mostraran un mensaje con el mensaje recibido del servidor, o con una descripcion en caso de producirse un fault.
La llamada al servicio se realiza al clickear en el botón:
<mx:Button label="Hola Mundo!" click="ro.getHolaMundoJava()"/>
Esto llamará al servicio configurado en el objeto remoto con id "ro", invocando al método "getHolaMundoJava()". Notar que este método no está definido en ningún lugar de la aplicación Flex cliente, por lo tanto errores de tipeos no generan errores de compilación, con lo que se debe tener cuidado de escribir bien.
Creación del Servicio en el servidor JEE, con BlazeDS y Spring
Crearemos ahora el servicio de lado del servidor, utilizando Spring como framework de nuestra aplicación.
Incluir el Jar de Spring al Proyecto
En las propiedades del proyecto -> menu "Java EE Module Dependencies" -> agregar el jar de spring, seleccionandolo con "Add Jars".
Creacion de las clases de servicio y objeto de negocio
En este ejemplo sencillo, crearemos una clase de servicio compuesta por un objeto de negocio con un único método que devolverá la frase "Hola Mundo desde Java!". Crearemos a continuación las interfases y clases que necesitamos. Ubicarlas en los paquetes correspondientes dentro de la carpeta src:
HolaMundoFlexService.java
package com.dosideas.flex.demo1.service; import com.dosideas.flex.demo1.business.HolaMundoBo; public class HolaMundoFlexService { private HolaMundoBo holaMundoBo; public String getHolaMundoJava() { return getHolaMundoBo().decirHola(); } //getter y setter del objeto de negocio ... }
HolaMundoBo.java
package com.dosideas.flex.demo1.business; public interface HolaMundoBo { public String decirHola(); }
HolaMundoBoImpl.java
package com.dosideas.flex.demo1.business.impl; import com.dosideas.flex.demo1.business.HolaMundoBo; public class HolaMundoBoImpl implements HolaMundoBo { public String decirHola() { return "Hola Mundo desde Java!"; } }
Creacion de archivos de configuracion de spring
Crear el archivo applicationContext.xml en el directorio WEB-INF de la aplicación web.
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <!-- bean de testing para la aplicacion flex --> <bean name="holaMundoFlexService" class="com.dosideas.flex.demo1.service.HolaMundoFlexService"> <property name="holaMundoBo" ref="business.HolaMundoBo" /> </bean> </beans>
Crear el archivo de configuracion de beans de objetos de negocio "hola-mundo-business.xml" en la carpeta src (raíz de los fuentes Java) con el siguiente contenido:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean name="business.HolaMundoBo" class="com.dosideas.flex.demo1.business.impl.HolaMundoBoImpl"> </bean> </beans>
Configurar el contexto de spring en la aplicación web
En el descriptor web.xml, agregar el siguiente codigo para que se reconozcan los archivos de configuración de spring. Agregaremos dos archivos de configuración, el applicationContext.xml que declarará el servicio que se proveerá a la aplicación cliente y será el punto de acceso a la aplicación y el archivo hola-mundo-business.xml que definirá los objetos de negocio que serán usados en el servicio.
<!-- Configuracion para el funcionamiento de spring --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext.xml classpath:hola-mundo-business.xml </param-value> </context-param> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener>
Configurar BlazeDS para que utilice el Bean de Spring "holaMundoFlexService" para responder al cliente Flex
Para que BlazeDS utilice los beans de spring hay que indicarle una clase factory que será la encargada de la instanciación de los servicios, que serán en definitiva beans de spring. Esta clase se llama SpringFactory.java y se encuentra en la distribucion de SpringFlex. Hay que agregarla al proyecto y configurarla:
Buscar esta clase en flex/samples/factories y copiarla en el paquete flex.samples.factories de nuestro proyecto, en la carpeta src (fuentes de Java, ojo no confundir con flex_src que son los fuentes de flex).
Configurar la factory en el archivo WEB-INF/flex/services-config.xml agregando:
<!-- factory para utilizar beans de spring --> <factories> <factory id="spring" class="flex.samples.factories.SpringFactory"/> </factories>
<destination id="hola-mundo-java-spring"> <properties> <factory>spring</factory> <!-- nombre del bean al que se quiere acceder --> <source>holaMundoFlexService</source> </properties> </destination>
¡Todo listo! Probamos la aplicación
La aplicación ya está lista para ejecutarse. Seleccionamos el proyecto -> Run As -> Run on Server.
Accedemos en un navegador a la dirección: http://localhost:8080/demo1-HolaMundoBlazeDSSpring/main.html
Podremos ver el mensaje recibido desde nuestra aplicación Java en el servidor:
Les dejo algunas páginas para que consulten más información: