#GX3199
Aplicaciones Offline para
Smart Devices: Conceptos
avanzados
Marcos Crispino
@mcrispino
mcrispino@genexus.com
#GX3199
#GX3199
Offline
#GX3199
TEMAS
Objeto Offline
Database
Generación
de código
Escenarios
avanzados
Sincronización
Objeto Offline
Database
#GX3199
Condiciones y eventos
• Conditions
• Event Start
• Navegación
#GX3199
Creación de la base de
datos
• Generación de los programas
• Ejecución en el dispositivo
• Solo creación
• Opción ...
#GX3199
Base de datos local
• SQLite
• Integridad transaccional
• Transacciones son bloqueantes
#GX23
TEMAS
Objeto Offline
Database
Generación de código
#GX3199
Online vs. Offline
• Eventos Start, Refresh y Load
• Eventos de usuario
• Procedures y Data Providers
• Business C...
#GX3199
Ejecución en dispositivos
• Acceso a datos (for each, new)
• Estructuras de control (if, while, etc.)
• Operacione...
#GX3199
Seguridad con GAM
• Credenciales en el servidor
• Opción de Login solo Online
• Usuario autenticado Offline
• Cons...
#GX3199
TEMAS
Objeto Offline
Database
Generación
de código
Escenarios avanzados
#GX3199
Aplicación full offline
• Nunca se conecta al servidor
• Datos precargados o generados por el usuario
• Ejemplo: a...
#GX3199
Aplicación basada en
servicios
• No necesita “backend”
• Requiere de servicios externos
• Puede o no tener datos l...
#GX3199
TEMAS
Objeto Offline
Database
Generación
de código
Escenarios
avanzados
Sincronización
#GX3199
Sincronización
Receive
Send
#GX3199
Propiedades
#GX3199
Receive
• Automática o Manual
• Data Synchronization Criteria
• Minimum Time Between Synchronizations
• Synchroniz...
#GX3199
Receive: by row
• Tablas auxiliares en el servidor
• Versión de los datos en el cliente (hash)
• Juego de datos po...
#GX3199
Receive: by row
Dispositivo Servidor
Clientes
[ {id=1, nombre=A}, {id=2, nombre=B} ]
Hash
3458145ae23490fb142
Clie...
#GX3199
Receive: filtrado de datos
• Conditions en el objeto Offline Database
• Se aplican antes de calcular el hash de la...
#GX3199
Send
• Solo Business Components
• Tabla auxiliar en SQLite
#GX3199
Send: cuándo
• Propiedad Local Changes Processing
• When Connected
• User Defined: Synchronization.Send()
#GX3199
Send: mapeo de claves
• Claves autogeneradas
• Usadas como Foreign Key en otras tablas
• Cambian de valor en el se...
#GX3199
Send: mapeo de claves
Cliente: {CliId=1,...}
Factura: {..., CliId=1, ...}
Dispositivo Servidor
Cliente: {CliId=1,....
#GX3199
Send: manejo de errores
• Respuesta de error
• SynchronizationEventsAPI
#GX23
TEMAS
Objeto Offline
Database
Generación
de código
Escenarios
avanzados
Sincronización
#GX23
www.genexus.com/encuentro
@mcrispino#GX3199
Upcoming SlideShare
Loading in …5
×

Aplicaciones offline sd conceptos avanzados

1,519
-1

Published on

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
1,519
On Slideshare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
24
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide
  • Introducción
  • Apertura: tuit de @spolsky, contar quién es, qué es Trello, aplicación iOS con más de 2 años, hace 6 meses versión 2.0 para iPad, ahora soporte offline y sincronización¿Por qué es importante? Porque es una funcionalidad costosa, que en GX está resuelto de forma automática.
  • Antes de empezar, tenemos que definir bien a que nos referimos cuando hablamos de aplicaciones offline.El término a veces genera confusión, porque la palabra offline puede tener distinto significado según el contexto en que se use.Para nosotros offline no significa aplicaciones que nunca están conectadas. Son aplicaciones que en general tienen conexión, pero que tienen que poder funcionar también cuando están desconectadas. Esto implica que tienen un repositorio de datos centralizado, pero también tienen que tener un repositorio de datos locales, y tienen que tener algún mecanismo de sincronización. Además tienen que tener la posibilidad de ejecutar código en el dispositivo, de forma tal de poder hacer cálculos cuando no se tiene conexión con el servidor.El escenario canónico es el de ingreso de pedidos, donde el usuario va al cliente con un dispositivo movil, ingresa el pedido tenga conexión o no, y se mandan los pedidos al servidor tan pronto como se pueda. Pero además, los precios de los productos se tienen que actualizar con cierta frecuencia, así como los datos de los clientes.
  • Entonces en esta charla vamos a hablar de estos temas, que tienen que ver con las aplicaciones offline.Primero vamos a ver qué es el objeto offline database, luego vamos a hablar sobre la generación de código en los dispositivos. Luego vamos a ver como esto nos permite resolver otros escenarios, y por ultimo vamos a hablar sobre sincronización que es quizá el tema más interesante.
  • El objeto offline database es un nuevo tipo de objeto en GeneXus Tilo que se crea a partir de un objeto main SD, y es quien define qué tablas van al dispositivo y cómo se sincronizan.Las tablas que se incluyen en la base de datos offline se determinan a partir de los paneles offline alcanzables desde el main.Este objeto aparece debajo del objeto main que lo genera en el Folder View de GeneXus.
  • En las aplicaciones en los smarte devices, en general, no vamos a querer tener todos los datos que tiene el servidor, ya sea porque son demasiados o por temas de privacidad. Por ejemplo, no voy a querer que un vendedor se lleve los datos que le corresponden a otro. Para eso tenemos la opción de definir en el objeto offline database qué datos tienen que ir al dispositivo.El objeto offline database tiene un tab de conditions globales, que aplican a las tablas que corresponda. Tiene un evento Start para poder hacer cálculos previos e inicializar variables que se usen en las condiciones.En la navegación aparecen las condiciones que aplican a cada tabla. Podemos ver en la foto que por ejemplo la condición por “cliente activo” aplica también a las órdenes de compra. Esto es porque las condiciones se aplican a todas las tablas que tenga sentido, incluso aquellas que se llega por tabla extendida. Esto asegura la consistencia de los datos en cuanto a la integridad referencial, ya que por ejemplo no voy a tener una orden de compra de un cliente que no tengo.
  • La creación de la base de datos offline se hace automáticamente cuando cambia la estructura de la base de datos. En realidad lo que se hace es generar los programas de creación, pero se ejecutan recién la primera vez que se corre la aplicación en el dispositivo.En la versión Beta 2 solo se genera la creación de la base, no hay reorganización. De todas formas, este create database solo se ejecuta la primera vez, o si hay una nueva versión de la aplicación que cambió la estructura de la base de datos ofline.En realidad, además de poder ejecutar el programa de reorganización, también se tiene la opción de mandar junto con la aplicación generada, un juego de datos que se toma como base de datos precargados. En ese caso lo que se hace es copiar esa base precargada en vez de ejecutar la creación.
  • Algunas características de la base de datos local:La base de datos en el dispositivo es SQLite, tanto para Andorid como para iOS.No tiene integridad referencial en el manejador de base de datos, pero se controla la integridad por programa.Sí soporta integridad transaccional, y las transacciones son bloqueantes, es decir, solo un proceso puede tener una transacción abierta en un momento dato.
  • Resumen ofline database, pasemos a ver la generacion de codigo.
  • Como vimos, el escenario de aplicaciones offline requiere de poder ejecutar lógica en los dispositivos, y para eso necesitamos generar código nativo.El lenguaje a generar depende del dispositivo donde vaya a ejecutarse la aplicación, y es Java para Android y Objective-C para iOS.
  • En las aplicaciones online no hay generación de código, es solo metadata que es interpretada por un “flexible client”.En las aplicaciones online, los eventos Start, Refresh y Load ejecutan siempre en el servidor. En Offline ejecutan en el cliente accediendo a datos locales.Los eventos de usuario siguen siendo interpretados, pero pueden llamar a otros objetos que ejecuten del lado del cliente.Los procedimientos y data providers que se llaman desde objetos offline, se generan también offline. Se pueden usar para acceder a datos pero también para ejecutar lógica en el cliente.Los Business Components se generan también offline.
  • ¿Qué se puede hacer con el código generado? Básicamente lo mismo que se hace en las aplicaciones web: acceder a datos usando el comando for each, utilizar estructuras de control con toda su potencia (en eventos online hay un ‘if’ pero es bastante limitado), operaciones aritméticas (que antes se tenían que hacer en el servidor), usar funciones del lenguaje como ser substr() y variables predefinidas como por ejemplo &time.
  • En el caso de las aplicaciones que tengan GAM, las credenciales de los usuarios se mantienen solamente en el servidor. De todas formas se pueden hacer aplicaciones offline que usen GAM.La pantalla de Login tiene que ser online, ya que no hay forma de autenticar al usuario estando desconectado.Una vez que el usuario inicia sesión, la aplicación sigue funcionando con las credenciales del usuario registrado.Se puede usar la API del GAM para obetener información del usuario, como ser su nombre, e-mail, identificador, etc. También se puede preguntar si es el usuario anónimo o un usuario registrado.Funciona por el momento solo con autenticación, no se tiene autorización porque implicaría llevarse todos los permisos del usuario al dispositivo.
  • Hasta ahora vimos lo que es el objeto ofline database y las posibilidades que nos da el generar codigo del lado del dispositivo.
  • Con esta funcionalidad que estuvimos viendo: la base de datos local, junto con la posibilidad de ejecutar código en el dispositivo, nos permite resolver algunos escenarios que no son exáctamente el planteado originalmente como escenario de aplicaciones offline.
  • Un ejemplo de aplicaciones que se puede resolver con esta funcionalidad es el de las aplicaciones que funcionan siempre desconectadas.Estas aplicaciones no requieren de acceso al servidor, de hecho, el servidor puede no existir. GeneXus lo va a generar de todas formas, pero podemos no hacer el deploy de la base de datos y de la capa de servicios.Los datos de este tipo de aplicaciones pueden venir precargados, o pueden ser datos generados por el usuario.Un ejemplo que para mi es claro, es una aplicación de finanzas personales, donde el usuario registra sus gastos pero tiene toda la información local.
  • Otro ejemplo pueden ser aplicaciones basadas en servicios. Son aplicaciones offline en el sentido que no necesitan del servidor y la base de datos generados por GeneXus, pero sí necesitan de servicios externos para funcionar por lo que necesitan de conexión a la red.Esto se puede lograr gracias a que al generar código en los dispositivos, podemos consumir servicios mediante el uso por ejemplo de HTTPClient.Los datos locales en este caso son opcionales. Podría por ejemplo tener una forma de guardar favoritos, o consultas recientes, o cualquier otra información que se necesite.Un ejemplo de este tipo de aplicaciones es Find My Plane, que es una aplicación para buscar información sobre vuelos en tiempo real. Esta aplicación era orignalmente online y los servicios de consulta de vuelos los consumía el servidor, pero ahora se pasó a Tilo y los servicios se consumen directamente desde el dispositivo.Otro posible ejemplo sería una aplicación para un banco, que no quiere que los datos pasen por un servidor centralizado, sino que quiere que la comunicación sea directamente con el dispositivo del cliente.
  • Resumen generacion de codigo, vamos a ver la sincronizacion
  • La sincronización de datos es fundamental en el escenario que planteamos, ya que los datos del dispositivo tienen que ser una vista de los datos del servidor, y las cosas que grabamos en el cliente se tienen que replicar en el servidor.
  • La sincronización siempre la inicia el dispositivo, puede iniciar de forma automática o a pedido del usuario, pero siempre es desde el cliente.Tenemos dos operaciones que son independientes. La operación de Receive es desde el servidor al cliente, y la de Send desde el dispositivo al servidor. Es decir, la operación siempre es vista del lado del cliente.Vamos a ver más detalles de cada una.
  • La sincronización la realiza el objeto Offline Database, para lo cual tiene algunas propiedades.Las tres primeras aplican al momento de recibir los datos, y la última al envío, recuerden que siempre visto desde el dispositivo.
  • La recepción de datos se puede iniciar de forma automática o de forma manual.Esto se define mediante la propiedad Data Synchronization Criteria, y si es automática se va a sincronizar cada vez que se abre la aplicación, siempre y cuando haya pasado el tiempo que se indica en la propiedad Minimum Time Between Sinchronizations.Si es manual, entonces debe ser el programador GeneXus quien la invoque llamando al método Synchronization.Receive(). Tener en cuenta que “manual” significa que se tiene que iniciar de forma manual, pero los programas de sincronización igual se generan.Lo otro que podemos configurar es si es por tabla, o por registro. Esto se configura mediante la propiedad Data Synchronization Granularity. Si es por tabla, para las tablas que hayan cambiado desde la última sincronización, se manda toda la información de la tabla, se borra lo que había en el dispositivo, y se carga todo lo que vino del servidor.Si es por registro, entonces solo se van a mandar las diferencias que haya como una serie de inserts, updates y deletes.La primer opción, por tabla, tiene la ventaja que requiere menos procesamiento del lado del servidor. También tiene sentido si los datos cambian mucho entre una sincronización y la siguiente. Por registro requiere más cálculos en el servidor, pero puede significar mucho menos tráfico de datos.
  • Cuando la sincronización es por registro, en el servidor se crean tres tablas auxiliares para guardar la información necesaria para poder calcular las diferencias.Lo que se tiene es para cada tabla que se sincroniza, un identificador de la versión de los datos que tiene el cliente. Este identificador es un hash de los datos de la tabla, por lo que antes de hacer nada se compara el hash que manda el cliente con el hash de los datos actuales en el servidor. Si son iguales termina ahí. Hasta acá es igual para la sincronización por tabla, solo que para esa opción no necesitamos las tablas auxiliares.Si son distintos, entonces se pasa a comparar por registro. El servidor tiene almacenados los registros que corresponde a la versión de los datos que tiene el cliente, por lo que puede calcular las diferencias con lo que hay en ese momento en la tabla. Con las diferencias se arma lo que se le manda al cliente, y a su vez se hace un nuevo hash de la tabla y se guarda ese hash junto con los datos que tiene en el momento, para poder sincronizar la próxima vez.
  • Vamos a ver un ejemplo para que quede mas claro.Supongamos que tenemos una tabla de clientes, inicialmente en el dispositivo esta vacia y en el servidor tengo dos registros.El dispositivo pide sincronizar, entonces el servidor calcula el hash de la tabla, manda los datos junto con el hash al cliente donde queda guardada la informacion, pero ademas se guarda esa informacion en las tablas auxiliares que les mensionaba.Pasa el tiempo, los datos en el servidor cambiaron como vemos, se modifico el registro 1, se borro el 2 y se ingreso uno nuevo con id 3. El cliente pide nuevamente sincronizar, pero esta vez como tiene datos, manda el hash de la tabla.El servidor calcula el nuevo hash, los compara, ve que son distintos, y entonces busca en las tablas auxiliares cuales eran los datos que correspondian al hash del dispositivo, y calcula las diferencias.En este caso le da un insert, un update y un delete.Manda esa informacion al cliente junto con el nuevo hash, y luego de aplicarlo el cliente queda con la misma informacion que el servidor. Ademas se guarda el hash para la proxima sincronizacion.
  • Los datos que se mandan al dispositivo pueden filtrarse como ya vimos, mediante el uso de las conditions del objeto Offline Database.Estos filtros se aplican antes de calcular el hash de la tabla y antes de hacer las comparaciones necesarias en la sincronización por registro, ya que los datos que no cumplan con las condiciones no pueden ir nunca al dispositivo.No se tiene regla parm, pero igual se pueden usar algunos parámetros para filtrar, como ser información del dispositivo (identificador, idioma, etc.) o el identificador del usuario en el caso que se use GAM.
  • Pasemos ahora a ver el envío de datos desde el dispositivo al servidor.Lo primero, es que solo se mandan al servidor las operaciones que se graben mediante business components. Si se graban datos con el comando new o se actualizan mediante un for each, esos datos no van al servidor.Esto es así porque lo que sabemos manejar del lado del servidor son business components, a los cuales se les aplican todas las reglas de la transacción, igual que si se estuviera trabajando en una aplicación online.En el dispositivo se crea una tabla auxiliar, donde se graba para cada operación que se hace mediante un business component, información de a que business component corresponde, el tipo de operación si es insert, update o delete, los datos del business component, y alguna información más que necesitamos para sincronizar como ser el estado en que está el registro y los mensajes de error en el caso que haya ido al servidor y no se haya podido aplicar.
  • El momento en que se envían los datos al servidor depende de la propiedad Local Changes Processing del objeto Offline Database.Los valores posibles son When Connected, que quiere decir que los datos se van a mandar inmediatamente si se tiene conexión y si no, tan pronto como se recupere la conectividad.La otra opción es User Defined, que quiere decir que nunca se van a mandar datos de forma automática, sino que el programador debe realizarlo mediante una invocación al comando Synchronization.Send()
  • Un problema que surge con el envío de los datos al servidor, es qué pasa con las claves que son autogeneradas. Pueden ser campos con autonumber, atributos clave de un segundo nivel con una regla serial, o una clave que se calcule mediante un procedimiento.Estas claves ademas son usadas como foreign key en otras tablas.Cuando se manda el insert de un registro con clave autonumerada al servidor, es casi seguro que va a quedar con distinto numero en el servidor. Vamos a ver un ejemplo para que quede mas claro.
  • Supongamos que se ingresa en el dispositivo un cliente, que tiene clave autonumber y queda con id 1. Para ese cliente se ingresa una factura, que hace referencia el cliente con id 1.Cuando se mandan los datos al servidor, el servidor hace el insert del cliente primero, y obviamente cambia de valor el identificador del cliente, porque en el servidor se graba calcula de nuevo. La factura tiene que seguir siendo de ese cliente, por lo que en la grabación se tiene que actualizar el identificador del cliente en la factura, que luego se graba con el cliente correcto.Esto se hace así de forma automática, pero además se manda al dispositivo el mapeo de claves que se hizo en el servidor para que quede actualizado también en el dispositivo. De esa forma, si más tarde ingreso otra factura para ese cliente, los datos van a ir bien y va a quedar la factura asociada al cliente correcto.
  • Puede pasar que cuando mando un business component al servidor, el mismo no se pueda grabar por algún motivo. Por ejemplo, cambio algún dato relacionado como el límite de crédito del cliente, y la venta no se puede ingresar.En ese caso, el business component no se borra de la tabla auxiliar, sino que se marca como que tiene error y quedan los mensajes del servidor para poder verlos en el dispositivo. Tampoco se vuelve a mandar automátcamente.Para poder acceder a estos datos, se cuenta con una API que permite consultar los registros pendientes de envío y los que se enviaron pero quedaron con error. Los que se enviaron y se procesaron bien se borran directamente.Una de las cosas que permite hacer la API es reenviar una operación que dio error, con la misma información con que se envió originalmente, por lo que el problema debe resolverse antes del lado del servidor.
  • Bueno, con esto completamos los cuatro temas de la charla. Muchas gracias, y solo me resta decirles que todo esto que estuvimos viendo va a estar disponible en la versión Beta 2 de GeneXus Tilo, e incluso ya lo pueden ir probando en los night builds disponibles hoy.
  • Aplicaciones offline sd conceptos avanzados

    1. 1. #GX3199 Aplicaciones Offline para Smart Devices: Conceptos avanzados Marcos Crispino @mcrispino mcrispino@genexus.com
    2. 2. #GX3199
    3. 3. #GX3199 Offline
    4. 4. #GX3199 TEMAS Objeto Offline Database Generación de código Escenarios avanzados Sincronización
    5. 5. Objeto Offline Database
    6. 6. #GX3199 Condiciones y eventos • Conditions • Event Start • Navegación
    7. 7. #GX3199 Creación de la base de datos • Generación de los programas • Ejecución en el dispositivo • Solo creación • Opción de precarga de datos
    8. 8. #GX3199 Base de datos local • SQLite • Integridad transaccional • Transacciones son bloqueantes
    9. 9. #GX23 TEMAS Objeto Offline Database
    10. 10. Generación de código
    11. 11. #GX3199 Online vs. Offline • Eventos Start, Refresh y Load • Eventos de usuario • Procedures y Data Providers • Business Components
    12. 12. #GX3199 Ejecución en dispositivos • Acceso a datos (for each, new) • Estructuras de control (if, while, etc.) • Operaciones • Funciones del lenguaje
    13. 13. #GX3199 Seguridad con GAM • Credenciales en el servidor • Opción de Login solo Online • Usuario autenticado Offline • Consulta de datos del usuario Offline • Solo autenticación
    14. 14. #GX3199 TEMAS Objeto Offline Database Generación de código
    15. 15. Escenarios avanzados
    16. 16. #GX3199 Aplicación full offline • Nunca se conecta al servidor • Datos precargados o generados por el usuario • Ejemplo: aplicación de finanzas personales
    17. 17. #GX3199 Aplicación basada en servicios • No necesita “backend” • Requiere de servicios externos • Puede o no tener datos locales • Ejemplo: Find My Plane
    18. 18. #GX3199 TEMAS Objeto Offline Database Generación de código Escenarios avanzados
    19. 19. Sincronización
    20. 20. #GX3199 Sincronización Receive Send
    21. 21. #GX3199 Propiedades
    22. 22. #GX3199 Receive • Automática o Manual • Data Synchronization Criteria • Minimum Time Between Synchronizations • Synchronization.Receive() • Por tabla o por registro • Data Synchronization Granularity
    23. 23. #GX3199 Receive: by row • Tablas auxiliares en el servidor • Versión de los datos en el cliente (hash) • Juego de datos por hash en el servidor
    24. 24. #GX3199 Receive: by row Dispositivo Servidor Clientes [ {id=1, nombre=A}, {id=2, nombre=B} ] Hash 3458145ae23490fb142 Clientes [] Clientes, 3458145ae23490fb142 [ {id=1, nombre=A}, {id=2, nombre=B} ] Clientes [ {id=1, nombre=D}, {id=2, nombre=B}, {id=3, nombre=C} ] Hash e59274ac5d5923b6efa8 INS: {id=3, nombre=C} UPD: {id=1, nombre=D} DLT: {id=2} Clientes, e59274ac5d5923b6efa8 [ {id=1, nombre=D}, {id=3, nombre=C} ] 3458145ae23490fb142
    25. 25. #GX3199 Receive: filtrado de datos • Conditions en el objeto Offline Database • Se aplican antes de calcular el hash de la tabla • Parámetros: • Información del dispositivo • Usuario de GAM
    26. 26. #GX3199 Send • Solo Business Components • Tabla auxiliar en SQLite
    27. 27. #GX3199 Send: cuándo • Propiedad Local Changes Processing • When Connected • User Defined: Synchronization.Send()
    28. 28. #GX3199 Send: mapeo de claves • Claves autogeneradas • Usadas como Foreign Key en otras tablas • Cambian de valor en el servidor • Actualización en la respuesta
    29. 29. #GX3199 Send: mapeo de claves Cliente: {CliId=1,...} Factura: {..., CliId=1, ...} Dispositivo Servidor Cliente: {CliId=1,...} Factura: {..., CliId=1, ...} Cliente: {CliId=24,...} Factura: {..., CliId=24, ...} INS INS Factura: {..., CliId=24, ...}Cliente: {CliId=1 => 24} Factura: {CliId=1 => 24}
    30. 30. #GX3199 Send: manejo de errores • Respuesta de error • SynchronizationEventsAPI
    31. 31. #GX23 TEMAS Objeto Offline Database Generación de código Escenarios avanzados Sincronización
    32. 32. #GX23 www.genexus.com/encuentro @mcrispino#GX3199
    1. ¿Le ha llamado la atención una diapositiva en particular?

      Recortar diapositivas es una manera útil de recopilar información importante para consultarla más tarde.

    ×