Ir al contenido principal

Context en el Pattern WorkWith de GX Evolution 1

Me sucedió trabajar en un proyecto que usaba el Work With Pattern y precisaba filtrar la información a mostrar utilizando como filtros valores que venian dados de antes.

En particular quería mostrar en el WWCustomer solo los clientes de determinado país (el país asociado al usuario que estaba logueado), pero podrían aplicar a multiples casos.Mi tendencia inicial fue utilizar cookies.

Es decir, en el login determinar el país correspondiende al usuario y hacer un "setCookie("Country", CountryId)".
Luego en el WWClientes simplemente agregar la condición: CountryId=getCookie("Country")

Si bien esto me funcionó había dos cosas que no me convencieron:

1. Parece un esquema algo "débil" en el sentido que no está formalizado que esa es información de contexto importante para el WW. Cualquiera podría modificar esa cookie con otro valor o directamente eliminarla y mi esquema dejaría de funcionar.

2. Al utilizar esa condición (con el "getcookie") la misma no va en el SELECT  resultante lo cual puede significar una pérdida de performance, etc.

Dejemos lo del esquema "débil" de lado porque es algo "opinable", lo que si me preocupaba era la performance, paginado, etc,  porque ahí es claro: es mejor que la condición sea parte del SELECT resultante de modo que la consulta la resuelva el DBMS.

¿Cómo hacer que la condición vaya en el SQL?

Fácil, se puede asignar una variable en el evento start y filtrar por ella.
El problema con esto es que si modifico los eventos del WWCustomer entonces pierdo el dinamismo de esa parte con el Pattern y es algo que no quiero perder.

Ahí apareció la solución de usar el contexto.

Es bastante simple:

1. En lugar de un SetCookie lo que se hace es agregar al SDT:Context el elemento que se desea mantener, en mi caso el CountryId:

contextsdt.PNG

y luego en el programa que hacía el SetCookie lo que hago es invocar al procedure SetContext:

contextsetcountry.PNG

2. Una vez que lo tengo “seteado” en el contexto luego solo debo poner la condición en la instancia del Pattern: CountriId=&Context.CountryId

contextconditionpattern.PNG

¿Cómo funciona?

Es bastante sencillo, en el objeto WWCustomer se crea automáticamente la variable &Context basada en el SDT:Context. Esa variable tiene como “Initial Value” el procedure “LoadContext” que es el que se encarga de instanciar &Context con lo que se tiene almacenado en la sesión.

En resumen, todo me queda optimizado y mantengo la automatización, el dinamismo con el pattern, etc.

Moraleja: si usa el WorkWith Pattern préstele atención al manejo del Context, es algo que está bueno para resolver varios casos del estilo.

Hay una KB con un ejemplo sencillo en el GXServer Publico

Comentarios

  1. Esta misma técnica yo la utilizo para hacer mis aplicaciones multitenant. Basta con poner el TenantId en el context, también en el momento del login como en el ejemplo de Gustavo, y luego en cada WW agregar la condición TenantId=&context.TenantId.

    Esto me lleva a pensar que no parece muy complicado potenciar al pattern Work With, para que tenga la opción de ayudarnos a crear aplicaciones multitenant.

    Imaginemos que exista una propiedad de la kb que sea Multitenant true o false, y si fuera true, que solicite informar el atributo que sea Id de la entidad Tenant. Luego en cada instancia de WW también una propiedad que sea Multitenant true, false o “Use environment property value”, esto es porque probablemente existan algunas entidades compartidas por los distintos tenant, por ejemplo Países.

    Con esto el Genexus ya dispondría de la información como para agregar en las condition de cada objeto el filtro por tenant; y lo que parecería más difícil, agregar en la estructura el TenantId, pero bueno, ya tenemos el Category pattern que toca la estructura cuando es aplicado.

    Para el equipo de desarrollo de Genexus seguramente no será tan simple de hacerlo como para mí describirlo (habría que resolver el tratamiento de autonuméricos, por ejemplo), pero me parece una idea alineada con lo que a futuro van a necesitar todos los sistemas y de paso se agrega funcionalidad al viejo pattern Work With que si bien es muchísimo lo que aporta actualmente, a veces extraño poder hacer un prompt o hacer múltiples WW para una misma transacción como lo hacía en las primeras versiones sobre la 9.0. También se me ocurre que por el porte del cambio, podríamos recibirlo en algún Ux de la evo 1 y no esperar hasta la evo 2 con las alternativas que Artech está evaluando según una conferencia que presencié en el encuentro.

    Saludos.
    Marcelo Arias
    marcelo.arias@saasforeach.com

    ResponderBorrar
  2. Marcelo,

    Compartimos la importancia del tema y se está trabajando en eso (que hacer app multitenant sea basicamente una propiedad), incluso Federico Azzato dio una charla en el XX Encuentro (http://www.events.genexus.com/portal/hgxpp001.aspx?16,73,1248,O,S,0,,2185) no tengo claro el status a hoy e incluso hay unos cuantos casos "divertidos" como formulas, etc, pero seguro es un objetivo a cubrir en el corto plazo.

    Saludos,
    Gustavo

    ResponderBorrar

Publicar un comentario

Entradas más populares de este blog

Abrir links con aplicaciones nativas y no el browser (deeplinking)

El problema que tengo con algunas aplicaciones Android/iOS es que cuando recibo un link por algún medio (mail, tweet, etc) al abrirlo me lo abre con el browser, en lugar de abrirlo con una aplicación nativa asociada a ese “contenido”. Por ejemplo, si recibo un link a un tweet espero que lo abra con alguna aplicación de twitter que tenga instalada y no con el browser. De modo análogo si recibo un mail con una nota de prensa de un medio X y tengo la aplicación de ese medio X instalada, espero que el link lo abra con la aplicación nativa y no con el browser. Lo mismo quisiera con mi aplicación de "banking" o cualquiera que tenga instalada y sepa manejar ese "contenido" (link). Los motivos son bastante obvios pero los resumo en: la experiencia de usuario es mucho mejor en la aplicación nativa que en el navegador. Parte importante del tema es que el mismo link sea válido tanto para ver el contenido en el browser como para verlo en la aplicación, porque como prove

¡A la salud de mi KB!

Es bueno, especialmente en "bases de conocimiento" (KB) que han pasado por varias versiones de Genexus, chequear su "estado de salud". En este sentido KBDoctor  es una herramienta que ayuda mucho, principalmente desde el punto de vista del "modelo" Genexus (atributos, calls, definiciones de variables, etc) representado en una KB. También es útil revisar la salud de los archivos que lo soportan. Hasta la 9.0 eran archivos C-tree (los famosos .DAT) que tenían indices (los famosos .IDX) y teníamos en "rebuild -y" que mejoraba esos archivos y sobre todo reconstruía los indices. A partir de la X las KBs se almacenan en MS SQL Server por lo cual la administración de la misma pasó de ser un "file server" a un "database server". En este sentido algo que me ha dado muy buenos resultados es el "CheckKnowledgeBase".

Rocha:Constantes tipo fecha

En la Rocha se soportan constantes del tipo fecha o fecha-hora con formato ANSI/ISO (AAAA-MM-DD HH:MM:SS).  Tecnicamente (Sintáxis): <date>::=    [0-9]{1,4}"/"[0-9]{1,2}"/"[0-9]{1,2} | [0-9]{1,4}"."[0-9]{1,2}"."[0-9]{1,2} | [0-9]{1,4}"-"[0-9]{1,2}"-"[0-9]{1,2} <hms>::=    [0-9]{1,2}[ap] | [0-9]{1,2}":"[0-9]{1,2}[ap]? | [0-9]{1,2}":"[0-9]{1,2}":"[0-9]{1,2}[ap]? <constant> ::=   "#"<date>"#" | "#"<date> <hms>"#" | "#"<hms>"#" Funcionalmente Se pueden utilizar esas constantes en las reglas, eventos, propiedades, etc (todo lugar donde se utilice el parser): Algunos ejemplos básicos: &FechaInicial=#2007-01-01# &FechaHoraInicial=#07-1-1 11:15a# &HoraInicial=#11a# Me parece bueno no tener que escribir funciones (CTOD, TTOC) sobre constantes tipo char para lograr una fecha y mucho mejor aun en