Operaciones CRUD desde Flex con Pimento y Cinnamon


¿Qué es Pimento Data Services y qué funcionalidades ofrece?

Cuando utilizamos JPA e Hibernate para ejecutar operaciones CRUD en nuestra aplicación creamos las entidades con sus correspondientes anotaciones, luego creamos una capa DAO en la cual invocamos las operaciones de persistencia y finalmente una capa de servicios desde la cual invocamos los métodos del DAO y encapsulamos la lógica de negocios. Si ejecutamos todo este código en una aplicación JEE que implemente AMF podremos invocar estos métodos desde Flex utilizando Remote Objects. Pero en caso que decidamos dotar de más inteligencia a la aplicación Flex podemos trasladar la capa de servicios al cliente y en este caso necesitaríamos invocar directamente a la capa DAO o a las operaciones de persistencia.

Pimento Data Services nos permite, desde ActionScript, invocar las operaciones de persistencia definidas por JPA en el servidor, a través de la clase EntityManager, homóloga de la de JPA, pero adaptada a este tipo de cliente. A través de esta clase podemos invocar las operaciones “load”, “persist”, “remove” y “merge”, además de ejecutar consultas utilizando JPAQL y “Named Query”.

El framework almacena en un “cache” en el cliente las entidades cargadas del servidor, asegurando que exista una sola instancia de cada entidad, y este “cache” se utiliza para enviar al servidor solamente las propiedades que cambien cuando se realice una operación “merge” o para restablecer el estado original de la entidad, también ofrece métodos para eliminar objetos del “cache” e inspeccionar si un objeto ya existe en el “cache”.

Pimento ofrece también funcionalidades que permiten realizar “lazy loading” de entidades. Para todas las asociaciones y colecciones marcadas como “lazy” que no han sido inicializadas en el momento de la carga, el servidor envía solamente “proxies” al cliente, y en el momento necesario, utilizando el método “initialize” de la clase EntityManager se cargarán el resto de los datos.

Ante una operación “merge” de una entidad se compara el estado de la misma con la que se encuentra en el “cache” y se envía al servidor solamente aquellas propiedades que hayan cambiado, este proceso ocurre recursivamente cuando las propiedades son colecciones.

El framework también se ocupa de gestionar las llaves primarias de las entidades, al hacer persistente una nueva entidad se devuelve la misma entidad con el valor correspondiente de su llave primaria inyectada.

Si tenemos propiedades en nuestra entidad en el servidor que no deseamos que lleguen al cliente o que no sean modificadas en éste, anotamos las mismas usando anotaciones propias del framework.
En el servidor podemos interceptar todas las operaciones iniciadas en el cliente y controlar el valor de las propiedades de las entidades involucradas en las operaciones.

Pimento Data Services se compone de dos partes, una se incluye en el cliente y otra en el servidor. La parte que se incluye en el servidor utiliza Spring para inyectar dependencias en todas las clases que reciben las entidades enviadas por el cliente. La parte correspondiente en el cliente incluye librerías que se añaden al proyecto.

El framework ofrece dos modelos de programación para trabajar con entidades persistentes: uno utilizando la clase EntityManager de AS3 y otro utilizando servicios personalizados, cada uno tiene sus ventajas y desventajas. El modelo más simple es el que utiliza el EntityManager de AS3, con este modelo creamos las entidades y le incluimos las anotaciones propias de JPA, luego añadimos la anotación “@Managed” a aquellas entidades que queremos que sean gestionadas por Pimento, se crean las clases AS3 equivalentes a las entidades gestionadas, se inicializa el cliente y se invocan las operaciones CRUD, opcionalmente se pueden crear interceptores.

Los servicios personalizados por su parte son equivalente a las capa de servicios que mencionábamos anteriormente, son clases Java gestionadas por Spring y que se exponen al cliente para que sean invocadas remotamente. El framework incluye tareas ant para generar los “proxies” de esas clases en el cliente.

Desde el punto de vista de flexibilidad los servicios personalizados son más convenientes si planeamos que nuestra aplicación tenga múltiples clientes (Web, de escritorio, Web Service, etc.), pero si el único cliente es Flex entonces la solución más simple es usar el EntityManager de AS3, en este caso solamente tenemos que crear en el servidor las entidades con sus anotaciones correspondientes.
El framework se soporta sobre Cinnamon Remoting, una aplicación JEE que implementa el protocolo AMF3, como BlazeDS, pero a diferencia de éste no soporta mensajería, por lo que se hace un poco complejo implementar la sincronización de datos.

En este artículo veremos a través de un ejemplo como ejecutar operaciones CRUD desde Flex con Pimento Data Services utiizando el EntityManager de AS3. En artículos futuros veremos la funcionalidad de “lazy loading” y los servicios personalizados.

El ejemplo

En el ejemplo que desarrollaremos partimos del hecho que queremos gestionar una entidad denominada User y contamos con un servidor de bases de datos MySQL.

Luego de descargar el framework desde aquí lo primero que haremos será crear la aplicación JEE que utilice Cinnamon y donde crearemos las entidades. Para esto creamos un proyecto de tipo “Dynamic Web Project” con las siguientes características:

  • Nombre del proyecto: PimentoServer
  • Target Runtime: En nuestro caso usaremos Apache Tomcat 6, pero puede utilizarse cualquier otro que se haya configurado.
  • Versión del módulo Web Dinámico: 2.5
  • Configuración: Configuración por defecto para Apache Tomcat 6.0
  • Cambiamos la carpeta donde se compilarán las clases a “PimentoServer/WebContent/WEB-INF/classes”.

Una vez creado el proyecto copiamos el contenido de la carpeta “server/web/WEB-INF/lib” de la distribución del framework en “WebContent/WEB-INF/lib” de nuestro proyecto. Sustituimos el archivo de HSQLDB por el controlador JDBC de MySQL, y copiamos de la carpeta “server/release” los archivos “cinnamon-core”, “cinnamon-reflect” y “pimento-core”. Necesitamos copiar también el paquete “javassist”, este lo podemos encontrar en la distribución de Spring con dependencias.

Creamos una carpeta denominada “config” dentro de “WebContent/WEB-INF” de nuestro proyecto y copiamos los archivos “jpa-spring.xml” y “pimento-spring.xml” en “server/web/WEB-INF/config” en la distribución del framework; también copiamos el archivo “dp.properties.template.mysql” de “server/web/WEB-INF/config/db-templates” como “db.properties” en “WebContent/WEB-INF/config” de nuestro proyecto y ajustamos los valores de la conexión a la base de datos. Como estamos en fase de desarrollo ponemos “hibernate.hbm2ddl.auto=update”.

Finalmente el archivo “web.xml” de nuestro proyecto queda así:

A continuación crearemos la entidad que vamos a gestionar desde el cliente:

Aquí la única anotación propia de Pimento es “@Managed”, que indica que la entidad será gestionada por el framework, o sea, será incluida en el “cache” del cliente cuando sea cargada, su llave primaria será inyectada al hacer persistente una instancia de la clase, se enviarán solamente las propiedades que cambien al realizar una operación “merge” y su estado podrá ser gestionado a través del EntityManager.

Desplegamos la aplicación en Tomcat y arrancamos el servicio, pero antes creamos la base de datos según quedó configurada en el archivo “db.properties”. Al iniciar la aplicación se creará la tabla que representa la entidad en la base de datos. Llenamos esta tabla con información inicial para poder efectuar la autenticación en la UI.

Esto es todo lo que haremos en el servidor, a continuación crearemos la UI.

Creamos un proyecto Flex con las siguientes características:

  • Nombre del proyecto: PimentoClient
  • Tipo de aplicación: Web
  • Seleccionamos el SDK por defecto
  • Como tecnología del servidor no seleccionamos ninguna
  • Como carpeta de salida seleccionamos la carpeta WebContent del proyecto PimentoServer que creamos anteriormente.

La interface de usuario contiene un ViewStack con dos elementos, en uno pondremos un panel de autenticación:

login

Al introducir un nombre de usuario y contraseña válidos pasaremos al segundo elemento del View Stack, en el cual se realizará la gestión de la entidad:

crud

Para estructurar mejor el proyecto nos auxiliaremos del framework Robotlegs. Lo primero que haremos será incluir en el proyecto las librerías del framework Pimento y Cinnamon. Copiamos en la carpeta “libs” del proyecto los archivos “cinnamon-1.1.0.swc” y “pimento-1.1.0.swc” que se encuentran en la carpeta “client\release” de la distribución, incluimos también “spicelib-core-2.0.1.swc” y “spicelib-reflect-2.0.1.swc” de la carpeta “client\lib” y la librería del framework Robotlegs.

Luego procedemos a crear el equivalente AS3 de la entidad creada en java:

Como podemos ver, no se incluye el metadata “RemoteClass”, que normalmente utilizamos para indicar la clase equivalente a ésta en el servidor, Pimento y Cinnamon se encargan de registrar la clase y realizar todo el proceso de serialización/deserialización entre AS3 y Java de las instancias cuando viajan de cliente a servidor y viceversa.

La configuración del framework en el cliente comienza con la creación de una instancia de la clase “PimentoConfig”, a través de la cual podemos obtener el “EntityManager” que usaremos para invocar las operaciones de persistencia. La clase PimentoConfig necesita conocer el URL de la aplicación JEE que a través de Cinnamon recibirá las solicitudes del cliente para invocar las operaciones de persistencia, específicamente el URL al servlet “service”. En nuestro caso cargaremos esta información de un archivo xml externo. El comando que hace todo esto queda así:

El contenido del archivo “config.xml” que se encuentra en la carpeta “src/config” del proyecto Flex es el siguiente:

Cuando el usuario introduzca un nombre de usuario y contraseña válidos se ejecutará el comando que realiza la autenticación, que es éste:

Como vemos en el método “execute”, el modo de uso de la clase EntityManager de Pimento es muy similar a su homóloga de JPA, pero con la característica distintiva que las operaciones de persistencia son asincrónicas, de ahí que debamos registrar manejadores para obtener los resultados y los posibles errores.

De forma similar el código para realizar las operaciones CRUD queda así:

Adicionar

Modificar

Eliminar

Listar

El código fuente de los proyectos del servidor y el cliente se puede descargar de aquí.

Conclusiones

Hemos visto el modelo de programación más simple de Pimento Data Services, este modelo nos permite trasladar al cliente la lógica de la capa de servicios e invocar directamente desde éste las operaciones de persistencia de JPA en el servidor. Hemos dejado fuera las funcionalidades del “lazy loading” y los servicios personalizados, que serán tratados en artículos futuros.

Comparte:



5votos  Vota!!

Acerca de esta entrada