OData Support in GeneXus - Draft

Unofficial Content

Scenario

Muchas veces se desea integrar una aplicacion GX con fuentes de datos externas.
Cuando dicha fuente proviene de un DBMS y se permite el acceso directo se puede utilizar el DBret para integrarlo al modelo de GeneXus.

En la actualidad, cuando la interfaz con la fuente externa no es SQL, la integración con GeneXus se debe realizar mediante objetos externos y/o procedimientos. La desventaja de esta solución es que no integra la fuente de datos al modelo GeneXus y por lo tanto no se pueden utilizar las construcciones naturales del lenguaje (TRNs, BCs, for eachs, Data Selectors) y se limitan o se hace engorroso el uso de otras (DataProviders, grillas, etc). En este escenario el especificador no puede generar navegaciones para esa fuente de datos.

Para resolver esto se agregar un mecanismo a GeneXus para poder integrar fuentes externas no SQL al modelo de GeneXus, y que este mecanismo sea extensible permitiendo agregar nuevas fuentes de datos.

Este mecanismo agrega un nuevo tipo de datastore (Service) extensible, de manera que una navegación GeneXus pueda calcularse sobre dicho datastore y sea luego traducida en una query hacia la fuente externa.

La solución se compone de 3 fases (diseño, generación, tiempo de ejecución):

  • Diseño: Inspección de la fuente de datos externa e integración al modelo GX
  • Generación: A partir de las navegaciones determinadas por el especificador, generar las queries para la fuente externa
  • Tiempo de ejecución: Ejecución de una query para la fuente externa y reinterpretación de los resultados en el modelo GX

Una de las fuentes de datos posibles, en el escenario anteriormente planteado, es un Servicio OData.

Open Data Protocol (a.k.a OData) is a data access protocol designed to provide standard CRUD access to a data source via a website.

"Open Data Protocol (OData) is a standardized protocol for creating and consuming data APIs. OData builds on core protocols like HTTP and commonly accepted methodologies like REST. The result is a uniform way to expose full-featured data APIs." 
fuente: Odata Home page.

Technology used

La implementación en GeneXus está basada en la versión 4 del protocolo (OData Version Documentation), si bien servicios implementados en versiones anteriores son soportados, no se garantiza que no pueda presentar algún inconveniente.

Para poder ejecutar aplicaciones utilizando esta featura, hay que agregar las bibliotecas de acceso correspondientes para cada lenguaje.

Si se genera C# basta copiar las dlls del directorio de GX gennet\bin\odata al directorio bin de la KB.
Si se genera Java hay que descargar la biblioteca de Olingo Client for Java de (https://olingo.apache.org/doc/odata4/download.html), descomprimir el zip y agregar al classpath todos los jars que hay en ese zip. Además agregar al classpath el archivo GxOData.jar del directorio GXJava de GeneXus.

How to Provide OData Services

En este escenario, una de las funcionalidades necesarias es que las aplicaciones GeneXus puedan exponer su modelo como servicio OData.

Para esto se agrega una property a nivel de generador llamada "Generate OData interface", esto genera las interfaces para que se puedan conumir via OData las transacciones y los Data Providers de la KB.

Por el momento esta solamente en Java y solamente Transacciones.

Features pendientes:
* Soporte para GAM
* Mas funcionalidades especificas de OData ( queryoptions, mediatypes, etc)
* Soporte de Etag &  If-Match
* Odata en Dataproviders.

How to Consume OData Services

Veamos esta funcionalidad con un ejemplo.

Supongamos que queremos integrar a nuestra KB el modelo OData TripPin.

Modelo OData del ejemplo (TripPin)

TripPinODataModel

El mismo consta de 4 entidades principales: 

  • Person
  • Airline
  • Airport
  • Photo

Las demás entidades no pueden ser "entidad base" de una consulta, es decir que por ejemplo no puedo acceder a un Trips directamente sino que debo hacerlo a través de una Person.

El modelo es bastante completo en cuanto a que usa un montón de características de OData v4, algunas de las cuales no se mapean directo al modelo GX:

  • Hay campos de entidades que son collection
  • Hay entidades de tipos de datos complejos (una Person tiene una collection de AddressInfo donde cada AddressInfo es un tipo complejo que tiene por ejemplo una City)
  • Hay campos de tipos enumerados (Gender), "subtipos" (Friends), geograficos (Loc), multimedia (Photo), fórmulas (Concurrency)

Importación del modelo desde GeneXus

Para importar el modelo, se debe ir a Tools ? Application Integration ? External DataStore Service Import

Dado que la importación va a crear atributos con nombre largo, es conveniento agrandar el valor de Significant Attribute Name Length en las propiedades de la versión. 

Se va a mostrar una pantalla como la siguiente:

ExternalDSServiceImport

Allí se debe elegir como Service Provider "OData" y se debe seleccionar un datastore de tipo Service. Si no existe uno se puede crear allí mismo desde el botón New.

Luego se coloca:

  • La URL del servicio, en este caso: http://services.odata.org/V4/(S(40gwjcqlhjmuyfayfnplov0o))/TripPinServiceRW/
  • User y Password para acceder al servicio (en este caso no tiene autenticación)
  • Información extra de la conexión, en este caso filter_strings=n para indicar que el servicio no soporta condiciones por >, <, >=, <= con el tipo de dato String

Al inspeccionar el servicio se presenta un nuevo diálogo para elegir qué entidades importar:

SelectEntitiesODataToImport

Por defecto este diálogo solamente muestra las transacciones asociadas a entidades principales. El proceso de Import en este caso va a importar todas las transacciones adicionales que sean necesarias para poder trabajar con las entidades principales seleccionadas. Si se desea importar especificamente parte del modelo se puede desmarcar "Show only top level" y seleccionar a mano las transacciones que se quiere importar (no recomendado).

El checkbox Normalize Model indica si se quiere que la fuente sea tomada como si los campos respetasen el GIK, o sea que un mismo nombre para un campo que aparece en varias entidades son el realidad el mismo campo. Si se tiene desmarcado cada campo secundario (que no sea una FK) se va a ser renombrado en la transacción que la modela para incluir al comienzo el nombre de la entidad (para que sea único en el modelo GX).

Al darle click a Import se realiza el proceso de importación que agrega los atributos, transacciones, dataviews y grupos de subtipos necesarios para modelar la fuente en GeneXus.

Modelo GeneXus (Opción Normalize Model no seleccionado)

ODataTripPinModelNoNormalized

Modelo GeneXus (Opción Normalize Model seleccionado)

ODataTripPinModelNormalized

Servicios OData de SAP

SAP ha adoptado ampliamente este protocolo para el intercambio de informacion, si bien provee muchos servicios prearmados, los cuales podemos consumir con GeneXus utilizando este mecanismo, tambien es posible invocar funciones Abap (o BAPIs) de SAP ERP, publicadas como servicios OData en SAP NetWeaver Gateway .

Para publicar una BAPI como OData service, seguir el siguiente wizard

SAP NetWeaver Gateway utiliza como metodo de seguridad "cross-site request forgery", se le envía a SAP Usr/Pswrd y este devuelve un token de la forma 'X-CSRF-Token : qyFwSG-_meLAJt-Ei7gOBA==' que hay que utilizar en los sucesivos POST/PUT/PATCH/DELETE que se hagan. Para que GeneXus haga esto en forma automática, al importar el servicio, en el campo Connection info (y/o en la property Additional connection string attributes del Data store asociado a los servicios OData) hay que colocar 'SAP=true'.

Restrictions

  • Momentaneamente, para habilitar la funcionalidad de consumo de fuentes de datos externas, se debe tener un archivo external_ds.flag en el directorio de GeneXus Tero.
  • El porque dejamos la posibilidad de importar el modelo en dos formatos (Normalizado y No Normalizado) es en principio en esta etapa de Beta, estudiaremos si tiene sentido ambos casos, o si siempre tiene más sentido el no normalizado. 
  • OData permite exponer funciones, por ejemplo en el modelo de TripPin hay una función que retorna el aeropuerto más cercano. Esto se podria modelar como un método de un objeto externo, pero por el momento no esta implementado.
  • Hay que trabajar en algunas cosas, por ejemplo no todos los Order son válidos en OData, o algunos orders son parciales. Las queries que estamos generando en general funcionan aunque se toma algunas libertades en cuanto al order. Eso deberia mostrarse en la navegación
  • En Java por ahora solo está implementado la parte de las consultas, pero no las actualizaciones.
  • En .net las actualizaciones sobre tipo multimedia no funciona bien (es un problema de la biblioteca)

 

Availability

As of August 2017, this feature is in an experimental phase in GeneXus 16 (Tero).