Artículo
· 26 feb, 2023 Lectura de 6 min

Mi primera experiencia con InterSystems IRIS! (API REST)

Buenas desarrollador!

En este artículo te voy a contar mi experiencia y conocimientos en el poco tiempo que llevo utilizando los distintos productos de InterSystems.

A parte de contar mis vivencias también veremos como hacer una pequeña API Rest con la que poder hacer un CRUD con la base de datos SQL de InterSystems.

Mi historia:

Me presento. Soy Ramón, tengo 23 años y acabo de comenzar mi carrera profesional. Agradezco la oportunidad que tengo de expandir mis fronteras en el mundo de la programación, así como también de poder contar con unos compañeros de trabajo magníficos con los que poder aprender más y mejor.

Mis comienzos utilizando InterSystems se remontan a finales del año pasado realizando algunas pequeñas integraciones y poco a poco asimilando conceptos básicos de una producción. Antes de esto solo realizaba las formaciones de InterSystems Learning donde aprendí ObjectScript entre otros. Considero que InterSystems tiene una curva de aprendizaje compleja pero una vez comprendes su funcionamiento, te provee de utilidades como el "visor de mensajes" que facilitan tus desarrollos al poder consultar en todo momento el flujo de tus mensajes. También se agradece poder hacer componentes en modo gráfico "BPL" e implementar lógica con las reglas de negocio mediante el editor de reglas.

Actualmente quiero poder sacar provecho a la parte de ciencia de datos con python embebido y poder entrenar modelos con instrucciones SQL con IntegratedML.

Y esto sería mi resumen, gracias por leer acerca de mí. wink

Y sin mas dilación... Ahora sí, comencemos con la prueba.

Para realizar esta práctica crearemos un contenedor en docker con la imagen de irishealt-community:2022

version: '3.6'
services:
  iris:
    #image: containers.intersystems.com/intersystems/iris-community:2022.1.0.209.0
    image: containers.intersystems.com/intersystems/irishealth-community:2022.1.0.209.0
    hostname: prueba
    container_name: prueba
    ports:
      - 51773:51773
      - 52773:52773
      - 53773:53773
      - 54773:54773
      - 2188:2188
      - 1972:1972
      - 9980:9980
      - 5000:5000
    command:
      - --check-caps false
      - --password-file /shared/pass.txt
    volumes:
      - type: bind
        source: ./shared # Carpeta en la que se guardará la persistencia de datos
        target: /shared # Path en el que se monta la carpeta
    environment:
      - ISC_DATA_DIRECTORY=/shared/iris

Crearemos un archivo yml con ese contenido y una carpeta shared con un pass.txt donde pondremos la contraseña que queramos utilizar para acceder al portal web.

Una vez realizado los pasos anteriores, abriremos docker desktop y ejecutaremos el siguiente comando en la terminal (es necesario tener docker desktop abierto o nos dará un problema):

Esto nos creará el contenedor.

Accederemos al portal web: http://localhost:52773/csp/sys/utilhome.csp y haremos login con superuser y la contraseña que pusimos en pass.txt

A continuación crearemos nuestra tabla en SQL. Para ello realizaremos lo siguiente:

Iremos a Explorador > SQL

Como "curiosidad" tendremos dos opciones para abrirlo, doble click en SQL o click en SQL y después click en el botón "Ir"

Código para crear nuestra tabla:

CREATE TABLE Prueba.juego
(
id_juego VARCHAR(128), 
nombre VARCHAR(128), 
precio DECIMAL(10,2),
plataformas VARCHAR(128), 
fecha_lanzamiento VARCHAR(128)
)

Insertaremos esa instrucción en el siguiente recuadro "Ejecutar Consulta" y la ejecutaremos.

Una vez creada la base de datos crearemos una API Rest para realizar un CRUD con la base de datos:

Para crear la API Rest he utilizado el estándar que utiliza mi empresa para desarrollar una producción por lo cual voy ha hacer un escueto resumen para que se entienda el funcionamiento.

He creado una producción la cual he llamado PruebaProduction y la he provisto de un servicio web "wsRest", un proceso "Proceso" y para finalizar una operación "Prueba" con un método que ejecuta una SQL embebida para insertar datos en la tabla creada anteriormente.

Al servicio le llegará nuestra petición, lo mandará al proceso y este lo redirigirá a la operación donde esta llamará al método.

Para probar que funciona lo que he creado utilizaremos Postman para hacer una llamada a nuestro servicio web escuchando en el puerto 9988 y con la siguiente url: localhost:9980/ws/publicarJuego

Podremos visualizar el flujo de nuestra petición desde el visor de mensajes.

Una manera de abrirlo es pinchar en nuestro servicio y en su menú pinchar en "Ir al visor de mensajes"

Una vez ahí buscaremos en los criterios básicos el tipo "Comienzo de sesión" y le daremos al botón Buscar.

Para acceder a la traza del mensaje deberemos hacer click en el número de la sesión (marcado con fondo verde). La traza será algo grande y vamos a ver solo el fragmento que nos interesa que es nuestro "POST".

Este mensaje lleva lo siguiente:

<?xml version="1.0" ?>
<!-- type: prueba.msg.PublicarJuegoRequest -->
<PublicarJuegoRequest xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:s="http://www.w3.org/2001/XMLSchema">
<idJuego>Skyrim</idJuego>
<nombre>Skyrim</nombre>
<precio>50.5</precio>
<plataformas>PC, XBOX, PS</plataformas>
<fechaLanzamiento>11/11/2011</fechaLanzamiento>
</PublicarJuegoRequest>

y devuelve lo mismo una vez comprobado de que se ha creado.

El método que se ejecuta en la operación es el siguiente:

Class prueba.bo.core.PruebaCore Extends %RegisteredObject
{

ClassMethod publicarJuego(pRequest As prueba.msg.PublicarJuegoRequest, Output pResponse As prueba.msg.PublicarJuegoResponse, bo As prueba.bo.Prueba) As %Status
{
    #dim sc As %Status = $$$OK
    set pResponse = ##class(prueba.msg.PublicarJuegoResponse).%New()
    set pResponse.exito = 1
    try {
        &sql(INSERT INTO Prueba.juego (id_juego, nombre, precio, plataformas, fecha_lanzamiento) VALUES (:pRequest.idJuego, :pRequest.nombre, :pRequest.precio, :pRequest.plataformas, :pRequest.fechaLanzamiento))
        if (SQLCODE=0) {
            set pResponse.idJuego = pRequest.idJuego
            set pResponse.nombre = pRequest.nombre
            set pResponse.precio = pRequest.precio
            set pResponse.plataformas = pRequest.plataformas
            set pResponse.fechaLanzamiento = pRequest.fechaLanzamiento
        }

    } catch (err) {
        // Si ha ocurrido un error, crear el objeto Status:
        if (err.%ClassName(1)="common.err.exception") && ($$$ISERR(err.status)) {
            set sc = err.status
        } else {
            set sc = $system.Status.Error(err.Code,err.Name,err.Location,err.InnerException)
        }

        set pResponse.exito = 0
        set pResponse.trace = ##class(util.Util).generarTraza("Proceso", "Error en crear juego 3: "_$System.Status.GetErrorText(sc))
        set sc = $$$OK
    }
    quit sc
}

}

Y el mapeo del servicio web será el siguiente:

Class prueba.ws.Rest Extends (rest.ws.RestBase, prueba.ws.RestMethods)
{

XData UrlMap
{
<Routes>
<Route Url="/publicarJuego" Method="POST" Call="publicarJuego"/>
</Routes>
}

}
Class prueba.ws.RestMethods Extends rest.ws.RestBase
{

Method publicarJuego(pInput As %Library.AbstractStream, Output pOutput As %Stream.Object) As %Status
{
    #dim params As %ListOfObjects = ##class(%ListOfObjects).%New()
    quit ..enviar(pInput, .pOutput, "wsRest", "publicarJuego", "publicarJuego", "prueba.msg", params, 0)
}

}

Ya por último podemos comprobar si en la base de datos se ha insertado el registro y efectivamente así ha sido.

Sí, soy consciente de que solo he hecho el método POST, no he creado los métodos PUT, DELETE y GET por no hacer demasiado extenso el artículo. Simplemente tendríamos que crear nuevos métodos a la operación y hacer una SQL para cada método.

Estructura del proyecto en VSCode:

Aún me queda mucho por aprender!!

Gracias por haber leído este artículo hasta el final, espero que te haya gustado y si te ha servido para algo aún mejor. smiley

Comentarios (2)1
Inicie sesión o regístrese para continuar

Hola Ramón! Bienvenido a la Comunidad... Gracias por compartir!! Interesante artículo, con un caso de uso que es bastante común y que otros seguro aprovechan. La ventaja de ir a través de una BO es que igual que en este caso tu has decidido realizar directamente la inserción vía SQL en IRIS, esa misma BO y toda la lógica de negocio anterior, podría estar dirigida a otra BD externa, que puede ser IRIS o no, e incluso a otra tabla. Es decir, la BO te encapsula el almacenamiento. El Business Process o Business Service que la llama, no sabe ni cómo ni dónde se va a almacenar la información... el BO se encarga y puede cambiar sin afectar al resto. Este desacople nos simplifica muchísimo el trabajo de mantenimiento y evolución de la solución!!

Estaría muy bien si pudieras poner tu código en un GitHub y compartirlo junto con el artículo. Seguro que otros lo pueden aprovechar.