#Interopérabilité

0 Abonnés · 67 Publications

Dans le domaine de la santé, l'interopérabilité est la capacité de différents systèmes informatiques et applications logicielles à communiquer, à échanger des données et à utiliser les informations qui ont été échangées.

Article Irène Mykhailova · Oct 31, 2022 2m read

Bonjour aux développeurs !

Il est possible que vous ayez à mettre en œuvre des scénarios qui ne nécessitent pas de référentiel FHIR, mais qui transmettent des demandes FHIR, gèrent les réponses et, éventuellement, exécutent des transformations ou extraient certaines valeurs entre les deux. Je vous propose ici quelques exemples qui peuvent être mis en œuvre en utilisant les systèmes InterSystems IRIS For Health et HealthShare Health Connect.

Dans les exemples suivants, j'ai utilisé des productions d'interopérabilité avec l'adaptateur d'interopérabilité FHIR Interoperability Adapter et les messages HS.FHIRServer.Interop.Request.

Le premier scénario consiste à créer une demande FHIR à partir de zéro (à partir d'un fichier ou d'une requête SQL), puis à l'envoyer à un service FHIR externe. image

Le scénario suivant est une sorte de l'accès direct à FHIR pour les demandes et les réponses à un référentiel FHIR externe, gérant également les jetons OAuth. image

Enfin, le dernier scénario consiste à recevoir des demandes FHIR pour les transmettre ensuite à un service FHIR externe, mais en extrayant des informations ou en modifiant certains champs entre les deux. image

Vous trouverez les détails de mise en œuvre dans l'application Open Exchange :)

J'espère que cela vous sera utile !

0
0 49
Annonce Irène Mykhailova · Août 22, 2022

Salut la communauté,

Nous sommes heureux de vous inviter au prochain webinaire de lancement du concours d'interopérabilité : Créer des solutions durables ! Le sujet de ce webinaire est dédié au concours de programmation d'interopérabilité.

Pendant ce webinaire, nous vous montrerons des certains principes généraux et des problèmes de résolution des problèmes de développement durable, ainsi que quelques bonnes idées qui ont surgi lors des hackathons pour vous inspirer et les choses à faire et à ne pas faire.

De plus, nous discuterons et répondrons aux questions sur la façon de créer des solutions d'interopérabilité à l'aide d'InterSystems IRIS et IRIS for Health.

Date et heure: lundi 29 août – 09 h 00 HAE

Speakers:  
🗣 Tomas Studenik, PDG d'Insane Business Ideas et co-fondateur de Caelestinus
🗣 @Dean Andrews, responsable des relations avec les développeurs  
🗣 @Evgeny Shvarov, responsable de l'écosystème des développeurs InterSystems


0
0 51
Annonce Irène Mykhailova · Août 18, 2022

Salut les développeurs !

Vous voulez montrer vos compétences en interopérabilité ? Participez à notre prochain concours passionnant :

🏆 Concours d'interopérabilité InterSystems : Construire des solutions durables 🏆

Durée : 29 août - 18 septembre

Plus de prix : $13,500 – la distribution des prix a changé !

0
0 78
Annonce Irène Mykhailova · Juil 17, 2022

Salut la communauté,

Nous sommes ravis d'annoncer que les rencontres de développeurs InterSystems sont enfin de retour en personne !

Le premier meetup lié au Python aura lieu le 21 juillet à 18h00 à Democracy Brewing, Boston, MA. Il y aura 2-3 courtes présentations liées au Python, des questions-réponses, des sessions de réseautage ainsi que de la bière gratuite avec des collations et des visites de la brasserie.

AGENDA:

0
0 48
Article Lorenzo Scalese · Mai 12, 2022 8m read

IRIS External Table est un projet Open Source de la communauté InterSystems, qui vous permet d'utiliser des fichiers stockés dans le système de fichiers local et le stockage d'objets en nuage comme AWS S3, en tant que tables SQL. IRIS External Table

Il peut être trouvé sur Github https://github.com/intersystems-community/IRIS-ExternalTable Open Exchange https://openexchange.intersystems.com/package/IRIS-External-Table et est inclus dans InterSystems Package Manager ZPM.

Pour installer External Table depuis GitHub, utilisez :

git clone https://github.com/antonum/IRIS-ExternalTable.git
iris session iris
USER>set sc = ##class(%SYSTEM.OBJ).LoadDir("<path-to>/IRIS-ExternalTable/src", "ck",,1)

Pour installer avec ZPM Package Manager, utilisez :

USER>zpm "install external-table"

Travailler avec des fichiers locaux

Créons un fichier simple qui ressemble à ceci :

a1,b1
a2,b2

Ouvrez votre éditeur préféré et créez le fichier ou utilisez simplement une ligne de commande sous linux/mac :

echo $'a1,b1\na2,b2' > /tmp/test.txt

Dans IRIS SQL, créez une table pour représenter ce fichier :

create table test (col1 char(10),col2 char(10))

Convertissez la table pour utiliser le stockage externe :

CALL EXT.ConvertToExternal(
    'test',
    '{
        "adapter":"EXT.LocalFile",
        "location":"/tmp/test.txt",
        "delimiter": ","
    }')

Et enfin - interrogez la table :

select * from test

Si tout fonctionne comme prévu, vous devriez voir un résultat comme celui-ci :

col1	col2
a1	b1
a2	b2

Retournez maintenant dans l'éditeur, modifiez le contenu du fichier et réexécutez la requête SQL. Ta-Da !!! Vous lisez les nouvelles valeurs de votre fichier local en SQL.

col1	col2
a1	b1
a2	b99

Lecture de données à partir de S3

Sur <https://covid19-lake.s3.amazonaws.com/index.html >, vous pouvez avoir accès à des données constamment mises à jour sur le COVID, stockées par AWS dans la réserve publique de données.

Essayons d'accéder à l'une des sources de données de cette réserve de données : s3://covid19-lake/rearc-covid-19-nyt-data-in-usa/csv/us-states

Si vous avez installé l'outil de ligne de commande AWS, vous pouvez répéter les étapes ci-dessous. Sinon, passez directement à la partie SQL. Vous n'avez pas besoin d'installer quoi que ce soit de spécifique à AWS sur votre machine pour suivre la partie SQL.

$ aws s3 ls s3://covid19-lake/rearc-covid-19-nyt-data-in-usa/csv/us-states/
2020-12-04 17:19:10     510572 us-states.csv

$ aws s3 cp s3://covid19-lake/rearc-covid-19-nyt-data-in-usa/csv/us-states/us-states.csv .
download: s3://covid19-lake/rearc-covid-19-nyt-data-in-usa/csv/us-states/us-states.csv to ./us-states.csv

$ head us-states.csv
date,state,fips,cases,deaths
2020-01-21,Washington,53,1,0
2020-01-22,Washington,53,1,0
2020-01-23,Washington,53,1,0
2020-01-24,Illinois,17,1,0
2020-01-24,Washington,53,1,0
2020-01-25,California,06,1,0
2020-01-25,Illinois,17,1,0
2020-01-25,Washington,53,1,0
2020-01-26,Arizona,04,1,0

Nous avons donc un fichier avec une structure assez simple. Cinq champs délimités.

Pour exposer ce dossier S3 en tant que table externe - d'abord, nous devons créer une table "normal" avec la structure désirée :

-- create external table
create table covid_by_state (
    "date" DATE,
    "state" VARCHAR(20),
    fips INT,
    cases INT,
    deaths INT
)


Notez que certains noms de champs comme "Date" sont des mots réservés dans IRIS SQL et doivent être entourés de guillemets doubles.
Ensuite - nous devons convertir cette table "régulière" en table "externe", basé sur le godet AWS S3 et le type de CSV.

 -- convertissez le tableau en stockage externe
call EXT.ConvertToExternal(
    'covid_by_state',
    '{
    "adapter":"EXT.AWSS3",
    "location":"s3://covid19-lake/rearc-covid-19-nyt-data-in-usa/csv/us-states/",
    "type": "csv",
    "delimiter": ",",
    "skipHeaders": 1
    }'
)

Si vous regardez de près - les arguments des procédures EXT.ExternalTable sont le nom de la table et ensuite une chaîne JSON, contenant plusieurs paramètres, tels que l'emplacement pour rechercher les fichiers, l'adaptateur à utiliser, le délimiteur, etc. En plus de AWS S3 External Table supporte le stockage Azure BLOB, Google Cloud Buckets et le système de fichiers local. GitHub Repo contient des références pour la syntaxe et les options supportées pour tous les formats.

Et enfin - faites une requête sur le tableau :

-- faites une requête sur le tableau :
select top 10 * from covid_by_state order by "date" desc

[SQL]USER>>select top 10 * from covid_by_state order by "date" desc
2.	select top 10 * from covid_by_state order by "date" desc

date	état	fips	cas	morts
2020-12-06	Alabama	01	269877	3889
2020-12-06	Alaska	02	36847	136
2020-12-06	Arizona	04	364276	6950
2020-12-06	Arkansas	05	170924	2660
2020-12-06	California	06	1371940	19937
2020-12-06	Colorado	08	262460	3437
2020-12-06	Connecticut	09	127715	5146
2020-12-06	Delaware	10	39912	793
2020-12-06	District of Columbia	11	23136	697
2020-12-06	Florida	12	1058066	19176

L'interrogation des données de la tableau distant prend naturellement plus de temps que celle de la table "IRIS natif" ou global, mais ces données sont entièrement stockées et mises à jour sur le nuage et sont introduites dans IRIS en coulisse.

Explorons quelques autres caractéristiques de la table externe.

%PATH et tables, sur la base de plusieurs fichiers

Dans notre exemple, le dossier du godet ne contient qu'un seul fichier. Le plus souvent, il contient plusieurs fichiers de la même structure, où le nom de fichier identifie soit l'horodatage, soit le numéro de périphérique, soit un autre attribut que nous voulons utiliser dans nos requêtes.

Le champ %PATH est automatiquement ajouté à chaque table externe et contient le chemin d'accès complet au fichier à partir duquel la ligne a été récupérée.

select top 5 %PATH, * from covid_by_state

%PATH	date	state	fips	cases	deaths
s3://covid19-lake/rearc-covid-19-nyt-data-in-usa/csv/us-states/us-states.csv	2020-01-21	Washington	53	1	0
s3://covid19-lake/rearc-covid-19-nyt-data-in-usa/csv/us-states/us-states.csv	2020-01-22	Washington	53	1	0
s3://covid19-lake/rearc-covid-19-nyt-data-in-usa/csv/us-states/us-states.csv	2020-01-23	Washington	53	1	0
s3://covid19-lake/rearc-covid-19-nyt-data-in-usa/csv/us-states/us-states.csv	2020-01-24	Illinois	17	1	0
s3://covid19-lake/rearc-covid-19-nyt-data-in-usa/csv/us-states/us-states.csv	2020-01-24	Washington	53	1	0

Vous pouvez utiliser ce champ %PATH dans vos requêtes SQL comme n'importe quel autre champ.

Données ETL vers des " tables réguliers "

Si votre tâche consiste à charger des données de S3 dans une table IRIS - vous pouvez utiliser l'External Table comme un outil ETL. Il suffit de le faire :

INSERT INTO internal_table SELECT * FROM external_table

Dans notre cas, si nous voulons copier les données COVID de S3 dans la table local :

--create local table
create table covid_by_state_local (
    "date" DATE,
    "state" VARCHAR(100),
    fips INT,
    cases INT,
    deaths INT
)
--ETL from External to Local table
INSERT INTO covid_by_state_local SELECT TO_DATE("date",'YYYY-MM-DD'),state,fips,cases,deaths FROM covid_by_state

JOIN entre IRIS tables natif et External Table. Requêtes fédérées

External Table est une table SQL. Il peut être joint à d'autres tables, utilisé dans des sous-sélections et des UNIONs. Vous pouvez même combiner la table IRIS "Régulier" et deux ou plusieurs tables externes provenant de sources différentes dans la même requête SQL.

Essayez de créer une table régulier, par exemple en faisant correspondre les noms d'État aux codes d'État, comme Washington - WA. Et joignez-la à notre table basé sur S3.

create table state_codes (name varchar(100), code char(2))
insert into state_codes values ('Washington','WA')
insert into state_codes values ('Illinois','IL')

select top 10 "date", state, code, cases from covid_by_state join state_codes on state=name

Remplacez 'join' par 'left join' pour inclure les lignes pour lesquelles le code d'état n'est pas défini. Comme vous pouvez le constater, le résultat est une combinaison de données provenant de S3 et de votre table IRIS natif.

Accès sécurisé aux données

La réserve de données AWS Covid est publique. N'importe qui peut y lire des données sans aucune authentification ou autorisation. Dans la vie réelle, vous souhaitez accéder à vos données de manière sécurisée, afin d'empêcher les étrangers de jeter un coup d'œil à vos fichiers. Les détails complets de la gestion des identités et des accès (IAM) d'AWS n'entrent pas dans le cadre de cet article. Mais le minimum, vous devez savoir que vous avez besoin au moins de la clé d'accès au compte AWS et du secret afin d'accéder aux données privées de votre compte. <https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys >

AWS utilise l'authentification par clé de compte/secrète autentification pour signer les demandes. https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys

Si vous exécutez IRIS External Table sur une instance EC2, la méthode recommandée pour gérer l'authentification est d'utiliser les rôles d'instance EC2 https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html IRIS External Table sera en mesure d'utiliser les permissions de ce rôle. Aucune configuration supplémentaire n'est requise.

Sur une instance locale/non EC2, vous devez spécifier AWS_ACCESS_KEY_ID et AWS_SECRET_ACCESS_KEY en spécifiant des variables d'environnement ou en installant et en configurant le client AWS CLI.

export AWS_ACCESS_KEY_ID=AKIAEXAMPLEKEY
export AWS_SECRET_ACCESS_KEY=111222333abcdefghigklmnopqrst

Assurez-vous que la variable d'environnement est visible dans votre processus IRIS. Vous pouvez le vérifier en exécutant :

USER>write $system.Util.GetEnviron("AWS_ACCESS_KEY_ID")

Il doit renvoi la valeur de clé.

ou installer AWS CLI, en suivant les instructions ici https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2-linux.html et exécuter :

aws configure

External Table sera alors en mesure de lire les informations d'identification à partir des fichiers de configuration aws cli. Votre shell interactif et votre processus IRIS peuvent être exécutés sous différents comptes - assurez-vous d'exécuter aws configure sous le même compte que votre processus IRIS.

0
0 92
Article Sylvain Guilbaud · Mars 18, 2022 6m read

Dans cet article, je vais vous montrer comment vous pouvez facilement conteneuriser les passerelles .Net/Java.

Pour notre exemple, nous allons développer une intégration avec Apache Kafka.

Et pour interopérer avec le code Java/.Net, nous utiliserons PEX.

Architecture

Notre solution fonctionnera entièrement dans docker et ressemblera à ceci :

Passerelle Java

Tout d'abord, nous allons développer l'opération Java pour envoyer des messages dans Kafka. Le code peut être écrit dans l'IDE de votre choix et il peut ressembler à ceci.

En bref :

  • Pour développer une nouvelle opération commerciale PEX, nous devons implémenter la classe abstraite com.intersystems.enslib.pex.BusinessOperation
  • Les propriétés publiques sont les paramètres de l'hôte de l'entreprise
  • La méthode OnInit est utilisée pour initier la connexion à Kafka et obtenir un pointeur vers InterSystems IRIS
  • OnTearDown est utilisé pour se déconnecter de Kafka (à l'arrêt du processus)
  • OnMessage reçoit le message dc.KafkaRequest et l'envoie à Kafka

Maintenant, plaçons-le dans Docker !

Voici notre dockerfile :

FROM openjdk:8 AS builder

ARG APP_HOME=/tmp/app

COPY src $APP_HOME/src

COPY --from=intersystemscommunity/jgw:latest /jgw/*.jar $APP_HOME/jgw/

WORKDIR $APP_HOME/jar/
ADD https://repo1.maven.org/maven2/org/apache/kafka/kafka-clients/2.5.0/kafka-clients-2.5.0.jar .
ADD https://repo1.maven.org/maven2/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3.jar .
ADD https://repo1.maven.org/maven2/ch/qos/logback/logback-core/1.2.3/logback-core-1.2.3.jar .
ADD https://repo1.maven.org/maven2/org/slf4j/slf4j-api/1.7.30/slf4j-api-1.7.30.jar .

WORKDIR $APP_HOME/src

RUN javac -classpath $APP_HOME/jar/*:$APP_HOME/jgw/* dc/rmq/KafkaOperation.java && \
    jar -cvf $APP_HOME/jar/KafkaOperation.jar dc/rmq/KafkaOperation.class

FROM intersystemscommunity/jgw:latest

COPY --from=builder /tmp/app/jar/*.jar $GWDIR/

Allons-y ligne par ligne et voyons ce qui se passe ici (je suppose que vous connaissez les constructions docker à plusieurs niveaux) :

FROM openjdk:8 AS builder

Notre image de départ est JDK 8.

ARG APP_HOME=/tmp/app
COPY src $APP_HOME/src

Nous copions nos sources du dossier /src dans le dossier /tmp/app.

COPY --from=intersystemscommunity/jgw:latest /jgw/*.jar $APP_HOME/jgw/

Nous copions les sources de la passerelle Java dans le dossier /tmp/app/jgw.

WORKDIR $APP_HOME/jar/
ADD https://repo1.maven.org/maven2/org/apache/kafka/kafka-clients/2.5.0/kafka-clients-2.5.0.jar .
ADD https://repo1.maven.org/maven2/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3.jar .
ADD https://repo1.maven.org/maven2/ch/qos/logback/logback-core/1.2.3/logback-core-1.2.3.jar .
ADD https://repo1.maven.org/maven2/org/slf4j/slf4j-api/1.7.30/slf4j-api-1.7.30.jar .

WORKDIR $APP_HOME/src

RUN javac -classpath $APP_HOME/jar/*:$APP_HOME/jgw/* dc/rmq/KafkaOperation.java && \
    jar -cvf $APP_HOME/jar/KafkaOperation.jar dc/rmq/KafkaOperation.class

Maintenant toutes les dépendances sont ajoutées et javac/jar est appelé pour compiler le fichier jar. Pour un projet concret, il est préférable d'utiliser maven ou gradle.

FROM intersystemscommunity/jgw:latest

COPY --from=builder /tmp/app/jar/*.jar $GWDIR/

Et enfin, les jars sont copiés dans l'image de base jgw (l'image de base se charge également du démarrage de la passerelle et des tâches connexes).

Passerelle .Net

Vient ensuite le service .Net qui recevra les messages de Kafka. Le code peut être écrit dans l'IDE de votre choix et il peut ressembler à ceci.

En bref :

  • Pour développer un nouveau service d'entreprise PEX nous devons implémenter la classe abstraite InterSystems.EnsLib.PEX.BusinessService
  • Les propriétés publiques sont les paramètres de l'hôte de l'entreprise
  • La méthode OnInit est utilisée pour établir une connexion avec Kafka, s'abonner à des sujets et obtenir un pointeur vers InterSystems IRIS
  • OnTearDown est utilisé pour se déconnecter de Kafka (à l'arrêt du processus)
  • OnMessage consomme les messages de Kafka et envoie des messages Ens.StringContainer aux autres hôtes d'Interoperability

Maintenant, plaçons-le dans Docker !

Voici notre dockerfile :

FROM mcr.microsoft.com/dotnet/core/sdk:2.1 AS build

ENV ISC_PACKAGE_INSTALLDIR /usr/irissys
ENV GWLIBDIR lib
ENV ISC_LIBDIR ${ISC_PACKAGE_INSTALLDIR}/dev/dotnet/bin/Core21

WORKDIR /source
COPY --from=store/intersystems/iris-community:2020.2.0.211.0 $ISC_LIBDIR/*.nupkg $GWLIBDIR/

# copier csproj et restaurer en tant que couches distinctes
COPY *.csproj ./
RUN dotnet restore

# copier et publier l'application et les bibliothèques
COPY . .
RUN dotnet publish -c release -o /app

# étape/image finale
FROM mcr.microsoft.com/dotnet/core/runtime:2.1
WORKDIR /app
COPY --from=build /app ./

# Configurations pour démarrer le serveur passerelle
RUN cp KafkaConsumer.runtimeconfig.json IRISGatewayCore21.runtimeconfig.json && \
    cp KafkaConsumer.deps.json IRISGatewayCore21.deps.json

ENV PORT 55556

CMD dotnet IRISGatewayCore21.dll $PORT 0.0.0.0

Allons-y ligne par ligne :

FROM mcr.microsoft.com/dotnet/core/sdk:2.1 AS build

Nous utilisons le SDK complet .Net Core 2.1 pour construire notre application.

ENV ISC_PACKAGE_INSTALLDIR /usr/irissys
ENV GWLIBDIR lib
ENV ISC_LIBDIR ${ISC_PACKAGE_INSTALLDIR}/dev/dotnet/bin/Core21

WORKDIR /source
COPY --from=store/intersystems/iris-community:2020.2.0.211.0 $ISC_LIBDIR/*.nupkg $GWLIBDIR/

Copiez .Net Gateway NuGets de l'image Docker officielle d'InterSystems dans notre image de constructeur

# copier csproj et restaurer comme couches distinctes
COPY *.csproj ./
RUN dotnet restore

# copier et publier l'application et les bibliothèques
COPY . .
RUN dotnet publish -c release -o /app

Construisez notre bibliothèque.

# étape/image finale
FROM mcr.microsoft.com/dotnet/core/runtime:2.1
WORKDIR /app
COPY --from=build /app ./

Copiez les dll de la bibliothèque dans le conteneur final que nous exécuterons réellement.

# Configurats pour démarrer le serveur Gateway
RUN cp KafkaConsumer.runtimeconfig.json IRISGatewayCore21.runtimeconfig.json && \
    cp KafkaConsumer.deps.json IRISGatewayCore21.deps.json

Actuellement, la passerelle .Net doit charger toutes les dépendances au démarrage, nous lui faisons donc connaître toutes les dépendances possibles.

ENV PORT 55556

CMD dotnet IRISGatewayCore21.dll $PORT 0.0.0.0

Démarrez la passerelle sur le port 55556 en écoutant sur toutes les interfaces.

Et voilà, c'est tout !

Voici un docker-compose complet pour que tout fonctionne (y compris Kafka et Kafka UI pour voir les messages).

Pour exécuter la démo, vous dever :

  1. Installer :
  2. Exécuter :
git clone https://github.com/intersystems-community/pex-demo.git cd pex-demo docker-compose pull docker-compose up -d

 

Avis important : Les bibliothèques Java Gateway et .Net Gateway DOIVENT provenir de la même version que le client InterSystems IRIS.

0
0 229
Article Guillaume Rongier · Mars 16, 2022 21m read

Cette formation s'adresse aux débutants qui souhaitent découvrir le framework IRIS Interoperability. Nous utiliserons Docker et VSCode.

GitHub : https://github.com/grongierisc/formation-template

1. Formation Ensemble / Interoperability

Le but de cette formation est d'apprendre le cadre d'interopérabilité d'InterSystems, et en particulier l'utilisation de :

  • Productions
  • Messages
  • Opérations commerciales
  • Adaptateurs
  • Processus métier
  • Services commerciaux
  • Services et opérations REST

TABLE DES MATIÈRES :

2. Cadre de travail

Voici le Framework IRIS.

FrameworkFull

Les composants à l'intérieur d'IRIS représentent une production. Les adaptateurs entrants et les adaptateurs sortants nous permettent d'utiliser différents types de formats comme entrée et sortie pour notre base de données. Les applications composites nous donneront accès à la production via des applications externes comme les services REST.

Les flèches entre tous ces composants sont des messages. Ils peuvent être des demandes ou des réponses.

3. Adapter le framework

Dans notre cas, nous allons lire des lignes dans un fichier csv et les enregistrer dans la base de données IRIS.

Nous ajouterons ensuite une opération qui nous permettra de sauvegarder également des objets dans une base de données externe, en utilisant JDBC. Cette base de données sera située dans un conteneur docker, en utilisant postgre.

Enfin, nous verrons comment utiliser des applications composites pour insérer de nouveaux objets dans notre base de données ou pour consulter cette base (dans notre cas, via un service REST).

Le framework adapté à notre objectif nous donne :

FrameworkAdapted

4. Prérequis

Pour cette formation, vous aurez besoin de :

5. Mise en place

5.1. Conteneurs Docker

Afin d'avoir accès aux images InterSystems, nous devons nous rendre à l'url suivante : http://container.intersystems.com. Après nous être connectés avec nos identifiants InterSystems, nous obtiendrons notre mot de passe pour nous connecter au registre. Dans l'addon docker VScode, dans l'onglet image, en appuyant sur connect registry et en entrant la même url que précédemment (http://container.intersystems.com) comme registre générique, il nous sera demandé de donner nos identifiants. L'identifiant est l'identifiant habituel mais le mot de passe est celui que nous avons obtenu sur le site Web.

De là, nous devrions pouvoir construire et composer nos conteneurs (avec les fichiers docker-compose.yml et Dockerfile donnés).

5.2. Portail de gestion

Nous allons ouvrir un portail de gestion. Il nous donnera accès à une page web où nous pourrons créer notre production. Le portail devrait être situé à l'url : http://localhost:52775/csp/sys/UtilHome.csp?$NAMESPACE=IRISAPP. Vous aurez besoin des informations d'identification suivantes :

IDENTIFIANT : SuperUser

MOT DE PASSE : SYS

5.3. Sauvegarde de la progression

Une partie des choses que nous allons faire sera sauvegardée localement, mais tous les processus et productions sont sauvegardés dans le conteneur docker. Afin de persister tout notre progrès, nous devons exporter chaque classe qui est créée par le portail de gestion avec l'addon InterSystems ObjectScript :

ExportProgress

Nous devrons sauvegarder notre production, le plan d'enregistrement, les processus métier et le transfert de données de cette manière. Après cela, lorsque nous fermerons notre conteneur docker et le recomposerons, nous aurons toujours toute notre progression sauvegardée localement (c'est, bien sûr, à faire après chaque changement via le portail). Pour le rendre à nouveau accessible à IRIS, nous devons compiler les fichiers exportés (en les sauvegardant, les addons InterSystems s'occupent du reste).

6. Productions

Nous pouvons maintenant créer notre première production. Pour cela, nous allons passer par les menus [Interoperability] et [Configurer] :

MenuProduction

Nous devons ensuite appuyer sur [Nouveau], sélectionner le paquet [Formation] et choisir un nom pour notre production :

ProductionCreation

Immédiatement après avoir créé notre production, nous devons cliquer sur [Paramètres de production] juste au-dessus de la section [Opérations]. Dans le menu latéral de droite, nous devrons activer [Test activé] dans la partie [Développement et débogage] de l'onglet [Paramètres] (n'oubliez pas de cliquer sur [Appliquer]).

ProductionTesting

Dans cette première production, nous allons maintenant ajouter des opérations commerciales.

7. Opérations

Une Business Operation (BO) est une opération spécifique qui nous permettra d'envoyer des requêtes depuis IRIS vers une application / un système externe. Elle peut également être utilisée pour enregistrer directement dans IRIS ce que nous voulons.

Nous allons créer ces opérations en local, c'est-à-dire dans le fichier Formation/BO/. En sauvegardant les fichiers, nous les compilerons dans IRIS.

Pour notre première opération, nous allons sauvegarder le contenu d'un message dans la base de données locale.

Nous devons d'abord avoir un moyen de stocker ce message.

7.1. Création de notre classe de stockage

Les classes de stockage dans IRIS étendent le type %Persistent. Elles seront enregistrées dans la base de données interne.

Dans notre fichier Formation/Table/Formation.cls nous avons :

Class Formation.Table.Formation Extends %Persistent
{

Property Name As %String;

Property Salle As %String;

}

Notez que lors de l'enregistrement, des lignes supplémentaires sont automatiquement ajoutées au fichier. Elles sont obligatoires et sont ajoutées par les addons InterSystems.

7.2. Création de notre classe de messages

Ce message contient un objet Formation, situé dans le fichier Formation/Obj/Formation.cls :

Class Formation.Obj.Formation Extends (%SerialObject, %XML.Adaptor)
{

Property Nom As %String;

Property Salle As %String;

}

La classe Message utilisera cet objet Formation, src/Formation/Msg/FormationInsertRequest.cls :

Class Formation.Msg.FormationInsertRequest Extends Ens.Request
{

Property Formation As Formation.Obj.Formation;

}

7.3. Création de notre opération

Maintenant que nous avons tous les éléments dont nous avons besoin, nous pouvons créer notre opération, dans le fichier Formation/BO/LocalBDD.cls :

Class Formation.BO.LocalBDD Extends Ens.BusinessOperation
{

Parameter INVOCATION = "Queue";

Method InsertLocalBDD(pRequest As Formation.Msg.FormationInsertRequest, Output pResponse As Ens.StringResponse) As %Status
{
    set tStatus = $$$OK

    try{
        set pResponse = ##class(Ens.Response).%New()
        set tFormation = ##class(Formation.Table.Formation).%New()
        set tFormation.Name = pRequest.Formation.Nom
        set tFormation.Salle = pRequest.Formation.Salle
        $$$ThrowOnError(tFormation.%Save())
    }
    catch exp
    {
        Set tStatus = exp.AsStatus()
    }

    Quit tStatus
}

XData MessageMap
{
<MapItems>
    <MapItem MessageType="Formation.Msg.FormationInsertRequest"> 
        <Method>InsertLocalBDD</Method>
    </MapItem>
</MapItems>
}

}

La MessageMap nous donne la méthode à lancer en fonction du type de demande (le message envoyé à l'opération).

Comme nous pouvons le voir, si l'opération a reçu un message du type Formation.Msg.FormationInsertRequest, la méthode InsertLocalBDD sera appelée. Cette méthode enregistrera le message dans la base de données locale d'IRIS.

7.4. Ajout de l'opération à la production

Nous devons maintenant ajouter cette opération à la production. Pour cela, nous utilisons le portail de gestion. En appuyant sur le signe [+] à côté de [Opérations], nous avons accès à l'[Assistant d'opérations commerciales]. Là, nous choisissons la classe d'opération que nous venons de créer dans le menu déroulant.

OperationCreation

9.3. Test

Un double clic sur l'opération nous permettra de l'activer. Après cela, en sélectionnant l'opération et en allant dans les onglets [Actions] dans le menu latéral droit, nous devrions être en mesure de tester l'opération (si ce n'est pas le cas, consultez la partie création de la production pour activer les tests / vous devrez peut-être démarrer la production si elle est arrêtée).

En faisant cela, nous allons envoyer à l'opération un message du type que nous avons déclaré plus tôt. Si tout se passe bien, les résultats devraient être comme indiqué ci-dessous :

OperationTest

L'affichage de la trace visuelle nous permettra de voir ce qui s'est passé entre les processus, les services et les opérations. Ici, nous pouvons voir le message envoyé à l'opération par le processus, et l'opération renvoyant une réponse (qui est juste une chaîne vide).

8. Processus métier

Les processus métier (BP) sont la logique métier de notre production. Ils sont utilisés pour traiter les demandes ou relayer ces demandes à d'autres composants de la production.

Les processus métier sont créés dans le portail de gestion :

BPMenu

8.1. BP simple

8.1.1. Création du processus

Nous sommes maintenant dans le concepteur de processus métier. Nous allons créer un BP simple qui appellera notre opération :

BPAddingCall

8.1.2. Modifier le contexte d'un BP

Un BP possède un Contexte. Il est composé d'une classe de requête, la classe de l'entrée, et d'une classe de réponse, la classe de la sortie. Les processus métier n'ont qu'une entrée et une sortie. Il est également possible d'ajouter des propriétés.

Puisque notre BP ne sera utilisé que pour appeler notre BO, nous pouvons mettre comme classe de requête la classe de message que nous avons créée (nous n'avons pas besoin d'une sortie puisque nous voulons juste insérer dans la base de données).

BPContext

Nous avons ensuite choisi la cible de la fonction d'appel : notre BO. Cette opération, étant appelée a une propriété callrequest. Nous devons lier cette callrequest à la requête de la BP (elles sont toutes deux de la classe Formation.Msg.FormationInsertRequest), nous faisons cela en cliquant sur la fonction d'appel et en utilisant le constructeur de requête :

BPBindRequests

Nous pouvons maintenant sauvegarder cette BP (dans le package « Formation.BP » et sous le nom « InsertLocalBDD » ou « Main », par exemple). Tout comme les opérations, les processus peuvent être instanciés et testés via la configuration de production, pour cela ils doivent être compilés au préalable (sur l'écran Concepteur de processus métier).

Pour l'instant, notre processus ne fait que transmettre le message à notre opération. Nous allons le complexifier pour que le BP prenne en entrée une ligne d'un fichier CSV.

8.2. Lecture de lignes CSV par un BP

8.2.1. Création d'une carte d'enregistrement

Afin de lire un fichier et de mettre son contenu dans un fichier, nous avons besoin d'une Carte d'enregistrement (RM). Il existe un Record Mapper spécialisé pour les fichiers CSV dans le menu [Interoperability > Build] du portail de gestion :

RMMenu

Nous créerons le mapper comme suit :

RMCreation

Nous allons créer le mappeur comme ceci :

RMDetails

Maintenant que la carte est créée, nous devons la générer (avec le bouton Générer). Nous devons maintenant avoir une Transformation de données à partir du format de la carte des enregistrements et un message d'insertion.

8.2.2. Création d'une transformation de données

Nous trouverons le créateur de transformations de données (DT) dans le menu [Interoperability > Builder]. Nous allons créer notre DT comme ceci (si vous ne trouvez pas Formation.RM.Csv.Record, peut-être que vous n'avez pas généré la carte d'enregistrement) :

DTCreation

Nous pouvons pouvons maintenant mapper les différents champs ensemble :

DTMap

8.2.3. Ajout de la transformation des données au processus métier

La première chose que nous devons changer est la classe de requête de la BP, puisque nous devons avoir en entrée la carte d'enregistrement que nous avons créée.

BP2ChangeContext

Nous pouvons alors ajouter notre transformation (le nom du processus ne change rien, d'ici nous avons choisi de le nommer Main) :

BP2AddingTransform

L'activité de transformation va prendre la requête de la BP (un enregistrement du fichier CSV, grâce à notre Record Mapper), et la transformer en un message FormationInsertRequest. Afin de stocker ce message pour l'envoyer à la BO, nous devons ajouter une propriété au contexte de la BP.

BP2MsgContext

Nous pouvons maintenant configurer notre fonction de transformation pour qu'elle prenne l'entrée du BP et enregistre sa sortie dans la propriété nouvellement créée. La source et la cible de la transformation RmToMsg sont respectivement request et context.Msg :

BP2RmToMsg

Nous devons faire de même pour Call BO. Son entrée, ou callrequest, est la valeur stockée dans context.msg :

BP2CallBO

Au final, le flux dans la BP peut être représenté comme ceci :

BP2Diagram

8.2.4. Configuration de la production

Avec le signe [+], nous pouvons ajouter notre nouveau processus à la production (si ce n'est pas déjà fait). Nous avons également besoin d'un service générique pour utiliser le record map, nous utilisons EnsLib.RecordMap.Service.FileService (nous l'ajoutons avec le bouton [+] à côté des services). Nous paramétrons ensuite ce service :

ServiceParam

Nous devrions maintenant être en mesure de tester notre BP.

8.2.5. Test

Nous testons l'ensemble de la production comme suit :

TestProductionCSV

Dans le menu Explorateur système > SQL, vous pouvez exécuter la commande

SELECT 
ID, Name, Salle
FROM Formation_Table.Formation

pour voir les objets que nous venons d'enregistrer.

9. Accéder à une base de données externe à l'aide de JDBC

Dans cette section, nous allons créer une opération pour sauvegarder nos objets dans une base de données externe. Nous utiliserons l'API JDBC, ainsi que l'autre conteneur docker que nous avons mis en place, avec postgre dessus.

9.1. Création de notre nouvelle opération

Notre nouvelle opération, dans le fichier Formation/BO/RemoteBDD.cls est la suivante :

Include EnsSQLTypes

Class Formation.BO.RemoteBDD Extends Ens.BusinessOperation
{

Parameter ADAPTER = "EnsLib.SQL.OutboundAdapter";

Property Adapter As EnsLib.SQL.OutboundAdapter;

Parameter INVOCATION = "Queue";

Method InsertRemoteBDD(pRequest As Formation.Msg.FormationInsertRequest, Output pResponse As Ens.StringResponse) As %Status
{
    set tStatus = $$$OK

    try{
        set pResponse = ##class(Ens.Response).%New()
        set ^inc = $I(^inc)
        set tInsertSql = "INSERT INTO public.formation (id, nom, salle) VALUES(?, ?, ?)"
        $$$ThrowOnError(..Adapter.ExecuteUpdate(.nrows,tInsertSql,^inc,pRequest.Formation.Nom, pRequest.Formation.Salle ))
    }
    catch exp
    {
        Set tStatus = exp.AsStatus()
    }

    Quit tStatus
}

XData MessageMap
{
<MapItems>
    <MapItem MessageType="Formation.Msg.FormationInsertRequest"> 
        <Method>InsertRemoteBDD</Method>
    </MapItem>
</MapItems>
}

}

Cette opération est similaire à la première que nous avons créée. Lorsqu'elle recevra un message du type Formation.Msg.FormationInsertRequest, elle utilisera un adaptateur pour exécuter des requêtes SQL. Ces requêtes seront envoyées à notre base de données postgre.

9.2. Configurer la production

Maintenant, via le portail de gestion, nous allons instancier cette opération (en l'ajoutant avec le signe [+] dans la production).

Nous devrons également ajouter le JavaGateway pour le pilote JDBC dans les services. Le nom complet de ce service est EnsLib.JavaGateway.Service.

JDBCProduction

Nous devons maintenant configurer notre opération. Puisque nous avons mis en place un conteneur postgre, et connecté son port 5432, les valeurs dont nous avons besoin dans les paramètres suivants sont :

DSN : jdbc:postgresql://db:5432/DemoData

Pilote JDBC : org.postgresql.Driver

JDBC Classpath : /tmp/iris/postgresql-42.2.14.jar

JDBCParam

Enfin, nous devons configurer les informations d'identification pour avoir accès à la base de données distante. Pour cela, nous devons ouvrir la visionneuse d'identifiants :

JDBCCredentialMenu

L'identifiant et le mot de passe sont tous deux DemoData, comme nous l'avons configuré dans le fichier docker-compose.yml.

JDBCCredentialCreation

De retour à la production, nous pouvons ajouter « Postgre » dans le champ [Identifiant] dans les paramètres de notre opération (il devrait être dans le menu déroulant). Avant de pouvoir le tester, nous devons ajouter le JGService à l'opération. Dans l'onglet [Paramètres], dans les [Paramètres supplémentaires] :

JDBCService

7.5. Test

Lors du test, la trace visuelle doit indiquer un succès :

JDBCTest

Lors du test, la trace visuelle doit montrer un succès :

9.4. Exercice

À titre d'exercice, il pourrait être intéressant de modifier BO.LocalBDD afin qu'il renvoie un booléen qui indiquera au BP d'appeler BO.RemoteBDD en fonction de la valeur de ce booléen.

Indice : cela peut être fait en changeant le type de réponse que LocalBDD renvoie et en ajoutant une nouvelle propriété au contexte et en utilisant l'activité if dans notre BP.

9.5. Solution

Tout d'abord, nous devons avoir une réponse de notre opération LocalBDD. Nous allons créer un nouveau message, dans le fichier Formation/Msg/FormationInsertResponse.cls :

Class Formation.Msg.FormationInsertResponse Extends Ens.Response
{

Property Double As %Boolean;

}

Ensuite, nous modifions la réponse de LocalBDD par cette réponse, et définissons la valeur de son booléen de manière aléatoire (ou non) :

Method InsertLocalBDD(pRequest As Formation.Msg.FormationInsertRequest, Output pResponse As Formation.Msg.FormationInsertResponse) As %Status
{
    set tStatus = $$$OK

    try{
        set pResponse = ##class(Formation.Msg.FormationInsertResponse).%New()
        if $RANDOM(10) < 5 {
            set pResponse.Double = 1
        } 
        else {
            set pResponse.Double = 0
        }
...

Nous allons maintenant créer un nouveau processus (copié sur celui que nous avons fait), où nous ajouterons une nouvelle propriété de contexte, de type %Boolean :

ExerciseContext

Cette propriété sera remplie avec la valeur du callresponse.Double de notre appel d'opération (nous devons définir la [Classe de message de réponse] à notre nouvelle classe de message) :

ExerciseBinding

Nous ajoutons ensuite une activité if, avec la propriété context.Double comme condition :

ExerciseIf

TRÈS IMPORTANT : nous devons décocher Asynchrone dans les paramètres de notre appel LocallBDD, ou l'activité if se déclenchera avant de recevoir la réponse booléenne.

Enfin, nous configurons notre activité d'appel avec comme cible le BO RemoteBDD :

ExerciseRemoteCall

Pour compléter l'activité if, nous devons faire glisser un autre connecteur de la sortie du if vers le triangle join ci-dessous. Comme nous ne ferons rien si le booléen est faux, nous laisserons ce connecteur vide. Après avoir compilé et instancié, nous devrions être en mesure de tester notre nouveau processus. Pour cela, nous devons changer le Target Config Name de notre File Service.

Dans la trace, nous devrions avoir environ la moitié des objets lus dans le csv enregistrés également dans la base de données distante.

10. Service REST

Dans cette partie, nous allons créer et utiliser un service REST.

10.1. Créer le service

Pour créer un service REST, nous avons besoin d'une classe qui étend %CSP.REST, dans Formation/REST/Dispatch.cls nous avons :

Class Formation.REST.Dispatch Extends %CSP.REST
{

/// Ignore any writes done directly by the REST method.
Parameter IgnoreWrites = 0;

/// Convertir par défaut le flux d'entrée en Unicode
Parameter CONVERTINPUTSTREAM = 1;

/// Le jeu de caractères par défaut est utf-8
Parameter CHARSET = "utf-8";

Parameter HandleCorsRequest = 1;

XData UrlMap [ XMLNamespace = "http://www.intersystems.com/urlmap" ]
{
<Routes>
  <!-- Get this spec -->
  <Route Url="/import" Method="post" Call="import" />
</Routes>
}

/// Obtenir cette spécification
ClassMethod import() As %Status
{
  set tSc = $$$OK

  Try {

      set tBsName = "Formation.BS.RestInput"
      set tMsg = ##class(Formation.Msg.FormationInsertRequest).%New()

      set body = $zcvt(%request.Content.Read(),"I","UTF8")
      set dyna = {}.%FromJSON(body)

      set tFormation = ##class(Formation.Obj.Formation).%New()
      set tFormation.Nom = dyna.nom
      set tFormation.Salle = dyna.salle

      set tMsg.Formation = tFormation

      $$$ThrowOnError(##class(Ens.Director).CreateBusinessService(tBsName,.tService))

      $$$ThrowOnError(tService.ProcessInput(tMsg,.output))

  } Catch ex {
      set tSc = ex.AsStatus()
  }

  Quit tSc
}

}

Cette classe contient une route pour importer un objet, liée au verbe POST :

<Routes>
  <!-- Obtenir cette spécification -->
  <Route Url="/import" Method="post" Call="import" />
</Routes>

La méthode d'importation va créer un message qui sera envoyé à un service métier.

10.2. Ajouter notre BS

Nous allons créer une classe générique qui va router toutes ses sollicitations vers TargetConfigNames. Cette cible sera configurée lorsque nous instancierons ce service. Dans le fichier Formation/BS/RestInput.cls nous avons :

Class Formation.BS.RestInput Extends Ens.BusinessService
{

Property TargetConfigNames As %String(MAXLEN = 1000) [ InitialExpression = "BuisnessProcess" ];

Parameter SETTINGS = "TargetConfigNames:Basic:selector?multiSelect=1&context={Ens.ContextSearch/ProductionItems?targets=1&productionName=@productionId}";

Method OnProcessInput(pDocIn As %RegisteredObject, Output pDocOut As %RegisteredObject) As %Status
{
    set status = $$$OK

    try {

        for iTarget=1:1:$L(..TargetConfigNames, ",") {
            set tOneTarget=$ZStrip($P(..TargetConfigNames,",",iTarget),"<>W")  Continue:""=tOneTarget
            $$$ThrowOnError(..SendRequestSync(tOneTarget,pDocIn,.pDocOut))
        }
    } catch ex {
        set status = ex.AsStatus()
    }

    Quit status
}

}

De retour à la configuration de production, nous ajoutons le service de la manière habituelle. Dans le champ [Target Config Names], nous mettons notre BO LocalBDD :

RESTServiceSetup

Pour utiliser ce service, nous devons le publier. Pour cela, nous utilisons le menu [Modifier l'application Web] :

RESTServicePublish

10.3. Test

Enfin, nous pouvons tester notre service avec n'importe quel type de client REST :

RESTTest

Conclusion

Grâce à cette formation, nous avons créé une production capable de lire les lignes d'un fichier csv et de sauvegarder les données lues à la fois dans la base de données IRIS et dans une base de données externe en utilisant JDBC. Nous avons également ajouté un service REST afin d'utiliser le verbe POST pour sauvegarder de nouveaux objets.

Nous avons découvert les principaux éléments du cadre d'interopérabilité d'InterSystems.

Nous l'avons fait en utilisant docker, vscode et le portail de gestion IRIS d'InterSystems.

0
0 322