Artículo
Ariel Arias · Nov 23 Lectura de 6 min

API REST, a una producción, un ejemplo rápido

Bajo el escenario que ya tenemos una API REST, funcionando, y queremos incorporarla a una producción para contar con trazabilidad y todas las ventajas que ofrece IRIS para interoperar, dejo este artículo para cambiar una API existente que responde un JSON, para responder el mismo JSON pero dejando sus trazas en una producción de la misma instancia.

Lo primero, ya contamos con una aplicación creada, llamada /restapi y que tiene como DispatchClass: Testing.REST.ApiDisp (o la clase que tenemos en nuestra instancia).

Este ejemplo, responderá un JSON a la petición: /restapi/test

La clase:

Class Testing.REST.ApiDisp Extends %CSP.REST
{

Parameter HandleCorsRequest = 1;

XData UrlMap [ XMLNamespace = "http://www.widgetsdirect.com/urlmap" ]
{
<Routes>
   <Route Url="/test" Method="GET" Call="TestAPI" Cors="false" />
</Routes>
}

ClassMethod TestAPI() As %Status
{
   Set %response.ContentType="application/json"

   SET retObj = {}
   SET retMessage = "API TEST"

   SET retEjemplo = "Puede incluir mensajes predeterminados"
   SET retObj.Message = retMessage
   SET retObj.Ejemplo = retEjemplo
   Set retObj.remoteip = %request.CgiEnvs("REMOTE_ADDR")
   Set retObj.cluster1 = %request.CgiEnvs("GATEWAY_INTERFACE")
   Set retObj.PeerAddr = $SYSTEM.TCPDevice.PeerAddr()
   Set retObj.LocalAddr = $SYSTEM.TCPDevice.LocalAddr()

   Set person = ##class(Testing.REST.Model.Persons).%OpenId(1)

   Set persona = {}
   Set persona.nombre = person.Name
   Set persona.titulo = person.Title

   Set retObj.datos = persona


   WRITE retObj.%ToJSON()
   QUIT $$$OK
}
}

Es una prueba sencilla en la que además de un mensaje, retrna un objeto persona (usamos el ID 1 sólo como ejemplo).

A la petición GET http://localhost:10012/restapi/test veremos un JSON así en espuesta:
`
{
"Message": "API TEST",
"Ejemplo": "Puede incluir mensajes predeterminados",
"remoteip": "172.26.0.1",
"cluster1": "CGI/1.1",
"cgienvsize": "",
"servername": "localhost",
"PeerAddr": "127.0.0.1",
"LocalAddr": "127.0.0.1",
"datos": {
"nombre": "Campos,Ashley D.",
"titulo": "Assistant Sales Rep."
}
}

`

Vamos a modificar la clase para extender además de %CSP.REST la clase Ens.BusinessService.

Al extender esta clase, podemos agregar en una producción nuestra clase REST (Testing.REST.ApiDisp). Al agregarla, podemos mantener el nombre de la misma clase para instanciar el BS o cambiarle el nombre para hacelo más fácil de identificar. En este caso vamos a usar el nombre REST.BS:

image

Luego, podemos agregar una línea para crear un BS. La línea que necesitamos:

`Set tSC = ##class(Ens.Director).CreateBusinessService("REST.BS", .Service)`

Vamos a crear un nuevo métod para no perder el que teníamos previamente como referencia solamente. Creamos un método llamado TestAPIBS:

`
ClassMethod TestAPIBS(idperson As %Integer) As %Status
{
    Set retObj = {}
    Set retMessage = "API TEST"
    Set retObj.Message = retMessage

    #Dim testreq As Testing.REST.Messages.TestReq
    #Dim testresp As Testing.REST.Messages.TestResp

    Set testresp = ##class(Testing.REST.Messages.TestResp).%New()
    Set testreq = ##class(Testing.REST.Messages.TestReq).%New()

    Set tSC = ##class(Ens.Director).CreateBusinessService("REST.BS", .Service)

    Set testreq.Codigo = idperson

    Set tSC = Service.ProcessInput(testreq,.testresp)
    Quit:$SYSTEM.Status.IsError(tSC) 
    Set %response.ContentType="application/json"

    If (testresp.Status = "OK") {
        Set persona = {}
        Set persona.nombre = testresp.Nombre
        Set persona.titulo = testresp.Titulo
        Set persona.provincia = testresp.Estado
        Set persona.compania = testresp.Company

        Set retObj.datos = persona
    }Else{
        Set retObj.estado = testresp.Status
        Set retObj.error = testresp.ErrorDesc
    }


    Write retObj.%ToJSON()
    Quit $$$OK
}
`

Para usar una producción, normalmente se requiere un BP y BO. Para este ejemplo, agregamos una clase tipo Ens.Request y otra tipo Ens.Response para utilizarlas dentro de la producción:

Request:

`
Class Testing.REST.Messages.TestReq Extends Ens.Request
{

Property Codigo As %Integer [ InitialExpression = 1 ];

}`

Response:

`Class Testing.REST.Messages.TestResp Extends Ens.Response
{

Property Codigo As %String(MAXLEN = "");

Property Nombre As %String(MAXLEN = "");

Property Titulo As %String(MAXLEN = "");

Property Estado As %String(MAXLEN = "");

Property Company As %String(MAXLEN = "");

Property Status As %String;

Property ErrorDesc As %String;

}`

A modo de ejemplo, usamos una clase Persona:

`Class Testing.REST.Model.Persons Extends (%Persistent, %Populate, %JSON.Adaptor)
{

Property Name As %String(MAXLEN = "");

Property Company As %String(MAXLEN = "");

Property Title As %String(MAXLEN = "");

Property State As %String(MAXLEN = "");
}`

Trasladamos la lógica de abrir un objeto "Persona" basado en un ID a un BO:

`Class Testing.REST.BO.GetPersonData Extends Ens.BusinessOperation
{

Parameter ADAPTER = "EnsLib.SQL.OutboundAdapter";

Property Adapter As EnsLib.SQL.OutboundAdapter;

Parameter INVOCATION = "Queue";

Method TestConnection(pRequest As Testing.REST.Messages.TestReq, Output pResponse As Testing.REST.Messages.TestResp) As %Status
{
    set tSC = $System.Status.OK()
    try
    {
        set pResponse=##class(Testing.REST.Messages.TestResp).%New()

        Set person = ##class(Testing.REST.Model.Persons).%OpenId(pRequest.Codigo)

        If $ISOBJECT(person) {
            Set pResponse.Status = "OK"
            Set pResponse.Codigo = person.%Id()
            Set pResponse.Nombre = person.Name
            Set pResponse.Titulo = person.Title
            Set pResponse.Company = person.Company
            Set pResponse.Estado = person.State
        }
        else {
            Set pResponse.Status = "NOK"
            Set pResponse.ErrorDesc = "No se encuentra persona " _ pRequest.Codigo
        }        

    }
    catch (tException)
    {
        set tSC = tException.AsStatus() 
        set pResponse.ErrorDesc = $System.Status.GetErrorText(tSC)
    }
    quit tSC
}

XData MessageMap
{
<MapItems>
    <MapItem MessageType="Testing.REST.Messages.TestReq"> 
        <Method>TestConnection</Method>
    </MapItem>

</MapItems>
}

}
`

Un BP que conectará nuestro BS con el BO:

image

Ahora modificamos la clase Dispatch para manejar las llamadas al GET que use el método creado (TestAPIBS):

`<Route Url="/testbs/:id" Method="GET" Call="TestAPIBS" Cors="false" />`

Agregamos el parámetro "id" sólo para hacer interactivo el GET y poder obtener la información de la persona basados precisamente en este Id.

Para el GET http://localhost:10012/restapi/testbs/10

Podemos ver una respuesta como esta:

image

Espero esto ayude a quienes inician con creación de APIs con IRIS, y puedan agregar funcionalides.

00
1 0 0 22
Log in or sign up to continue