Artículo
Alberto Fuentes · Jul 6 Lectura de 7 min

Cómo aprovechar las consultas y ObjectScript con el framework AppS.REST

Hace un tiempo se publicó el paquete AppS.REST. AppS.REST es un framework para exponer fácilmente clases persistentes de IRIS como recursos REST. Las clases que tienen habilitado AppS.REST soportan operaciones CRUD con poco esfuerzo del desarrollador, acortando la brecha entre los datos persistentes en IRIS y los consumidores de datos, como una aplicación front-end de Angular.

¡Pero las clases de IRIS son mucho más que una simple definición para cargar y guardar registros individuales! Este artículo tiene como objetivo destacar algunas maneras de aprovechar el poder de IRIS en tus aplicaciones REST.  Usando la aplicación de ejemplo Phone.Contact, veremos el soporte de consultas incluido en AppS.REST, el uso de consultas de clase y finalmente los métodos ObjectScript.

Preparación

Puedes encontrar el paquete AppS.REST en Open Exchange. Este artículo utilizará ejemplos de la aplicación Sample Phonebook (disponible en github).  Ambos paquetes se pueden instalar fácilmente con Objectscript Package Manager, que se puede encontrar aquí

Una vez instalados, la aplicación Sample Phonebook generará algunos datos ficticios y configurará la aplicación web necesaria. Esa aplicación web reenviará todas las solicitudes a la clase Sample.Phonebook.REST.Handler. Como estoy haciendo las pruebas en mi equipo local, todas mis solicitudes http estarán en http://localhost:52773/csp/USER/phonebook-sample/api/, pero tu servidor y tu puerto pueden ser diferentes a los míos.

Utilicé la extensión Talend API Tester de Google Chrome para probar todas estas llamadas REST, pero hay muchas buenas herramientas API disponibles.

Cómo habilitar solicitudes simples

Echemos un vistazo a la clase Model.Person, que está habilitada para REST al extender de AppS.REST.Model.Adaptor. Vemos que se muestra como el recurso "contact", como se define en el parámetro RESOURCENAME.

Class Sample.Phonebook.Model.Person Extends (%Persistent, %Populate, %JSON.Adaptor, AppS.REST.Model.Adaptor)
{
Parameter RESOURCENAME = "contact";

Ten en cuenta que aunque la clase IRIS se llama "Person", estamos mostrando la clase como el recurso "contact" a nuestros consumidores de REST. Empezaremos con una solicitud básica de GET para demostrar como un consumidor de datos puede interactuar con este recurso:  

http://localhost:52773/csp/USER/phonebook-sample/api/contact/2

{
"_id": "2",
"name": "Harrison,Angela C.",
"phones":[
{"_id": "2||15","number": "499-388-2049","type": "Office"},
{"_id": "2||32","number": "227-915-3954","type": "Mobile"}
]}

Genial, ¡ya estamos consumiendo datos de IRIS a través de REST! 

Consultas pre-construidas listas para usar

Lo anterior es bueno para cargar una instancia particular conocida de un recurso, pero ¿qué sucede si quieres aprovechar las funcionalidades de consulta de datos de IRIS? El framework AppS.REST nos da algunas capacidades de consulta listas para usarse directamente. Por ejemplo, la siguiente solicitud GET busca todos los contactos:

http://localhost:52773/csp/USER/phonebook-sample/api/contact

Fíjate que tiene el mismo aspecto que la anterior, sólo que sin especificar el ID del contacto. Para solicitar contactos con un nombre determinado, podemos añadir un parámetro URL:

http://localhost:52773/csp/USER/phonebook-sample/api/contact?name[eq]=Harrison,Angela C.

[{
"_id": "2",
"name": "Harrison,Angela C.",
"phones":[{"_id": "2||15", "number": "499-388-2049", "type": "Office"…]
}]

Podemos imaginar una aplicación que permita al usuario buscar contactos por medio de las primeras letras de su apellido. Podemos conseguirlo con otro operador:

http://localhost:52773/csp/USER/phonebook-sample/api/contact?name[stwith]=Harri

Ahora recuperamos todos los contactos cuyos nombres empiezan con "Harri":

[{
"_id": "2",
"name": "Harrison,Angela C.",
"phones":[{"_id": "2||15", "number": "499-388-2049", "type": "Office"…]
},{
"_id": "47",
"name": "Harrison,Yan N.",
"phones":[{"_id": "47||26", "number": "372-757-5547", "type": "Mobile" },…]
}]

AppS.REST admite 7 operadores que se traducen directamente a SQL:
        "lte": " < "
        "gte": " > "         "eq": " = "
        "leq": " <= "
        "geq": " >= "
        "stwith": " %startswith "
        "isnull": " es nulo"

Cómo exponer consultas de clase como acciones REST

¿Qué pasa si queremos aprovechar consultas más complicadas o previamente existentes en nuestra aplicación REST?  ¡Podemos exponer cualquier consulta de clase como una acción REST!

La clase Person tiene una consulta llamada FindByPhone, que utiliza la tabla PhoneNumber para buscar personas por un phoneFragment:

Query FindByPhone(phoneFragment As %String) As %SQLQuery
{
select distinct Person
from Sample_Phonebook_Model.PhoneNumber
where $Translate(PhoneNumber,' -+()') [ $Translate(:phoneFragment,' -+()')
}

El framework AppS.REST generará automáticamente la representación de JSON apropiada a partir de los ID que devuelve la consulta.

Para exponer la consulta como acción REST, añadimos una entrada en el bloque XData llamado ActionMap de la clase Person para definir un endpoint "find-by-phone" en el recurso contact:

XData ActionMap
{
   <action name="find-by-phone" target="class" method="GET" query="FindByPhone">
      <argument name="phoneFragment" target="phoneFragment" source="url" />
   </action>
}

Esa acción ahora se dirige a la consulta de clase de FindByPhone, y espera un argumento para phoneFragment como parámetro de la URL.

Ahora, si hacemos una solicitud GET al endpoint $find-by-phone del recurso de contacto, obtendremos todos los contactos que tengan un número de teléfono que coincida:
http://localhost:52773/csp/USER/phonebook-sample/api/contact/$find-by-phone?phoneFragment=641

[{
"_id": "19",
"name": "Ipsen,Rob Z.",
"phones":[{"_id": "19||211", "number": "641-489-2449", "type": "Home"}]
},{
"_id": "86",
"name": "Newton,Phil Y.",
"phones":[{"_id": "86||108", "number": "380-846-4132", "type": "Mobile"}]
}]

Cómo exponer métodos de ObjectScript como acciones REST

Mostrar consultas puede ser útil, pero ¿qué pasa si queremos mostrar el código de la aplicación que está escrito en ObjectScript? Echemos un vistazo al método AddPhoneNumber de Model.Person:

Method AddPhoneNumber(phoneNumber As Sample.Phonebook.Model.PhoneNumber) As Sample.Phonebook.Model.Person
{
    Set phoneNumber.Person = $This
    $$$ThrowOnError(phoneNumber.%Save())
    Quit $This
}

Este método de instancia se llama para añadir un número de teléfono a una persona que ya existe en la base de datos, así que vamos a ver cómo se puede mostrar como una acción REST, al igual que el ejemplo de consulta de clase anterior.

En el ActionMap de Model.Person, vemos otra entrada que llama al método AddByPhone:

&lt;action name="add-phone" target="instance" method="POST" call="AddPhoneNumber">
&lt;argument name="phoneNumber" target="phoneNumber" source="body" />
&lt;/action>

A diferencia de la acción find-by-phone, esta se dirige a una instancia de Model.Person, por lo que nuestra solicitud de URL deberá incluir un ID después del recurso:

http://localhost:52773/csp/USER/phonebook-sample/api/contact/2/$add-phone

El framework AppS.REST automáticamente creará una instancia de un objeto para la persona con ID=2, y ejecutará el método de instancia en él.

El Action Map define esto como una acción POST, y espera un phoneNumber en la estructura de la solicitud. AppS.REST traducirá automáticamente la estructura JSON de la publicación en una instancia de la clase Phone, ya que ésta también se extiende a AppS.REST.Model.Adaptor.

Poniendo todo junto, ejecutamos POST en http://localhost:52773/csp/USER/phonebook-sample/api/contact/2/$add-phone con la siguiente estructura:

{"number":"123-456-7890","type":"Mobile"}

Si la solicitud tiene éxito, el número de teléfono se añade a nuestro contacto y recibimos de vuelta el objeto Person completo, con el nuevo número de teléfono incluido:

{
"_id": "2",
"name": "Harrison,Angela C.",
"phones":[
{"_id": "2||301", "number": "123-456-7890", "type": "Mobile"},
{"_id": "2||15", "number": "499-388-2049", "type": "Office"},
{"_id": "2||32", "number": "227-915-3954", "type": "Mobile"}
]}

Las acciones son muy flexibles, lo que te permite mostrar casi cualquier funcionalidad de las clases a tus consumidores REST.

Conclusión

Espero que esta rápido vistazo de la aplicación Sample.Phonebook haya demostrado las muchas maneras en que el framework AppS.REST facilita la exposición rápida y sencilla de las clases de IRIS a través de REST.  AppS.REST.Model.Adaptor permite habilitar operaciones CRUD sobre REST para tus clases IRIS con muy pocos pasos manuales. Mostrar las consultas de clase y los métodos de ObjectScript se puede hacer definiendo Acciones en el ActionMap de tu clase.

00
2 1 0 26
Log in or sign up to continue