OData y SAP Gateway – V – Documentar y Probar con OpenAPI

Vamos a hacer un parón en el camino, entenderéis porqué, en el estudio de cómo manejar servicios web OData en SAP con SAP Gateway. Lo que vamos a implementar es una herramienta de documentación y pruebas muy potente para nuestros servicios OData en nuestro sistema SAP. Se trata de implementar la funcionalidad de OpenAPI (el antiguo Swagger) en nuestro SAP para que genere el aplicativo de documentación y pruebas.


Serie de Artículos sobre OData

Este artículo pertenece a una serie de artículos que se van complementando poco a poco como itinerario de conocimiento:


¿Qué es OpenAPI?

OpenAPI es una especificación que define un estándar para construir y describir interfaces de programación de aplicaciones (APIs). OpenAPI es una evolución del formato conocido anteriormente como «Swagger», aunque a veces ambos términos se usan indistintamente. Es ampliamente utilizado para APIs RESTful y permite a los desarrolladores y sistemas documentar y entender cómo interactuar con una API sin necesidad de ver su implementación interna.


Algunos puntos clave de OpenAPI:

  • Estandarización: Define un formato estandarizado para describir los endpoints de una API, incluyendo los métodos HTTP disponibles (GET, POST, PUT, DELETE, etc.), los parámetros de entrada, respuestas y errores que puede generar.
  • Documentación automática: Una de las características más útiles es que permite generar documentación automáticamente a partir de la descripción de la API, lo cual facilita su uso por otros desarrolladores. Este es el motivo principal de este artículo sobre la serie de OData.
  • Interacción simplificada: Con OpenAPI, las herramientas y bibliotecas pueden generar clientes o servidores automáticamente en diversos lenguajes de programación, facilitando el desarrollo de aplicaciones que consumen o exponen APIs.
  • Archivo descriptor: Usualmente, la especificación OpenAPI se escribe en un archivo YAML o JSON, que describe toda la estructura de la API.

Como he comentado anteriormente, este artículo se llama «Documentar y Probar con OpenAPI» porque es extremadamente útil usar OpenAPI para documentar y tener un entorno de pruebas sólido y robusto. Y, dentro de nuestro estudio de OData, nos va a venir muy bien esta herramienta para entender como funciona y en que afecta la configuración del Proyecto Gateway.


Proyecto OpenAPI para SAP en GitHub

Existe un proyecto OpenAPI para SAP open source en GitHub para poder ser importado y usado en los sistemas SAP. El proyecto, de Geert Janklaps es el siguiente geert-janklaps / abap-openapi-ui y lo explica en este artículo de SAP Community ABAP OpenAPI UI v1 released!.

Pero ¿Cómo importamos ese proyecto en nuestro sistema SAP? Pues como vimos en la entrada:

Tenemos la herramienta abapGit para poder manejar los repositorios Git como GitHub en SAP, por lo que el primer paso es instalar la versión standalone de AbapGit. Hago esto porque en principio lo único que quiero es poder importar el proyecto OpenAPI. Si quisiese usar un repositorio Git para trabajar con versionado y todo lo que ofrece instalaría la «Developer version».

Por lo tanto creamos el report ZABAPGIT_STANDALONE en nuestro sistema, como yo solo lo quiero para importar proyectos de ABAP en Git lo crearé como objeto local, porque no necesito transportarlo. Una vez hayamos importado el código tendremos el siguiente report:


Instalar el proyecto ABAP OpenAPI

Una vez tenemos el report de ABAPGit y sabemos donde está el proyecto podemos instalarlo, para ello lo primero que hacemos es crear un repositorio Offline pulsando el botón superior New Offline.

Y como resultado nos habrá creado el repositorio Offline.

Ahora es cuando vamos a importar, en este repositorio, el proyecto ABAP OpenAPI que s el siguiente geert-janklaps / abap-openapi-ui y descargamos el proyecto en ZIP

Y con este ZIP pulsamos el botón ImportZIP del repositorio que hemos creado anteriormente.

Y al importar nos dará un resumen de todos los objetos que va a crear en el repositorio en base al proyecto ABAP OpenAPI.

Si nos parece correcto, pulsaremos el botón Pull para aceptar la creación de los objetos.

Una vez aceptado, nos pedirá orden de transporte y generará los objetos del proyecto.


Transacción ZGW_OPENAPI

Si accedemos a la transacción ZGW_OPENAPI accederemos a esta pantalla:

Donde poder indicar nuestro Servicio OData y que nos genere la vista Swagger UI o JSON y, si seleccionamos Swagger UI nos saldrá una aplicación web OpenAPI con la definición de nuestro servicio, acciones posibles, campos y la posibilidad de probarlo.

Para los que conocen el antiguo Swagger (ahora OpenAPI) ya sabrán las funcionalidades que ofrece. Pero para todos, de cara a los proyectos OData de SAP Gateway.

  • Opciones sobre entidades y propiedades: Si repasamos el artículo OData y SAP Gateway – IV – Opciones sobre Entidades y Campos donde explicamos diversas opciones sobre entidades y propiedades de un proyecto SAP Gateway en la SEGW. Estas opciones se verán reflejadas en el OpenAPI generado, de forma que podremos ver el resultado de nuestra configuración en esta herramienta.
  • Visualización del diagrama entidad relación: en la. Parte superior del OpenAPI generado de nuestro proyecto SAP Gateway veremos todas nuestras entidades y sus relaciones (que vimos en la entrada OData y SAP Gateway – III – Recuperar Subentidades)
  • Plantilla de ejecución de métodos sobre entidades: En base a los métodos de ejecución que se haya generado en base a las opciones de la entidad en el proyecto (GET, POST, PUT) podremos realizar pruebas en OpenAPI. La principal diferencia es que estás pruebas estarán mucho más guiadas y tendrán mucha más información que el Gateway Client. Tendremos campos para Filter, Skip, Top, Order, Select, Count, Expand, además de tener acceso directo a la documentación oficial OData de como se usa.
  • Ejecucion OData REST de métodos sobre entidades: Una vez preparada la ejecución con todos los campos de opciones sobre la ejecución, al ejecutar podremos ver la URL de ejecución, el resultado y posibles errores. Además podremos poner un break point externo en nuestro método de la clase DPC_EXT y al ejecutar podremos capturar la ejecución en debugging.

Para mi, cuando estoy trabajando en proyectos OData en SAP es un imprescindible. Me sirve para entregar una documentación, como capa de pruebas y para ver si la configuración de mi proyecto SAP Gateway OData sea coherente.

OData y SAP Gateway – IV – Opciones sobre Entidades y Campos

En la entrada anterior de esta serie de artículos sobre OData ‘OData y SAP Gateway – II – Publicar un servicio OData en SAP‘ creamos un servicio muy básico de consulta de Businsess Partners, posteriormente añadimos la recuperación de Subentidades. Pero ahora toca para un poco, y saber las opciones de configuración del servicio Gateway. Se viene artículo denso, meramente informativo, pero necesario para sentar las bases.

Serie de Artículos sobre OData

Este artículo pertenece a una serie de artículos que se van complementando poco a poco como itinerario de conocimiento:


Opciones a nivel Modelo de Datos

Tenemos diversas opciones cuando estamos visualizando el modelo de datos, esto nos da una lista de Entidades y, para cada una de ellas, tenemos diversas opciones de configuración.

Donde tenemos las opciones de configuración:

  • Name: Indica el nombre de la entidad.
  • ABAP Structure: La estructura ABAP subyacente que define los campos y tipos de datos de la entidad. Utilizada para mapear los datos de la entidad a una estructura ABAP correspondiente en el backend.
  • Base Type: El tipo base del cual hereda la entidad, esto es utilizado en escenarios de herencia, donde una entidad puede extender otra entidad.
  • Is Abstract: Indicador de si la entidad es abstracta. Las entidades abstractas no pueden instanciarse directamente y se utilizan como base para otras entidades.
  • Label: El nombre legible o etiqueta de la entidad sirve para darle un nombre más amigable para los usuarios finales.
  • Label Editor: Herramienta para editar la etiqueta.
  • Semantics: Define el propósito de los datos contenidos en la entidad, ofreciendo un contexto adicional para entender cómo se deben utilizar e interpretar esos datos. Algunos ejemplos comunes de semántica en las entidades podrían ser CRM, HR, Clientes, Transaccional, etc. Estos términos ayudan a categorizar y definir el contexto de los datos. La ayuda del campo habla de propiedad y los valores posibles también, pero es un error, a nivel de entidad se usa para categorizar el propósito,
  • Thing Type: Checkbox que se selecciona para indicar si un tipo de entidad es una «cosa» (thing) en lugar de un objeto subordinado. En nuestro ejemplo el «objeto» serían los BusinesPartner y los objetos subordinados las entidades subordinadas.
  • Media: Especifica que el objeto de datos pertenece a una colección de medios. Este campo se utiliza para indicar que el tipo de entidad tiene un recurso de medios. Por ejemplo si tuviesemos una entidad Attachment.
  • As Author Property: No es necesario, es parte del estándar AtomPub, que se utiliza para publicar y editar recursos en un servidor web, el servidor se encarga de completar el campo atom:author utilizando la información del usuario autenticado.
  • As ETag Property: Tampoco es necesario, se refiere a una propiedad en una entidad que se utiliza para la gestión de la concurrencia optimista en SAP Gateway. ETag (Entidad Tag) es un mecanismo que ayuda a prevenir conflictos durante actualizaciones concurrentes de los datos. El atributo ETag no necesita ser proporcionado por el cliente, ya que el servidor genera y gestiona este valor automáticamente. El ETag se utiliza para asegurar que las operaciones de actualización y eliminación solo se realicen si la versión de la entidad no ha cambiado desde que fue leída por el cliente.
  • As Published Property: El campo As Published Property se refiere a una propiedad específica en una entidad que se utiliza para almacenar la marca de tiempo (fecha y/o hora) en que el elemento fue publicado por primera vez. Este es un elemento del Protocolo de Publicación Atom (AtomPub) llamado atom:published
  • As Title Property: Se refiere a un elemento en el Protocolo de Publicación Atom (AtomPub) llamado atom:title. Indicará la propiedad que usaremos como texto que transmite un encabezado legible por humanos (título) para un nuevo miembro de la colección.
  • As Updated Property: Es como «As Published Property» pero con la fecha/hora de ultima actualización. Es un elemento del Protocolo de Publicación Atom (AtomPub) llamado atom:updated.

Opciones por entidad y propiedades

Si pulsamos en una entidad, y vamos a ver sus propiedades, vemos que, por cada campo, tenemos varias opciones para ser configuradas. Estas opciones serán las que marquen el comportamiento de dicho campo en dicha entidad en el Servicio OData.

Las opciones de configuración son:

  • Name: Nombre de la propiedad o campo de la entidad, el identificador único del campo dentro de la entidad.
  • Is Key: Marca de si la propiedad es clave en la entidad, indica si el campo es una clave primaria para la entidad. Esto es importante para el uso del servicio y para relacionar dicha entidad con otras subordinadas.
  • Edm. Core Type: Tipo de datos, el tipo de datos en el modelo de datos de entidad (EDM), como Edm.String, Edm.Int32, etc.
  • Precision: Precisión del campo, número de dígitos totales que el campo puede tener.
  • Scale: Escala del campo, número de dígitos que el campo puede tener a la derecha del punto decimal.
  • Max Length: Longitud máxima, la longitud máxima del campo, aplicable principalmente a tipos de datos string.
  • Unit Property Name: Nombre de la propiedad de unidad, campo relacionado que especifica la unidad de medida para este campo (por ejemplo, metros, kilogramos).
  • Creatable: Indicador de que la propiedad puede ser Creada, permite la asignación de valor a esta propiedad en solicitudes de creación (POST).
  • Updatable: Indicador de que la propiedad puede ser Actualizada, permite la asignación de valor a esta propiedad en solicitudes de actualización (PUT/PATCH).
  • Sortable: Indicador de que la propiedad puede ser Ordenada, permite que este campo sea utilizado en sentencias $orderby para ordenar datos.
  • Nullable: Indicador de que la propiedad puede ser Nula, permite que esta propiedad tenga un valor nulo. Por ejemplo, algo que da muchas veces error son las fechas a ‘00000000’, para que funcione correctamente tenemos que poner este indicador.
  • Filterable: Indicador de que la propiedad puede ser Filtrada, permite que esta propiedad sea utilizada en sentencias $filter para filtrar datos.
  • Label: Etiqueta descriptiva de la propiedad, un nombre descriptivo utilizado en interfaces de usuario o documentación.
  • Label Editor: Editor de la etiqueta de la propiedad, herramienta para editar y gestionar el texto de la etiqueta, incluyendo referencias a textos traducibles.
  • Complex Type Name: Nombre del tipo complejo, si la propiedad es de un tipo complejo, este es el nombre del tipo complejo.
  • ABAP Field Name: Nombre del campo en ABAP, el nombre del campo correspondiente en ABAP.
  • ABAP Type: Tipo de datos en ABAP, el tipo de datos ABAP correspondiente (por ejemplo, CHAR, NUMC, DATS).
  • Semantics: Semántica del campo, describe el propósito o la función del campo en un contexto más amplio, proporcionando significado adicional sobre su interpretación y uso.

Opciones por EntitySet

A nivel de EntitySet podemos elegir el comportamiento de cada entidad. Tendremos las siguientes opciones:

  • Name: Nombre del EntitySet. El nombre del conjunto de entidades utilizado en las URIs para acceder a las entidades del conjunto.
  • Entity Type Name: Nombre de la Entidad en la que se basa el EntitySet. El nombre del tipo de entidad que define la estructura y las propiedades de las entidades dentro del conjunto.
  • Label: Etiqueta descriptiva del EntitySet. Un nombre descriptivo utilizado en interfaces de usuario o documentación.
  • Label Text Reference Editor: Editor de referencia de texto de la etiqueta. Herramienta para editar y gestionar el texto de la etiqueta, incluyendo referencias a textos traducibles.
  • Semantics: Semántica del EntitySet. Describe el propósito o la función del EntitySet en un contexto más amplio, proporcionando significado adicional sobre su interpretación y uso.

Opciones de capacidades y comportamiento de las Entidades OData

Sobre el resto de checks de este menú vamos a detenernos un poco más, puesto que son las opciones que marcarán el comportamiento y capacidades de nuestras entidades dentro de un proyecto OData. Estas opciones permiten una gran flexibilidad y control sobre cómo se pueden gestionar y acceder a los datos a través de servicios OData en SAP Gateway, mejorando tanto la seguridad como el rendimiento de las aplicaciones que consumen estos servicios.

Creatable

Indicador de que la entidad puede ser Creada.

  • Descripción: Cuando esta opción está seleccionada, indica que los clientes pueden crear nuevas entidades en el conjunto de entidades utilizando el método HTTP POST.
  • Uso: Permite operaciones de creación de entidades. Esto es útil cuando el servicio OData debe permitir la inserción de nuevos registros en la base de datos.

Updatable

Indicador de que la entidad puede ser Actualizada.

  • Descripción: Permite que las entidades dentro del conjunto sean actualizables utilizando el método HTTP PUT o PATCH.
  • Uso: Esencial para permitir modificaciones a los registros existentes en el conjunto de entidades. Los clientes pueden actualizar una entidad específica mediante su clave primaria.

Deletable

Indicador de que la entidad puede ser Eliminada.

  • Descripción: Permite que las entidades dentro del conjunto sean eliminadas utilizando el método HTTP DELETE.
  • Uso: Facilita la eliminación de registros específicos del conjunto de entidades. Esto es útil para gestionar la vida útil de los datos.

Pageable

Indicador de que la entidad admite paginación.

  • Descripción: Permite la paginación de los resultados de una consulta OData utilizando los parámetros $skip y $top.
  • Uso: Mejora el rendimiento y la usabilidad cuando se trabaja con grandes volúmenes de datos. Los clientes pueden solicitar subconjuntos de datos en cada llamada, lo que facilita la gestión de grandes conjuntos de datos.

Addressable

Indicador de que la entidad es direccionable.

  • Descripción: Permite que las entidades sean accesibles directamente mediante su clave primaria en la URI.
  • Uso: Los clientes pueden acceder a una entidad específica utilizando su URI, facilitando operaciones CRUD directas sobre entidades individuales.

Searchable

Indicador de que la entidad puede ser buscada.

  • Descripción: Permite realizar búsquedas en las entidades utilizando el parámetro de consulta $search.
  • Uso: Facilita la búsqueda de entidades que contienen ciertos términos, mejorando la experiencia del usuario al permitir consultas más complejas.

Subscribable

Indicador de que la entidad puede ser suscrita.

  • Descripción: Permite que los clientes se suscriban a cambios en el conjunto de entidades.
  • Uso: Útil para aplicaciones que necesitan notificaciones o actualizaciones en tiempo real cuando ocurren cambios en los datos.

Requires Filter

Indicador de que se requiere un filtro para acceder a la entidad.

  • Descripción: Obliga a que todas las consultas al conjunto de entidades incluyan un parámetro de filtro ($filter).
  • Uso: Restringe el acceso directo a las entidades, asegurando que las consultas sean más específicas y potencialmente mejorando el rendimiento al reducir el volumen de datos devueltos en cada consulta.

Opciones aplicadas en nuestro proyecto Gateway

Pues para nuestro proyecto Gateway ZODATA_TEST_BP, en base a los apartados de este artículo se han aplicado las siguientes opciones:

Opciones a nivel Modelo de Datos

A nivel de Modelo de Datos, es decir, de Entidad, la configuración aplicada es la siguiente:


Opciones por entidad y propiedades

Por Entidad, se configuran sus propiedades de la siguiente forma:

BusinessPartners

Por ahora no se puede crear (no lo hemos implementado), no se puede actualizar (idem) por lo que las propiedades no tiene sentido que las marquemos como Creatable o Updatabe. Marcamos todos los campos con la posibilidad de hacer SORT, eso podremos afinarlo cuando afinemos el método de GetEntitySet, por ahora ninguno puede ser nulo (que no es lo mismo que vacío), y marcamos para filtrar todos menos el nombre completo.

Address

Lo mismo de la creación y actualización. Marcamos como Nullable las fechas porque si no da un error de que la fecha no puede ser «» y marcamos los campos por los que pensamos ordenar y filtrar.

IdentNumbers

Lo mismo de la creación y actualización. Lo mismo de las fechas Nullable y los filtros.

Relation

Igual que las anteriores.

Roles

Igual que las anteriores.


Opciones por EntitySet

A nivel Set de Entidad, EntitySet, como por ahora no tenemos la actualización ni creación, le ponemos la paginación y la búsqueda y que la entidad de BusinessPartner requiere filtro.


En conclusión

Nuestro proyecto está en una fase muy inicial, solo es de búsqueda y recuperación de datos, por lo tanto muchas de estas opciones directamente no aplican. Pero creo que hemos hecho un repaso exhaustivo de las posibilidades, a nivel configuración de un proyecto Gateway. Importante, he dicho posibilidades a nivel configuración, la lógica la tendremos que implementar en la clase Z*DPC_EXT correspondiente.


Si te interesa, suscríbete al blog por email

OData y SAP Gateway – III – Recuperar Subentidades

En la entrada anterior de esta serie de artículos sobre OData ‘OData y SAP Gateway – II – Publicar un servicio OData en SAP‘ creamos un servicio muy básico de consulta de Business Partners. Ahora toca añadir más funcionalidad a ese servicio que creamos en el anterior artículo. Antes de nada, vamos a recapitular.

Serie de Artículos sobre OData

Este artículo pertenece a una serie de artículos que se van complementando poco a poco como itinerario de conocimiento:


Modelo de datos

Recuperamos cómo era el modelo de datos del servicio que queríamos publicar.

Como podemos ver en el diagrama Entidad-Relación tenemos una Entidad padre «Business Partner» que tiene cuatro entidades relacionadas:

  • Roles del Business Partner
  • Direcciones del Business Partner
  • Relaciones del Business Partner
  • Números de Identificación del Business Partner

Además, este ejemplo lo hemos hecho sencillo, con un solo nivel de relación, por tener un escenario controlado y que esto no se convierta en algo inmanejable de explicar pero, como podreis imaginar, las entidades subordinadas pueden tener otras subentidades a su vez.


Proyecto SAP Gateway creado

Además creamos el siguiente proyecto de Gateway con las entidades del modelo de datos y las relaciones/asociaciones.


Associations Creadas

Vimos en la entrada «OData y SAP Gateway – II – Publicar un servicio OData en SAP» como creábamos Associations o relaciones entre entidades, y el resultado es el siguiente:

Donde vemos que al crear las asociaciones se crean tambien Association Sets y Navigation Properties desde la entidad Padre a las hijas.


Clase de Implementación

En la clase de implementación que crea el proyecto de Gateway ZCL_ZODATA_TEST_BP_DPC_EXT redefinimos solo un método, el GET_ENTITYSET de la entidad BUSINESSPARTNERS.

Pero claro, ahora estamos hablando de relaciones entre entidades, y queremos saber cómo implementar consultas de Business Partners que nos traigan las subentidades de cada BP (Roles, Direcciones, Relaciones con otros BPs y Números de Identificación).

Para ello nos va a valer la Query simple que implementamos, pero queremos que, cuando llamemos a la consulta, nos devuelva los BPs y sus entidades relacionadas.


Uso del $expand en la consulta

Para poder consultar las subentidades de cada entidad en una consulta, usaremos en la URL de llamada al servicio la sentencia $expand. Podemos ver la documentación oficial OData al respecto de la sentencia $expand. Por ejemplo si hacemos una búsqueda de Business Partners y, para cada uno de ellos queremos saber sus roles, realizaremos la consulta de este modo. Para ello ponemos en el Gateway Client (/IWFND/GW_CLIENT).

Error Method ROLESSET_GET_ENTITYSET not implemented

Pero nos da ese error, y esto es porque no hemos implementado el método del GET_ENTITYSET (dame la colección de datos) de la entidad ROLES.


Implementar el GET_ENTITYSET

Para implementar el GET_ENTITYSET nos iremos a nuestra clase Z*DPC_EXT y buscaremos el GET_ENTITYSET de nuestra entidad que queremos consultar. Y redefinimos el método.

Pero claro, una vez redefinido, tenemos que implementar la lógica al respecto de esa acción (GET_ENTITYSET) de esa entidad (ROLES). Vemos que en la firma del método tenemos muchos parámetros de entrada y un par de salida. Son los siguientes:

Parámetros de Entrada

  • IV_ENTITY_NAME: Nombre de la entidad que se va a manejar en el método. Normalmente, cuando hablamos de métodos propios de una entidad concreta, como es el caso, será irrelevante. Pero en otras ocasiones se trata de métodos genéricos, donde tenemos que cambiar la lógica de la acción propuesta en base a este método.
  • IV_ENTITY_SET_NAME: Lo mismo que el anterior pero con el EntitySet.
  • IV_SOURCE_NAME: Nos dirá si partimos de una entidad superior o no y cual es.
  • IT_FILTER_SELECT_OPTIONS: Tabla con los campos de selección que se hayan usado para la búsqueda del EntitySet mediante la sentencia $filter. En este caso si hemos añadido algún criterio de selección para los Roles. Puedes ver la documentación oficial OData sobre el FILTER.
  • IS_PAGING: Nos indica el TOP y SKIP para la consulta, esto sirve para acotar el número de resultados y poder paginar. Por ejemplo, si tenemos 1000 registros pero ponemos un TOP de 100 y un SKIP de 500, recuperaremos del 501 al 600. Puedes ver la documentación oficial OData sobre el TOP y SKIP.
  • IT_KEY_TAB: Si hemos accedido a la entidad por una clave, la suya o la de una entidad superior, en el campo KEY TAB vendrán las claves por las que se accede al EntitySet.
  • IT_NAVIGATION_PATH: Tabla que contiene la ruta de navegación entre entidades.
  • IT_ORDER: Tabla con los criterios de ordenación deseados para recuperar los datos de la colección del EntitySet. Puedes ver la documentación oficial OData sobre ORDERBY.
  • IV_FILTER_STRING: El string de búsqueda con los campos y los valores buscados. Es una forma distinta de manejar los criterios de búsqueda de la tabla IT_FILTER_SELECT_OPTIONS.
  • IV_SEARCH_STRING: Permite realizar búsquedas de texto completo en los datos de una entidad. Este parámetro permite indicar una cadena de búsqueda que se aplicará a varios campos de la entidad, haciendo más fácil encontrar registros que contengan el texto indicado en cualquier parte de esos campos.
  • IO_TECH_REQUEST_CONTEXT: Este parámetro proporciona información técnica sobre la solicitud actual. Contiene detalles relevantes del contexto técnico de la llamada al servicio OData, permitiendo acceder a datos importantes para el procesamiento de la solicitud. Desde este parámetro podemos recuperar mucha información:
    • Usuario llamante
    • Cabecera HTTP
    • Parámetros de la URL
    • IP del cliente
    • Parámetros de la Query

Parámetros de Salida

  • ET_ENTITYSET: Tabla de datos de salida de la consulta para devolver el conjunto de entidades (EntitySet) solicitado. Es una tabla interna, con el tipo de datos de la entidada, que contiene los datos que se devuelven al cliente como resultado de la consulta. Por lo tanto, es la tabla resultado que tenemos que rellenar con los datos buscados una vez aplicados los criterios de entrada.
  • ES_RESPONSE_CONTEXT: Es una estructura de salida de la consulta OData, contiene metadatos sobre la respuesta, como el número de registros devueltos, información de paginación, y cualquier mensaje de error o advertencia.

Implementación de ROLESET_GET_ENTITYSET

Bueno, mucha explicación de lo que son todos los parámetros que se manejan en el GET_ENTITYSET pero no mostramos cómo hacerlo en la práctica. Como es imposible abarcarlo todo en un artículo, los ejemplos de implementación serán sencillos, para complicarlo está la definición de los parámetros del GET_ENTITYSET.

Lo primero que vamos a hacer es ver qué nos llega en la entrada cuando usamos un $expand desde la entidad padre. Para ello, lo que queremos es parar la ejecución en ese método, lo que yo hago es poner una sentencia absurda para poder poner un Breakpoint externo.

Si alguna vez se cumple esto sal corriendo

Al ejecutar de nuevo la llamada en el Gateway Client (/IWFND/GW_CLIENT)

/sap/opu/odata/sap/ZODATA_TEST_BP_SRV/BusinessPartnerSet?$expand=RolesSet

Se abre la sesión debug en el breakpoint externo y podemos ver los datos que nos vienen:

Ahora podemos ver la definición de cada campo que hemos hecho arriba para entenderlo. Vemos que la entidad buscada (IV_ENTITY_NAME) es «Roles» que el origen (IV_SOURCE_NAME) es «BusinessPartner», que no tiene criterios de búsqueda añadidos, ni paginación, ni orden,que la tabla IT_NAVIGATION_PATH tiene un registro con la navigation properties RolesSet desde BusinessPartner, y tiene una clave en la tabla IT_KEY_TAB.

Ahí tenemos nuestro Business Partner padre

Ahora, teniendo el campo Partner en la tabla IT_KEY_TAB vamos a implementar la lógica para rellenar el RolesSet.

Este código se ejecutar una vez por cada Partner servido

Si ahora ejecutamos nuestra sentencia ya veremos datos de los roles de cada uno de los registros de Business Partners.

Implementar GET_ENTITYSET del resto de entidades

Una vez tengamos implementado el GET_ENTITYSET de las subentidades nuestra clase Z*DPC_EXT quedará de este modo:

Y para el que le interese los GET_ENTITYSET quedarán de esta forma:

AddressSet
IdentNumbersSet
RelationSet

Seleccionar las entidades a recuperar

Pero claro, tenemos cuatro subentidades subordinadas de BusinessPartner. ¿Cómo tenemos que hacerlo? Para hacerlo pondremos en la sentencia $expand las subentidades que queramos recuperar, separadas por coma. En nuestro ejemplo la sentencia total sería:

/sap/opu/odata/sap/ZODATA_TEST_BP_SRV/BusinessPartnerSet?$expand=RolesSet,IdentNumbersSet,AddressSet,RelationSet

El resultado será que, para cada Business Partner, tendremos su colección de Roles, Números de Identificación, Direcciones y Relaciones. Por supuesto, para cada subentidad, tendremos que implementar su GET_ENTITYSET correspondiente.

Lo importante de esto es que podemos elegir qué subentidades recuperar, haciendo la recuperación de datos selectiva y dependiente del llamante.


Si te interesa, suscríbete al blog por email

OData y SAP Gateway – II – Publicar un servicio OData en SAP

Nos metemos en harina y dejamos de teorizar. Después del artículo ‘OData y SAP Gateway‘ donde explicamos OData y su uso en SAP. Hoy vamos a aprender lo básico para saber montar un servicio OData en SAP usando el Gateway. Vamos a intentar que esto sea una serie de artículos sobre OData y SAP Gateway.


Serie de Artículos sobre OData

Este artículo pertenece a una serie de artículos que se van complementando poco a poco como itinerario de conocimiento:


Modelo de datos

Lo primero que vamos a hacer es definir nuestro modelo de datos a extraer. Esto no forma parte del proceso, pero es algo que necesitamos tener claro antes de continuar. Aquí os hago una propuesta. Vamos a hacer un servicio sobre Business Partners (BP) y sus objetos relacionados. Si no sabes lo que es un Business Partner revísa la entrada del blog:

Lo escribo en esquema para tenerlo claro.

Datos generales de Business Partner.

  1. Roles de BP
  2. Direcciones
  3. Relaciones
  4. Datos de Área de Ventas

Ahora lo pongo en un diagrama Entidad-relación.

Y además añadimos la estructura sencilla de tablas donde se encuentran estos datos:

Con esta estructura «sencilla» podemos abordar el problema (publicar un servicio web) de múltiples formas. Podríamos crear un servicio de consulta SOAP que por id de BP te devuelva una tabla con tablas anidadas con esa estructura. Pero luego, si queremos crear o actualizar tenemos que crear otro o crear un servicio monstruoso.

La potencia de OData reside en generar estas entidades y subentidades con las acciones CRUD (Create Read Update Delete) que necesitemos sobre cualquier entidad o subentidad. Por lo tanto, con OData hacemos un servicio web de microservicios. Pudiendo elegir entidad por entidad y campo por campo si se puede consultar, crear, actualizar o eliminar.


Estructuras a usar

Para crear este OData podemos hacer que cada entidad del modelo sea una entidad OData. De esta forma veremos que el servicio OData será muy versátil, pudiendo recuperar la profundidad de datos que necesitemos.

Para ello vamos a crear las siguientes estructuras y tipos tabla de las entidades subordinadas a los datos de cabecera.

Estructura para Roles de BP
Tipo Tabla para Roles de BP
Estructura para Direcciones de BP
Tipo Tabla para Direcciones de BP
Estructura de datos para Relaciones del BP
Tipo Tabla de Relaciones del BP
Estructura de Identificadores del BP
Tipo Tabla de Identificadores del BP

Con estos tipos de tablas creamos la estructura de datos de cabecera del BP.

Donde vemos que hay 4 tablas dentro de la estructura para los datos de Roles, Direcciones, Relaciones y Números de identificación del BP.


Gateway Service Builder (SEGW)

Una vez tenemos nuestro modelo y las estructuras creadas tenemos que crear un proyecto en la Gateway Service Builder (SEGW) y añadir la entidad del BP.

Al pulsar el botón de Nuevo nos aparecerá esta ventana

El campo Project Type es importante, porque nos permitiría crear un servicio OData v4. Ya hablaremos de eso, pero por ahora vamos a hacer un servicio OData básico, ya lo complicaremos más adelante.

Una vez creado el proyecto, estará vacío, por lo que vamos a añadir las entidades. Como previamente hemos creado la entidad de datos generales del Business Partner junto con todas las tablas relacionadas, vamos a importar esa estructura generada.

Entramos en la opción de importar una estructura del diccionario

Añadimos nuestra estructura padre de datos generales de Business Partners.

Seleccionamos nuestra estructura padre

Al darle a Next nos pedirá que indiquemos que campos/entidades queremos importar de la estructura seleccionada.

Como la estructura es nuestra, seleccionamos todo

Una vez hayamos seleccionado los campos y entidades nos pedirá, de cada entidad que vaya a crear y campo, cual es la clave, nombre y etiqueta. No obstante es algo que podemos cambiar posteriormente.

En Address la clave es Partner y Addrnumber
De IdentNumber la clave es PARTNER y TYPE.
De Relation la clave es PARTNER1 y PARTNER2.
De Roles la clave es PARTNER y RLTYP

Como resultado tendremos cinco entidades creadas:

  • BusinessPartner
  • Address
  • IdentNumbers
  • Relation
  • Roles

Cada una de ellas con los atributos y claves seleccionados en el punto anterior.

Relaciones entre Entidades

Ahora lo que tenemos que hacer es relacionar las entidades subordinadas con la entidad padre, para ello creamos una Assiciation

Botón derecho en Association y Create

Vamos a ver el ejemplo de Roles, el resto serán iguales puesto que la estructura de entidades es sencilla.

Definición de la Asociación entre entidades y su cardinalidad
Identificamos la asociación de claves entre entidades
Resumen de Asociación

Una vez hayamos hecho todas las asociaciones tendremos que generar el servicio con el botón

Vemos las entidades, asociaciones entre entidades y pulsamos a Generar

Al generar se nos propone unos nombres de clases controladoras del servicio OData. Por norma general esto aceptamos la propuesta y seguimos generando.

Clases controladoras del servicio OData

Al generar se nos añade la información de Service Implementation con todas las acciones CRUD de cada una de las entidades.


Implementación del servicio

Una vez tengamos generado el servicio veremos, en la parte de Service Implementation veremos cada una de las acciones posibles de cada una de las entidades. Por cada entidad tendremos las acciones:

  • Create: Creación de la entidad. Si estamos hablando de BusinessPartner, pues creación de un BP nuevo.
  • Delete: Borrado de la entidad. Por ejemplo, cuando queremos eliminar una dirección del Business Partner.
  • GetEntity: Consulta de los datos por clave, es decir, solo consultamos un registro
  • GetEntitySet: Consulta de los datos por Query, es decir, se va a recuperar una colección (tabla) de datos en base a unos criterios de búsqueda.
  • Update: Actualización de una entidad ya existente.

Como en nuestro caso se trata de un servicio OData de consulta de datos de BPs nos fijamos en la carpeta de Service Implementation del proyecto OData. Donde vemos cada una de las entidades y subentidades las acciones y, al pulsar doble click vemos el objeto técnico y la clase y el método donde se debe implementar la lógica.

De una entidad vemos sus métodos de implementación de la clase DPC_EXT

La clase donde se debe implementar la lógica es la ZCL_<NOMBRE_PROYECTO>_DPC_EXT (guárdate esto en la cabeza que lo vas a usar mucho). Para acceder a la clase es tan sencillo como entrar en la SE24 o entrar, dando doble-click sobre ella en el apartado Runtime Artifacs.

En una primera instancia veremos todos los métodos del CRUD de cada entidad sin redefinir. Para ir añadiendo nuestro código tenemos que ir redefiniendo cada método en la clase DCP_EXT e ir añadiendo la lógica esto lo haremos con más en otro artículo, pero en este vamos a hacer algo muy básico.


Implementado una query simple de BPs

Para implementar la consulta básica de los Business Partners vamos a implementar el método GET_ENTITYSET de la entidad BusinessPartners. Por lo tanto será el método BUSINESSPARTNERS_GET_ENTITYSET de la clase ZCL_ZODATA_TEXT_BP_DPC_EXT. Para ello debemos redefinir este método.

Formas de Redefinir el método en la clase DPC_EXT

Al redefinir el método aparece una propuesta de código.

Propuesta de código

Vamos a realizar una implementación muy muy sencilla para ver la funcionalidad básica. Todo esto puede llegar a ser mucho más complejo. Ya lo explicaremos.

Ponemos una Select muy sencilla para ver cómo se implementa.
En posteriores artículos entraremos en detalle de las posibilidades que nos da de implementación.

Activación del servicio /IWFND/MAINT_SERVICE

Una vez tenemos el servicio OData generado e implementado tenemos que activar el servicio para que pueda ser llamado, Para ello entramos en la transacción /IWFND/MAINT_SERVICE. Es algo que sólo hay que hacerlo una vez por servicio.

En una primera vez, tenemos que añadir el servicio a la lista.

Al pulsar el botón «Añadir servicio» se nos abrirá una búsqueda de servicios, buscamos el nuestro, lo seleccionamos y pulsamos «Añadir servicios seleccionados».

Añadimos nuestro servicio

Nos pedirá el nombre, paquete y si queremos que se genere el nodo ICF.

Una vez añadido el servicio lo tendremos disponible en la lista de servicios de la /IWFND/MAINT_SERVICE.


Probando el servicio

Una vez tengamos el servicio activo en la /IWFND/MAINT_SERVICE podemos entrar en el SAP Gateway Client para probar el servicio OData. Para ello podemos entrar con la transacción /IWFND/GW_CLIENT o bien desde la /IWFND/MAINT_SERVICE pulsando el botón Cliente SAP Gateway.

Podemos pulsar este botón o ir directamente a la Transacción /IWFND/GW_CLIENT

Una vez dentro del SAP Gateway Client veremos la siguiente pantalla. Pero esa URL propuesta lo único que nos dará será un XML de definición del servicio. Si queremos probarlo será en base a una entidad con las acciones CRUD.

Una ves aquí podemos seleccionar la entidad sobre la que queramos hacer la acción con el botón .

Seleccionamos BusinessPartnerSet porque es lo que hemos configurado

Resumen

El resultado de este servicio OData que hemos creado es una consulta básica a los datos de cabecera de los Business Partners. Tan básica que no tiene ni filtros y no sacamos datos de subentidades. Pero el objetivo es que tuviésemos algo que pueda ejecutarse de forma fácil para ver un resultado. En siguientes capítulos de esta serie me gustaría abordar:

  • Subentidades de una entidad (Expanded Entities)
  • Filtros en la consulta
  • Opciones de CRUD por entidad en OData
  • Documentar un servicio OData con OpenAPI/Swagger
  • Probar el servicio con Postman
  • Creación de un OData desde un Módulo de Función

Veremos a lo que llegamos, porque esto tiene mucho contenido, paso a paso.


Si te interesa, suscríbete al blog por email

OData y SAP Gateway

Como el objetivo de este Blog es aprender y aportar conocimiento para que el que quiera aprenda, voy a explicar conceptos que, pareciendo básicos, puede ayudar a la gente a entender el ecosistema y las funcionalidades.


Serie de Artículos sobre OData

Este artículo pertenece a una serie de artículos que se van complementando poco a poco como itinerario de conocimiento:


¿Qué es OData?

OData (Open Data Protocol) es una especificación abierta que define un conjunto de mejores prácticas para la construcción y el consumo de APIs RESTful. Fundamentado en protocolos web estándar HTTP, ATOM y JSON, permite a los desarrolladores exponer y consumir datos a través de servicios web de una manera simple y estándar.


Pero ¿Cuándo y por Quién?

Un poco de historia nos lleva de vuelta al año 2007, cuando Microsoft lideró el desarrollo de OData como parte de su iniciativa de plataforma de datos ADO.NET. En 2012, la Organización para el Avance de Estándares de Información Estructurada (OASIS) tomó el control de la norma, y desde entonces, su adopción y desarrollo han sido constantes.


Funcionalidad

Su capacidad para tratar los datos como recursos RESTful le otorga un papel vital en la construcción de aplicaciones modernas que necesitan interactuar con bases de datos, no solo para la simple lectura y escritura de datos, sino también para operaciones más complejas. OData soporta operaciones CRUD (Crear, Leer, Actualizar, Eliminar), así como consultas más complejas a través de sus capacidades de filtrado, ordenamiento, agrupación y paginación.


OData Entidad y Relaciones

Una entidad en OData es una unidad de datos que representa un objeto del mundo real. Cada entidad tiene un conjunto de propiedades y se identifica de forma única mediante una clave. Pudiendo hacer acciones sobre ella (CRUD). Por ejemplo la entidad Pedido Ventas, Producto, Interlocutor Comercial, etc.

Las entidades a menudo tienen relaciones entre ellas. Por ejemplo en la entidad Pedido de Ventas podemos tener relacionadas las entidades Cliente, Datos Organizativos, Notas, Anexos, etc. De esa forma podemos consultar la entidad padre y además las relaciones que se requieran.


OData ventajas sobre el REST puro

En OData tenemos las siguientes Ventajas:

  • Exploración de Datos: Las relaciones entre entidades en OData permiten a los clientes explorar el gráfico de datos de una manera estructurada y coherente.
  • Consultas Complejas: Con OData, puedes hacer consultas más complejas que abarcan múltiples entidades y sus relaciones, todo en una única petición.
  • Metadatos: OData proporciona un documento de metadatos que describe todas las entidades, propiedades y relaciones.
  • Estándar y Consistencia: Al tener un modelo de datos claramente definido con entidades y relaciones, OData ofrece una forma estándar de interactuar con el API, lo cual simplifica el desarrollo y el mantenimiento.
  • Optimización del Tráfico: Al poder seleccionar sólo las entidades y relaciones específicas que necesitas, se reduce la cantidad de datos transferidos sobre la red.

En una API REST puro, cada recurso (que es similar a una entidad) se accede mediante su propia URL. No hay una forma estándar de describir las propiedades o las relaciones del recurso, lo que puede llevar a una mayor complejidad para entender la estructura y la funcionalidad del API. En REST puro, las relaciones entre recursos a menudo se manejan mediante URL o IDs incrustados en las respuestas, sin una forma estándar de describir o navegar estas relaciones. Esto puede complicar las operaciones como filtrado, ordenación o selección de campos para datos relacionados


Ejemplo de uso de OData

Para poder probar OData podemos usar la guía oficial de OData en su web, usando Postman en el apartado Getting Started – Learning OData on Postman.

Ejemplo de ejecución en postman del proyecto de OData https://www.postman.com/collections/bf7d9130241aaa7160d8

OData en SAP – SAP Gateway

Ahora bien, ¿Cómo se enmarca OData en el ecosistema SAP? Aquí es donde entra en juego SAP Gateway.

SAP Gateway es un componente clave que facilita el camino para conectar dispositivos, entornos y plataformas no-SAP a sistemas SAP, de una forma segura y escalable. SAP Gateway aprovecha OData para exponer los datos y las funcionalidades de los sistemas SAP a aplicaciones basadas en web, móviles y otras plataformas.

Comparativa entre comunicaciones directas o por medio de SAP Gateway y OData

La integración de OData en SAP Gateway permite la creación de interfaces de usuario y la fácil exposición de la funcionalidad de los sistemas SAP. Esto ha allanado el camino para un desarrollo más rápido y eficiente de aplicaciones modernas que consumen datos y funcionalidades de SAP.


Funcionalidades y limitaciones de SAP Gateway

Las funcionalidades que le dan poder a SAP Gateway son:

  1. Exposición de servicios OData: Gateway puede exponer datos y funcionalidades de SAP como servicios OData, permitiendo el desarrollo de aplicaciones web y móviles.
  2. Seguridad y Autorización: Proporciona control granular sobre qué datos y funciones están disponibles para qué usuarios a través de la gestión de roles y autorizaciones de SAP.
  3. Soporte para múltiples formatos de datos: Puede proporcionar datos en formatos JSON y XML, que son comúnmente utilizados en aplicaciones web y móviles.

Desde la introducción de SAPUI5 y Fiori, el papel de OData en el ecosistema SAP ha ganado aún más importancia. SAPUI5 y Fiori se basan en servicios OData para recuperar datos y funcionalidades de los sistemas SAP.

A pesar de sus muchas ventajas, SAP Gateway tiene algunas limitaciones. Por ejemplo, puede no ser la mejor opción para escenarios que requieran transacciones de alta velocidad o una gran cantidad de datos en tiempo real. Además, el rendimiento puede verse afectado si se manejan grandes volúmenes de datos a través de servicios OData.

Transacciones para el uso de SAP Gateway

Existen varias transacciones que son esenciales al trabajar con SAP Gateway. Algunas de las más importantes incluyen:

  • SEGW: SAP Gateway Service Builder, utilizado para desarrollar, probar y activar los servicios oData.
  • /IWFND/MAINT_SERVICE: Para activar y mantener los servicios.
  • /IWFND/ERROR_LOG: Para revisar los registros de error de Gateway.
  • /IWFND/APPS_LOG: Herramienta de rastreo para solucionar errores de aplicaciones en SAP Gateway.
  • /IWBEP/REG_MODEL: Para registrar los modelos de datos.
  • /IWBEP/TRACES: Permite la activación de trazas para servicios oData.
  • /IWFND/CACHE_CLEANUP: Útil para limpiar el caché de metadatos.
  • /IWBEP/CACHE_CLEANUP: Limpia el caché del modelo de datos.
  • SM59: Utilizada para configurar conexiones RFC.
  • SICF: Para configurar y activar los servicios HTTP necesarios para la comunicación oData.

Estas transacciones son cruciales para trabajar con SAP Gateway, desde el desarrollo y mantenimiento de servicios hasta la depuración y el manejo de errores. Utilizarlas eficientemente permitirá una mejor implementación y gestión de servicios oData en el entorno SAP.

Algunos trucos que debes conocer:

  1. Utiliza la herramienta Gateway Client: La transacción /IWFND/GW_CLIENT te permite probar tus servicios directamente en el sistema SAP, lo cual es muy útil durante el desarrollo y la depuración.
  2. Depuración de servicios OData: Puedes depurar los servicios OData en Gateway utilizando la transacción /IWBEP/DEBUG_GW_SERVICE, lo cual es muy útil para solucionar problemas y optimizar tus servicios.
  3. F12 en el Navegador: Cuando estás en Fiori, por ejemplo, es muy útil abrir la consola de desarrollo de Chrome, Firefox, etc. Para saber las llamadas hacia el backend (Gateway) que realiza Fiori. Esto te da una idea del servicio llamado, la request lanzada y la respuesta recibida.

Y podría profundizar más en el uso y manejo de SAP Gateway pero como punto de partida y explicación del OData es más que suficiente. Espero que sea de ayuda, en caso de necesitar más información no dudéis en dejar comentarios en este artículo.


Si te interesa, suscríbete al blog por email