#Tutoriel

0 Abonnés · 35 Publications

Publication qui comprend l'explication étape par étape de la fonctionnalité ou de la solution technique.

Annonce Irène Mykhailova · Sept 29, 2025

Bonjour à la communauté,

Nous sommes ravis de vous présenter un tout nouveau tutoriel Instruqt :

🧑‍🏫 RAG avec InterSystems IRIS Vector Search

Ce laboratoire pratique vous guide dans la création d'un chatbot IA basé sur la génération augmentée de récupération (RAG) et optimisé par InterSystems IRIS Vector Search. Vous découvrirez comment la recherche vectorielle peut être exploitée pour fournir des réponses actualisées et précises, en combinant les atouts d'IRIS et de l'IA générative.

✨ Pourquoi l'essayer ?

0
0 21
Article Iryna Mykhailova · Sept 17, 2025 3m read

Salut tout le monde! Ayant récemment rejoint InterSystems, je me suis rendu compte que, même en ayant la version communautaire de la Community Edition totalement gratuite et géniale, la manière d'y accéder n'était pas très claire. J'ai donc décidé de rédiger un guide présentant toutes les différentes façons d'accéder à la version communautaire de la Community Edition d'InterSystems IRIS:

Obtention de la Community Edition d'InterSystems IRIS sous forme de conteneur

L'utilisation d'une instance conteneurisée de la Community Edition est l'approche recommandée pour les personnes qui découvrent le développement sur InterSystems IRIS. À mon avis, c'est aussi la plus simple. La Community Edition d'InterSystems IRIS est disponible sur DockerHub; si vous avez un compte SSO InterSystems, vous pouvez également la trouver dans le registre de conteneurscan also find it in the InterSystems Container Registry.

Quel que soit le cas, vous devrez extraire l'image de votre choix à l'aide de l'interface CLI Docker:

docker pull intersystems/iris-community:latest-em
// or
docker pull containers.intersystems.com/intersystems/iris-community:latest-em

Ensuite, vous devrez démarrer le conteneur: Afin d'interagir avec IRIS en dehors du conteneur (par exemple, pour utiliser le portail de gestion), vous devrez publier certains ports. La commande suivante exécutera le conteneur IRIS Community Edition avec les ports du superserveur et du serveur web publiés ; notez que vous ne pouvez rien avoir d'autre en cours d'exécution qui dépende des ports 1972 ou 52773!

docker run --name iris -d --publish 1972:1972 --publish 52773:52773 intersystems/iris-community:latest-em

Obtention de la Community Edition d'InterSystems IRIS dans le Cloud

Vous souhaitez peut-être éviter complètement le problème d'avoir à gérer une installation locale; et si tel est le cas, vous pouvez vous lancer avec un déploiement cloud de la Community Edition d'InterSystems IRIS. Tous les principaux fournisseurs de cloud sont pris en charge. Consultez notre page Cloud Partners page pour plus d'information. Dans cet exemple, nous allons nous concentrer sur le déploiement sur AWS.

Commencez par rechercher la Community Edition d'InterSystems IRIS sur AWS Marketplace:

Vous pouvez cliquer sur "View purchase options" (Afficher les options d'achat) et vous connecter à votre compte pour afficher la page d'abonnement:

 

En faisant défiler vers le bas, vous pouvez cliquer sur “Subscribe” (s'abonner), remplir l'information requise, puis cliquer sur “Deploy” (déployer) pour déployer la Community Edition d'InterSystems IRIS en tant que nœud cloud! Consultez notre documentation ici déploiement d'InterSystems IRIS dans le cloud pour plus de d'information.

Obtention de la Community Edition d'InterSystems IRIS sous forme de kit d'installation

Si vous préférez travailler avec InterSystems IRIS installé directement sur votre machine et que vous ne souhaitez pas utiliser de conteneurs, vous pouvez télécharger un kit d'installation pour votre système à partir du service InterSystems Evaluation Service. Pour télécharger un kit d'installation, vous devez avoir un identifiant SSO InterSystems. Bonne nouvelle: si vous avez un compte sur la Communauté de développeurs, vous en avez déjà un! Sinon, vous pouvez cliquer sur "Créer un nouveau compte" et suivre les étapes indiquées:

 Une fois connecté, la page suivante devrait s'afficher. Cliquez sur "Télécharger la version Community Edition" pour commencer le téléchargement du kit d'installation:

 

Vous serez invité à fournir certaines information concernant la version exacte d'InterSystems IRIS dont vous avez besoin et la plate-forme sur laquelle vous allez l'installer:

 

Dans la plupart des cas, vous devrez sélectionner « InterSystems IRIS Community » et la version la plus récente disponible pour votre plateforme. Suivez les instructions d'installation fournies dans la documentation spécifique à votre plateforme, et le tour est joué!

0
0 25
Article Guillaume Rongier · Juil 2, 2025 4m read

Bonjour chers ingénieurs interface et développeurs d'applications,     

Saviez-vous que Python peut être utilisé dans des productions ou des intégrations?

L'interface utilisateur de configuration de production est low-code, mais dans de nombreux projets, vous pouvez arriver au point où il est nécessaire d'écrire du code. Comme nous l'avons vu dans le cours Architecture d'intégration, les Business Process comportent de nombreux emplacements où insérer du code, notamment l'éditeur BPL (pour les Business Process BPL) et l'éditeur DTL (pour les transformations de données).

😯 À partir d'InterSystems IRIS 2025.1, Python et InterSystems ObjectScript sont tous deux pris en charge dans les éditeurs BPL et DTL. 😄 Vous pouvez choisir entre ces langues selon vos préférences personnelles, et pas selon des besoins techniques. 😍

Rédaction du code Python dans l'éditeur BPL

Python est pris en charge dans l'éditeur BPL depuis InterSystems IRIS 2024.1. Examinons un Business Process BPL:

Business Process BPL comprend les activités suivantes (dans l'ordre) : activité Début, activité Affectation, activité Code avec un logo Python, activité If avec un logo Python, activité Transformation du côté vrai de l'activité If, et activité Fin.

Dans l'activité <code>, GetWinningBid, remarquez l'icône Python. En ouvrant cette activité <code>, on peut voir que le champ intitulé Code contient des instructions Python! Ces instructions utilisent la bibliothèque intégrée iris pour ouvrir un objet d'un ID donné.

Une activité Code provenant d'un éditeur BPL. Le langage est défini sur Python. Le code indique # Utilisation du corps de la requête pour ouvrir l'objet Bid avec l'ID donné. New line. bidID = request.id. New line. context.winningBid = iris.cls("AuctionServer.Bid")._OpenId(bidID).

Vous pouvez définir le langage pour l'ensemble du BPL (Python ou ObjectScript) via le paramètre Language dans l'onglet General u BPL, puis utiliser le menu déroulant Language Override (Remplacement du language) dans un champ de code donné pour remplacer la valeur par défaut du BPL.

L'activité <code> n'est pas la seule activité qui analyse le code dans un Business Process BPL. L'activité <code> analyse les instructions de code complètes, mais autres champs des activités BPL acceptent également des expressions de code. Vous pouvez les reconnaître grâce au menu déroulant Language Override (Remplacement du langage), où vous pouvez remplacer la valeur par défaut de BPL. 

Par exemple, l'activité <if>, qui crée un flux logique conditionnel, a un champ appelé Condition qui accepte des expressions de code. Il a un champ correspondant appelé Condition Language Override (Remplacement du langage de condition). Dans cet exemple, ce champ est défini sur Python.

Lorsque Python n'était pas encore pris en charge dans ces domaines, les ingénieurs d'interface devaient savoir comment écrire des expressions logiques dans ObjectScript. Par exemple, vous deviez savoir que || signifie Or, et && signifie And. Vous pouvez désormais utiliser Python, dont la syntaxe pour les expressions logiques est plus proche du langage naturel.

Dans l'éditeur BPL, s'il vous faut importer des paquetages Python, vous pouvez le faire sous les instructions Python From/Import dans l'onglet General.

Rédaction du code Python dans l'éditeur DTL 

Python est également pris en charge dans les champs de code de l'éditeur DTL depuis InterSystems IRIS 2025.1. Les utilisations courantes du code personnalisé dans DTL sont le formatage de chaînes et les calculs.

Une transformation de données DTL convertissant un objet source, AuctionServer.Bid, into a target object, AuctionServer.Order

Si vous devez importer des paquetages Python dans l'éditeur DTL, recherchez l'onglet Paramètres Transformation et utilisez le champ d' instruction Python From / Import. Le langage par défaut pour les expressions de code peut également être défini dans l'onglet d'instructions Transformation .

Dans l'onglet Paramètres de transformation du DTL, le langage est défini sur Python et le champ des instructions Python From / Import contient la mention from numpy import random.

Pour trouver les champs d'analyse de code des actions DTL, il suffit de rechercher tout champ associé à une liste déroulante Language Override. Par exemple, dans l'action <code> du DTL, vous pouvez écrire des instructions de code complètes. Les actions telles que Set, If, Trace et autres prennent en charge les expressions de code, qui peuvent être écrites en Python ou en ObjectScript.

Une activité de code issue d'une transformation de données DTL, avec le langage défini sur Python. Le contenu du champ de code indique bidders = [bid.User for bid in source.Lot.Bids()]. New line. bidders = set(bidders). New line. target.NumOutbid = (len(bidders) - 1).

Flux de travail axés sur le code

Si vous maîtrisez le processus d'édition de productions via un code, vous pouvez modifier les fichiers BPL et DTL via leurs fichiers de configuration. Cette méthode n'est pas aussi simple que les interfaces de l'éditeur, mais elle est très intuitive pour les programmeurs expérimentés.

Vous pouvez également utiliser Python pour écrire des méthodes dans des fonctions utilitaires personnalisées et des composants personnalisés, tels que des opérations commerciales et des services commerciaux (à l'exception des méthodes de rappel callback methods, comme défini dans la documentation).

Récapitulatif 

  • L'éditeur DTL et l'éditeur BPL prennent désormais en charge le code et les expressions Python. 
  • Si nécessaire, indiquez les paquetages que vous souhaitez importer via les paramètres généraux de BPL ou DTL. 
  • Vous pouvez définir un langage par défaut pour chaque DTL/BPL et remplacer des champs spécifiques si nécessaire.

Rejoignez la conversation!

  • Avez-vous déjà utilisé Python pour créer des intégrations personnalisées? 
  • Quelles questions avez-vous au sujet de la prise en charge de Python dans les intégrations?
  • Ajoutez vos commentaires ci-dessous!
0
0 28
Article Sylvain Guilbaud · Mai 19, 2025 3m read

Bonjour à la communauté,

Vous cherchez un moyen d'intégrer InterSystems IRIS® for Health à votre équipe ? Exploitez tout le potentiel de cette plateforme grâce à ces ressources de formation InterSystems. Grâce à une combinaison de formations en ligne et en présentiel, vous pouvez accompagner différents rôles au sein de votre organisation et préparer votre équipe à la réussite.

Ressources d'intégration pour chaque rôle

Développeurs

0
1 52
Article Sylvain Guilbaud · Mai 19, 2025 3m read

Bonjour à la communauté,

Exploitez tout le potentiel d'InterSystems IRIS et accompagnez votre équipe dans son intégration grâce à la gamme complète de ressources de formation InterSystems, disponibles en ligne et en présentiel, adaptées à chaque rôle de votre organisation. Les développeurs, administrateurs système, analystes de données et intégrateurs peuvent rapidement se familiariser avec la solution.

Ressources d'intégration pour chaque rôle

Développeurs

0
0 54
Article Guillaume Rongier · Avr 14, 2025 5m read

Les référentiels, applications et serveurs FHIR servent généralement des données cliniques en petites quantités, par exemple pour renvoyer des données sur un patient, ses médicaments, ses vaccins, ses allergies, ou d'autres renseignements. Cependant, il est courant qu'une grande quantité de données au format FHIR/JSON soit demandée pour être utilisée pour charger des Data Lakes, identifier des cohortes étudiées, la santé de la population ou transférer des données d'un DME (dossier médical électronique) à un autre. Pour répondre à ces scénarios d'activités commerciales qui nécessitent d'importantes extractions et charges de données, il est recommandé d'utiliser la fonctionnalité d'accès aux données en masse FHIR fournie par l'institution HL7.

InterSystems IRIS for Health met en œuvre l' ccès aux données de masse FHIR (FHIR Bulk Data Access) avec la fonctionnalité BFC - Bulk FHIR Coordinator (https://docs.intersystems.com/irisforhealthlatest/csp/docbook/DocBook.UI.Page.cls?KEY=HXFHIR_bulk). Selon la documentation d'InterSystems, le BFC « simplifie l'interaction des données de masse FHIR pour les clients et, pour ne pas surcharger un serveur FHIR avec des demandes de données de masse, le Bulk FHIR Coordinator (BFC) d'InterSystems sert d'intermédiaire dans l'interaction entre un client de données de masse et un point d'extrémité de serveur de ressources FHIR pour les demandes de données de masse. Le Bulk FHIR Coordinator peut faciliter l'exportation de données de masse FHIR pour les serveurs de ressources FHIR qui ne prennent pas en charge nativement l'interaction de données de masse". Le diagramme de la documentation illustre comment le coordinateur FHIR en bloc sert d'intermédiaire dans l'interaction entre un client et les endpoints FHIR:

Le Coordinateur Bulk FHIR sert d'intermédiaire entre un client et un endpoint FHIR

Ainsi, si vous souhaitez migrer d'un serveur FHIR vers IRIS for Health, vous pouvez utiliser BFC pour vous connecter à un serveur FHIR cible afin d'obtenir toutes les données dont vous avez besoin sous forme de fichiers json (ressources ndjson), et les importer dans votre serveur FHIR InterSystems.

Dans cet article, vous découvrirez étape par étape les différentes manières de configurer et d'utiliser BFC pour obtenir toutes les données patient d'un référentiel FHIR dans des fichiers JSON en vue d'une utilisation ultérieure.

Étape 1 - Obtenir/configurer une instance IRIS for Health pour utiliser BFC

Si vous n'avez pas d'instance IRIS for Health, cliquez sur le lien suivant pour en obtenir une: https://openexchange.intersystems.com/package/iris-fhir-template. Suivez les procédures d'installation suivantes:

1.1 Installation de Docker:

Clone/git extrait le référentiel dans n'importe quel répertoire local

git clone https://github.com/intersystems-community/iris-fhir-template.git

Ouvrez le terminal dans ce répertoire et lancez:

docker-compose up -d


1.2 Ou installation de l'IPM (nécessite un IRIS for Health en cours d'exécution):

Ouvrez l'installation d'IRIS for Health avec le client IPM installé. Appel dans n'importe quel espace de nom:

USER>zpm "install fhir-server"

Ainsi, le serveur FHIR sera installé dans l'espace de noms FHIRSERVER.

Ou encore, pour une installation programmée, on peut appeler ce qui suit:

set sc=$zpm("install fhir-server")

Étape 2 - Création d'un nouveau justificatif d'identité

1. Access the Management Portal for the namespace FHIRSERVER (http://localhost:32783/csp/sys/%25CSP.Portal.Home.zen?$NAMESPACE=FHIRSERVER).

2. Accédez à l'Interopérabilité > Configuration > Informations d'identification:

3. Paramétrez les valeurs BulkCreds et enregistrez:

  • Identifiant: BulkCreds
  • Nom d'utilisateur: _SYSTEM
  • Mot de passe: SYS

Étape 3 - Configuration du BFC (Bulk Data Coordinator)

1. Accédez à BFC UI (http://localhost:32783/csp/healthshare/fhirserver/bulkfhir/index.html):

2. Appuyez sur le bouton + Nouvelle configuration > Création d'une nouvelle:

3. Configuration des paramètres:

  • Nom: BFC_Patients
  • Endpoint BFC (tout chemin relatif): /bulkfhir/patients
  • Gardez tous les autres paramètres tels quels

4. Appuyez sur le bouton Next.

5. Selectionnez HS.BulkFHIR.Auth.BasicAuth.Adapter et appuyez sur le bouton Next

6. Selectionnez HS.BulkFHIR.Fetch.PureFHIR.Adapter pour le champ Fetch Adapter et définissez les valeurs suivantes:

  • URL de l'endpoint: http://fhir-template:52773/fhir/r4
  • Configuration SSL: BFC_SSL
  • Type d'autorisation: HTTP
  • Identifiant HTTP: BulkCreds
  • Acceptez les valeurs par défaut pour tous les autres champs

7. Appuyez sur le bouton Next.

8. Selectionnez la valeur de HS.BulkFHIR.Storage.File.Adapter pour le champ Storage Adapter et définissez les valeurs suivantes:

  • Storage Adapter: HS.BulkFHIR.Storage.File.Adapter
  • URL du fichier: /bulkfhir/file
  • Répertoire: /usr/irissys/mgr/Temp/BulkFHIR/FHIRSERVER/

9. Appuyez sur le bouton Next.

10. Vérifiez la configuration et cliquez sur le bouton de configuration "Configure" en bas de la page:

11. Vous verrez le message de réussite: 

Étape 4 (étape finale) - Récupération de vos données de masse

1. Accéder à Exportations (Exports):

2. Appuyez sur le bouton + Nouvelle demande d'exportation:

3. Sélectionnez la valeur du champ de configuration BFC_Patients et appuyez sur le bouton Next

4. Sélectionnez l'option Patient et appuyez sur le bouton Export Now (Exportation immédiate):

5. Vous verrez le message de réussite:

6. Appuyez sur le bouton d'actualisation "Refresh" en haut de la page:

7. Consultez la session de configuration BFC_Patients terminée:

8. Appuyez sur le dernier bouton de téléchargement "Download" ():

9. Consultez la liste des fichiers json exportés:

10. Téléchargez n'importe quel fichier et consultez son contenu:

11. Pour lancer une exportation FHIR en masse à partir d'un client REST, envoyez une requête GET à votre endpoint BFC en indiquant l'opération souhaitée, par exemple:

  •     Système — GET https://bfcEndpoint/$export
  •     Patient — GET https://bfcEndpoint/Patient/$export
  •     Groupe — GET https://bfcEndpoint/Group/groupID/$export

12. Plus de détails sur l'utilisation via l'API: https://docs.intersystems.com/healthconnectlatest/csp/docbook/DocBook.UI.Page.cls?KEY=HXFHIR_bulk#HXFHIR_bulk_export_rest_initiate

13. Plus de détails sur l'utilisation de BFC:

  • https://docs.intersystems.com/healthconnectlatest/csp/docbook/DocBook.UI.Page.cls?KEY=HXFHIR_bulk#HXFHIR_bulk_intro
  • https://www.youtube.com/watch?v=J-AVP9MFMWI

Profitez-en!!

0
0 35
Article Guillaume Rongier · Mars 26, 2025 7m read

Introduction

Une API REST (Representational State Transfer) est une interface qui permet de faire communiquer différentes applications entre elles via le protocole HTTP, en utilisant des opérations standard telles que GET, POST, PUT, et DELETE. Les API REST sont largement utilisées dans le développement de logiciels pour exposer des services accessibles par d'autres applications, permettant ainsi l'intégration entre différents systèmes.

Cependant, pour garantir que les APIs soient faciles à comprendre et à utiliser, une bonne documentation est essentielle. C'est là qu'OpenAPI entre en jeu.

OpenAPI est une norme de description pour les APIs RESTful. Elle permet de définir de manière structurée les fonctionnalités d'une API, en spécifiant les extrémités disponibles, les types de données acceptés et renvoyés, les paramètres requis et les réponses attendues. Toutes ces informations sont rassemblées dans un fichier de spécification (généralement avec une extension .yaml ou .json), qui peut être interprété par des outils automatisés pour générer du code, de la documentation, etc.

La spécification OpenAPI Specification est conçue pour être lisible par les machines et les humains, permettant la description, la production, la consommation et la visualisation de services web RESTful de manière standardisée. Par conséquent, un document OpenAPI représente une description formelle de l'API, utile à la fois pour les développeurs qui ont besoin de l'utiliser et pour les outils qui peuvent l'exploiter pour automatiser divers processus.

Pourquoi est-il utile de définir un fichier de spécifications?

L'adoption d'OpenAPI pour documenter une API offre plusieurs avantages, notamment:

  • Clarté: elle fournit une documentation détaillée et structurée, permettant aux développeurs de comprendre rapidement comment interagir avec l'API, quelles requêtes doivent être envoyées et quelles données peuvent être attendues en réponse.
  • Automatisation: la documentation peut être générée automatiquement à partir du code, et rester à jour avec tout changement d'API.
  • Interactivité: des outils tels que Swagger, une suite open source de documentation et de test d'API, incluent Swagger UI. Cela vous permet d'explorer et de tester les API directement depuis le navigateur, ce qui simplifie le développement, la vérification et la compréhension des API.
  • Normalisation: l'utilisation d'OpenAPI garantit que la documentation suit un format commun et reconnu, ce qui facilite l'intégration avec d'autres outils et services.

Comment créer un document OpenAPI?

Il existe deux approches principales pour générer un fichier de spécification OpenAPI:

  • Approche "code-first" (automatique): si une API REST a déjà été développée dans InterSystems IRIS, vous pouvez générer automatiquement la documentation OpenAPI sans écrire de fichier de spécification manuellement.
  • Approche "specification-first" (manuelle): dans ce cas, le fichier OpenAPI est écrit manuellement en YAML ou JSON, décrivant tous les points de terminaison, paramètres et réponses attendues. Cette approche est utile lorsque vous souhaitez définir l'API avant de la mettre en œuvre, ce qui facilite la conception et le partage avec d'autres développeurs ou parties prenantes.

Approche automatique

Il existe deux façons de générer automatiquement le fichier de spécification OpenAPI dans InterSystems IRIS.

Méthode 1 : Utilisation de la fonction GetWebRESTApplication

Une approche consiste à utiliser la fonction GetWebRESTApplication fournie par la classe %REST.API.
Un exemple pratique d'utilisation consiste à ajouter la fonction suivante dans la classe de répartition:

ClassMethod GenerateOpenAPI() As%Status
{
    // Le nom de l'application RESTSet webApplication = "MyAPP"// Remplacez par le nom de votre application web// Récupérez la documentation OpenAPI 2.0Set sc = ##class(%REST.API).GetWebRESTApplication("", webApplication, .swagger)
<span class="hljs-keyword">If</span> <span class="hljs-built_in">$$$ISERR</span>(sc) {
    <span class="hljs-keyword">Quit</span> sc  <span class="hljs-comment">// Si une erreur s'est produite, quittez la méthode</span>
}

<span class="hljs-comment">// Renvoyez la documentation au format JSON</span>
<span class="hljs-keyword">Set</span> <span class="hljs-built_in">%response.ContentType</span> = <span class="hljs-string">"application/json"</span>
<span class="hljs-keyword">Do</span> <span class="hljs-keyword">##class</span>(OMRREST.impl).<span class="hljs-built_in">%WriteResponse</span>(swagger.<span class="hljs-built_in">%ToJSON</span>()) 

<span class="hljs-keyword">Quit</span> <span class="hljs-built_in">$$$OK</span>

}

Ajoutez en outre le chemin d'accès suivant à l'UrlMap:

  <Route Url="/openapi" Method="GET" Call="GenerateOpenAPI"/>

À ce stade, vous aurez tout ce qu'il vous faut pour générer le fichier de spécification à partir de votre classe d'envoi. Pour consulter la documentation, connectez-vous à l'URL indiquée (où MyWebapp est le nom de votre application web, tel que défini dans le portail de gestion):

<host>:<port>/MyWebapp/openapi

Le JSON ainsi généré représente la spécification OpenAPI de votre API. Après avoir exploré la deuxième méthode, nous verrons comment la visualiser et la tester dans Swagger.

Méthode 2 : Utilisation de l'API de gestion

Une autre façon de générer le fichier de spécification OpenAPI consiste à utiliser l' API de gestion InterSystems IRIS.

Pour appeler ce service, vous pouvez utiliser des outils tels que Postman, un outil de développement qui vous permet de tester, documenter et automatiser les API.
Postman fournit une interface simple et intuitive pour l'envoi de requêtes HTTP (GET, POST, PUT, DELETE, etc.), la visualisation des réponses, la gestion de l'authentification et la création de tests automatisés.

Pour formuler la requête à l'aide de Postman, procédez comme suit:

  1. Cliquez sur le bouton New  et créez une requête HTTP.
  2. Configurez la requête comme suit et envoyez-la:
    • Sélectionnez la méthode GET comme méthode HTTP.
    • Spécifiez l'URL dans le format suivant, en utilisant l' <baseURL> de votre instance:
      https://<baseURL>/api/mgmnt/v1/namespace/myapp
      Ici, namespace est le nom de l'espace de noms où vous avez créé d le service REST, et myapp et le nom de votre application.
    • Définissez la méthode d' Authorisation sur Basic Auth et fournissez le nom d'utilisateur et le mot de passe d'un utilisateur ayant un accès en lecture à l'espace de noms spécifié.

Une fois le JSON généré, il peut être visualisé et testé à l'aide d'outils tels que Swagger Editor.

{
   "info":{
      "title":"",
      "description":"",
      "version":"",
      "x-ISC_Namespace":"MyNamespace"
   },
   "basePath":"/MyWebapp",
   "paths":{
      "/loginForm":{
         "post":{
            "parameters":[
               {
                  "name":"payloadBody",
                  "in":"body",
                  "description":"Request body contents",
                  "required":false,
                  "schema":{
                     "type":"string"
                  }
               }
            ],
            "operationId":"loginForm",
            "x-ISC_ServiceMethod":"loginForm",
            "responses":{
               "default":{
                  "description":"(Unexpected Error)"
               },
               "200":{
                  "description":"(Expected Result)"
               }
            }
         }
      },
      "/refresh":{
         "post":{
            "parameters":[
               {
                  "name":"payloadBody",
                  "in":"body",
                  "description":"Request body contents",
                  "required":false,
                  "schema":{
                     "type":"string"
                  }
               }
            ],
            "operationId":"refresh",
            "x-ISC_ServiceMethod":"refresh",
            "responses":{
               "default":{
                  "description":"(Unexpected Error)"
               },
               "200":{
                  "description":"(Expected Result)"
               }
            }
         }
      },
      "/logout":{
         "post":{
            "parameters":[
               {
                  "name":"payloadBody",
                  "in":"body",
                  "description":"Request body contents",
                  "required":false,
                  "schema":{
                     "type":"string"
                  }
               }
            ],
            "operationId":"logout",
            "x-ISC_ServiceMethod":"logout",
            "responses":{
               "default":{
                  "description":"(Unexpected Error)"
               },
               "200":{
                  "description":"(Expected Result)"
               }
            }
         }
      },
      "/openapi":{
         "get":{
            "operationId":"GenerateOpenAPI",
            "x-ISC_ServiceMethod":"GenerateOpenAPI",
            "responses":{
               "default":{
                  "description":"(Unexpected Error)"
               },
               "200":{
                  "description":"(Expected Result)"
               }
            }
         }
      }
   },
   "swagger":"2.0"
}

Approche manuelle

L'approche manuelle pour générer un document OpenAPI consiste à écrire manuellement le fichier de spécification au format YAML ou JSON. Cette approche est particulièrement utile lorsque vous souhaitez contrôler entièrement la conception de l'API avant sa mise en œuvre, ou lorsque vous documentez une API déjà existante sans recourir à des outils automatisés.

Pour rédiger le fichier de spécification OpenAPI, vous pouvez vous référer à , la documentation officielle de la version 2.0 de la spécification OpenAPI, où vous trouverez des renseignements sur les champs obligatoires et sur la manière de décrire les points de terminaison, les paramètres, les réponses, etc. Ce guide détaillé vous aidera à comprendre comment structurer correctement le fichier YAML ou JSON afin de respecter les normes OpenAPI.

Un bon exemple d'utilisation de cette approche est la création d'un service REST à l'aide des méthodes décrites dans la documentation officielle d'InterSystems IRIS.
Vous trouverez une introduction au développement et à la configuration d'une application REST dans IRIS sur cette page de la documentation, qui décrit étape par étape les méthodes nécessaires pour exposer une application RESTful avec IRIS.

2
1 85
Article Iryna Mykhailova · Juil 17, 2024 4m read

Parmi les points problématiques de la maintenance des interfaces HL7 figure la nécessité d'effectuer un test de régression fiable lors du déploiement dans de nouveaux environnements et après les mises à jour. La classe %UnitTest permet de créer des tests unitaires et de les intégrer au code de l'interface. Les données de test peuvent également être enregistrées au sein de la classe de test unitaire, ce qui permet de réaliser rapidement et facilement des tests de fumée et des tests de régression.

##Ressources:

##Scénario: Une classe de test unitaire sera créée pour chaque flux entrant en fonction des exigences en matière de profilage, de routage et de mappage des données.

  • Exigences relatives aux échantillons:*

Functional Requirements

Pour tester chaque scénario, nous devons lancer un échantillon pour chaque type d'événement et confirmer les règles de routage. Il nous faut également confirmer les exigences spécifiques en matière de mappage et trouver des exemples de données pour chaque scénario.

##Production HL7

L'objectif de ce UnitTest-RuleSet est de tester un pipeline HL7 : Service métierRègles de routageTransformation.

Dans cet exemple créé pour la production illustrée ci-dessous, le flux de processus ADT passe par plusieurs sauts supplémentaires. Une classe étendant UnitTest.RuleSet.HL7 a été modifiée pour permettre de traiter des flux de processus plus complexes.

Flux de processus: FromHSROUTER.TESTAdtFromTESTAdt.ReorgSegmentProcessRouteTESTAdtTEST.ADTTransformHS.Gateway.HL7.InboundProcess

HL7 Production

##Création d'une Classe de Test Unitaire

Créez une classe TestAdtUnitTest qui étend UnitTest.RuleSet.HL7. (UnitTest.RuleSet.Example dans le référentiel UnitTest-RuleSet contient un exemple d'une telle classe.

*Remarque: Dans cet exemple, tout a été déplacé sous HS.Local dans HSCUSTOM pour faciliter les tests. *

Signature:Class HS.Local.EG.UnitTest.TestAdtUnitTest Extends HS.Local.Util.UnitTest.RuleSet.HL7

##Aperçu de la structure des classes

La classe de test unitaire est organisée de la manière suivante:

Unit Test Class Layout

##Paramètres de configuration

Ces paramètres de classe sont utilisés pour configurer les tests.

// Espace de noms où la production est située
Parameter Namespace = "EGTEST";

// Répertoire de base pour les tests unitaires

Parameter TestDirectory = "/tmp/unittest";

// nom du sous-répertoire pour les tests unitaires

Parameter TestSuite = "TEST-HL7ADT";

/// Remplacement pour un schéma différent
Parameter HL7Schema = "2.5.1:ADT_A01";

/// Remplacement par le nom du service existant en production
Parameter SourceBusinessServiceName = "FromHSROUTER.TESTAdt";

/// Remplacer par le nom du moteur de routage de processus métier existant en production
Parameter TargetConfigName = "FromTESTAdt.ReorgSegmentProcess";

/// Nom du processus de routage primaire en production
Parameter PrimaryRoutingProcessName = "RouteTESTAdt";

/// Nom du processus de routage secondaire en production
Parameter SecondaryRoutingProcessName = "TEST.ADTTransform";

Remarque: Les processus de routage primaire et secondaire sont référencés dans les différentes méthodes de test afin de tester la sortie et les résultats de deux processus de routage enchaînés.

##Création d'exemples de messages d'entrée

Pour créer une classe de test unitaire réutilisable, il faut enregistrer des échantillons anonymes pour chaque type d'événement et tout message supplémentaire nécessaire à la réalisation des scénarios de test dans la classe de test unitaire, dans des blocs XDATA au bas du fichier.

  • Exemple du bloc XDATA:*

Le nom *SourceMessageA01 * est utilisé pour référencer le bloc XDATA spécifique.

XData SourceMessageA01 { <![CDATA[ MSH|^~\&|Epic|TEST||TEST|20230911060119|RUBBLE|ADT^A01|249509431|P|2.2 EVN|A01|20230911060119||ADT_EVENT|RUBBLE^MATTHEW^BARNEY^D^^^^^TEST^^^^^UH|20230911060000|PHL^PHL^ADTEDI ZVN||LS23450^LS-23450^^^^RTL PID|1|000163387^^^MRN^MRN|000163387^^^MRN^MRN||FLINTSTONE^ANNA^WILMA||19690812|F|MURRAY^ANNA~FLINTSTONE^ANNA^R~FLINTSTONE^ANNA|B|100 BEDROCK WAY^^NORTH CHARLESTON^SC^29420-8707^US^P^^CHARLESTON|CHAR|(555)609-0969^P^PH^^^555^6090969~^NET^Internet^ANNAC1@YAHOO.COM~(555)609-0969^P^CP^^^555^6090969||ENG|M|CHR|1197112023|260-61-5801|||1|||||Non Veteran|||N ZPD||MYCH||AC|||N||N PD1|||TEST HOLLINGS CANCER CENTER^^10003|1134107873^LINK^MICHAEL^J^^^^^EPIC^^^^PNPI ROL|1|UP|GENERAL|1134107873^LINK^MICHAEL^J^^^^^EPIC^^^^PNPI|20211115 NK1|1|GABLE^BETTY|PARENT||(555)763-5651^^PH^^^555^7635651||Emergency Contact 1 NK1|2|FLINTSTONE^FRED|Spouse|100 Bedrock way^^REMBERT^SC^29128^US|(888)222-2222^^PH^^^888^2222222|(888)222-3333^^PH^^^888^2223333|Emergency Contact 2 PV1|1|O|R1OR^RTOR^07^RT^R^^^^TEST RT OR|EL|||1386757342^HALSTEAD^LUCINDA^A.^^^^^EPIC^^^^PNPI|1386757342^HALSTEAD^LUCINDA^A.^^^^^EPIC^^^^PNPI||OTO||||PHYS|||1386757342^HALSTEAD^LUCINDA^A.^^^^^EPIC^^^^PNPI|SO||BCBS|||||||||||||||||||||ADMCONF|||20230911060000 PV2||PRV||||||20230911||||HOSP ENC|||||||||N|N||||||||||N ZPV||||||||||||20230911060000 OBX|1|NM|PRIMARYCSN|1|1197112023||||||F AL1|1|DA|900525^FISH CONTAINING PRODUCTS^DAM|3|Anaphylaxis|20210823 AL1|2|DA|568^PEANUT^HIC|3|Anaphylaxis|20221209 AL1|3|DA|12753^TREE NUT^HIC|3|Anaphylaxis|20221209 AL1|4|DA|1193^TREE NUTS^DAM|3|Anaphylaxis|20130524 AL1|5|DA|1554^HYDROCODONE^HIC||Other|20210728 AL1|6|DA|3102^POLLEN EXTRACTS^HIC||Other|20201204 AL1|7|DA|11754^SHELLFISH DERIVED^HIC||Other|20210728 DG1|1|I10|Q85.02^Neurofibromatosis, type 2^I10|Neurofibromatosis, type 2||ADMISSION DIAGNOSIS (CODED) DG1|2|I10|D33.3^Benign neoplasm of cranial nerves^I10|Benign neoplasm of cranial nerves||ADMISSION DIAGNOSIS (CODED) DG1|3|I10|J38.01^Paralysis of vocal cords and larynx, unilateral^I10|Paralysis of vocal cords and larynx, unilateral||ADMISSION DIAGNOSIS (CODED) DG1|4||^NF2 (neurofibromatosis 2) [Q85.02]|NF2 (neurofibromatosis 2) [Q85.02]||ADMISSION DIAGNOSIS (TEXT) DG1|5||^Acoustic neuroma [D33.3]|Acoustic neuroma [D33.3]||ADMISSION DIAGNOSIS (TEXT) DG1|6||^Unilateral complete paralysis of vocal cord [J38.01]|Unilateral complete paralysis of vocal cord [J38.01]||ADMISSION DIAGNOSIS (TEXT) GT1|1|780223|FLINTSTONE^ANNA^WILMA^^^^L||100 BEDROCK WAY^^NORTH CHARLESTON^SC^29420-8707^US^^^CHARLESTON|(555)609-0969^P^PH^^^555^6090969~(555)763-5651^P^CP^^^555^7635651||19690812|F|P/F|SL|248-61-5801|||||^^^^^US|||Full ZG1||||1 IN1|1|BL90^BCBS/STATE EMP^PLANID||BCBS STATE|ATTN CLAIMS PROCESSING^PO BOX 100605^COLUMBIA^SC^29260-0605||(800)444-4311^^^^^800^4444311|002038404||||20140101||NPR||FLINTSTONE^THOMAS^^V|Sp|19661227|3310 DUBIN RD^^NORTH CHARLESTON^SC^29420^US|||1|||||||||||||1087807|ZCS49984141|||||||M|^^^^^US|||BOTH IN3|1|||2||20230911|20230911|RUBBLE^MATTHEW^BARNEY^D|||NOT|||||(800)999-0000^^^^^800^9990000~(888)444-5555^^^^^888^4445555 ZIN|||||||FLINTSTONE^THOMAS^^V|||||16871492 ]]> }

Exemple de code permettant d'extraire des données d'un bloc XDATA pour les utiliser dans le cadre de tests :

set xdata=##class(%Dictionary.CompiledXData).%OpenId(..%ClassName(1)_"||"_XDataName,0)

Voici un exemple de code de ** GetMessage**, une méthode d'assistance utilisée pour lire et renvoyer les données d'un bloc XDATA en fonction du nom du bloc.

ClassMethod GetMessage(XDataName As %String) As EnsLib.HL7.Message { #dim SourceMessage as EnsLib.HL7.Message set xdata=##class(%Dictionary.CompiledXData).%OpenId(..%ClassName(1)_"||"XDataName,0) quit:'$IsObject(xdata) $$$NULLOREF set lines="" while 'xdata.Data.AtEnd { set line=$ZSTRIP(xdata.Data.ReadLine(),"<w") continue:line="" continue:$Extract(line,1)="<" // ignorer les balises XML ouvrantes ou fermantes et commencer la balise CData continue:$Extract(line,1)="]" // ignorer ]]> closing CDATA set lines=lines($S($L(lines)=0:"",1:$C(..#NewLine)))_line } set SourceMessage=##class(EnsLib.HL7.Message).ImportFromString(lines,.tSC) quit:$$$ISERR(tSC) $$$NULLOREF set SourceMessage.DocType=..#HL7Schema set tSC=SourceMessage.PokeDocType(..#HL7Schema) quit SourceMessage }

##Création de méthodes de test

La classe de test unitaire contient également une méthode de test qui configure chaque test de manière programmatique, injecte le message dans la production et vérifie que le message transformé qui en résulte correspond à ce qui est attendu.

L'exemple de test contient les méthodes de test suivantes :

  • TestMessageA01
  • TestMessageA02
  • TestMessageA03
  • TestMessageA04
  • TestMessageA05
  • TestMessageA06
  • TestMessageA08
  • TestMessageA28
  • TestMessageA31
  • TestCorrectAssigningAuthorityForA01
  • TestEncoutnerNumberPresent
  • TestPD1LocationMapped

Exemple de méthode: TestMessageA01 Méthode permettant de vérifier que les messages A01 sont traités sans erreur et routés vers la transformation correcte.

Method TestMessageA01() { Set ReturnA01 = ..#SecondaryRoutingProcessName_":HS.Local.EG.ProfSvcs.Router.Base.ADT.TransformA01" #dim message as EnsLib.HL7.Message

    // Télécharger un nouveau message HL7 par UnitTest
set ..HL7Message=..GetMessage("SourceMessageA01")
quit:'$IsObject(..HL7Message) $$$ERROR(5001,"Failed to correlate Xdata for Source Message")

set routingProcess = ..#PrimaryRoutingProcessName

set message=..HL7Message.%ConstructClone(1)
do message.PokeDocType(message.DocType)
do message.SetValueAt("SYSA","MSH:3.1")
set expectSuccess=1
set expectReturn="send:"_ReturnA01
set expectReason="rule#8"
do ..SendMessageToRouter(message,"TestMessageA01",routingProcess, expectSuccess, expectReturn, expectReason)

}

Remarque: SendMessageToRouter() est une méthode mise en œuvre dans le paquet UnitTest-RuleSet.

Exemple de méthode: TestEncounterNumberPresent

La méthode ci-dessous vérifie la présence de valeurs spécifiques dans le message après la transformation.

Method TestEncounterNumberPresent()
{
	#dim message as EnsLib.HL7.Message

    // Télécharger un nouveau message HL7 par UnitTest
set ..HL7Message=..GetMessage("SourceMessageA01")
quit:'$IsObject(..HL7Message) $$$ERROR(5001,"Failed to correlate Xdata for Source Message")

// source du processus de transformation
set routingProcess = ..#SecondaryRoutingProcessName
set message=..HL7Message.%ConstructClone(1)
do message.PokeDocType(message.DocType)
do message.SetValueAt("SYSA","MSH:3.1")
// Vérifier que la sortie PV1:19 n'est pas vide
set expectSuccess=1
set expectElement="PV1:19"
set expectReturnVal="1197112023"
do ..SendMessageReturnOutput(message,"TestMessageA01", routingProcess, expectSuccess, expectElement, expectReturnVal)
 }

Remarque: SendMessageReturnOutput() est une méthode modifiée pour renvoyer le message résultatif pour évaluation.

##Comment exécuter le UnitTest

Les mises en œuvre de la classe %UnitTest dépend de la globale ^UnitTestRoot pour l'emplacement des dossiers de travail des tests unitaires.

Il y a deux paramètres utilisés pour définir les dossiers:

 // Répertoire de base pour les tests unitaires
 Parameter TestDirectory = "/tmp/unittest";

 // nom du sous-répertoire pour les tests unitaires
 Parameter TestSuite = "TEST-HL7ADT";

Dans ce cas, la classe s'attend à ce que le dossier : /tmp/unittest/TEST-HL7ADT soit présent dans l'environnement où la classe de test unitaire est exécutée.

En outre, la mise en œuvre personnalisée définit la globale ^UnitTestRoot et passe à l'espace de noms spécifique dans le paramètre d'espace de noms Namespace.

Pour le lancement depuis le terminal:

HSCUSTOM> do ##class(HS.Local.EG.UnitTest.TestAdtUnitTest).Debug()

Les résultats du lancement seront envoyés à la console. Si l'un des tests échoue, tout le test est considéré comme ayant échoué. Outre le terminal, on peut également consulter les résultats à partir du portail de gestion. Pour ouvrir l'URL, utilisez le lien figurant dans le résultat.

##Extrait du résultat de la Console

TestMessageA31 passed TestPD1LocationMapped() begins ... 14:50:20.104:...t.TestAdtUnitTest: TestPD1Location Sent LogMessage:SessionId was 130 LogMessage:Source Config Name name is :TEST.ADTTransform LogMessage:Message Body Id was 94 LogMessage:Expect Success is 0 LogMessage:Testing for value PV1:39 LogMessage:Found value AssertNotEquals:Expect No Match:TestPD1Location:ReturnValue= (failed) <<==== FAILED TEST-HL7ADT:HS.Local.EG.UnitTest.TestAdtUnitTest:TestPD1LocationMapped LogMessage:Duration of execution: .033106 sec. TestPD1LocationMapped failed HS.Local.EG.UnitTest.TestAdtUnitTest failed Skipping deleting classes TEST-HL7ADT failed

Use the following URL to view the result: http://192.168.1.229:52773/csp/sys/%25UnitTest.Portal.Indices.cls?Index=3&$NAMESPACE=EGTEST Some tests FAILED in suites: TEST-HL7ADT

##Affichage des résultats dans le portail de gestion

Utilisez l'URL affichée sur le terminal et copiez-la dans un navigateur pour voir les résultats. En cliquant sur le nom du test, vous obtiendrez des détails supplémentaires.

Unit Test in Management Portal

En cliquant sur le lien de chaque test, vous obtiendrez plus d'informations sur le test :

UnitTest Results

##Conclusion La création de classes de tests unitaires pour chaque interface HL7 et leur intégration dans le code de l'interface permettent de documenter le processus de test et les échantillons de données, ainsi que de tester rapidement la régression de toute mise à jour ou modification des données ou de leur mise en œuvre.

Lors du déploiement, la classe de test unitaire sert de test de fumée autonome pour confirmer que l'interface est complète et fonctionnelle.

##Considérations supplémentaires

  • Le cadre UnitTest_RuleSet peut être adapté aux tests unitaires du CCDA. Les tests de routage sont relativement semblables à l'exemple HL7. Pour répondre aux exigences de mappage, il faut mettre en œuvre la classe de test unitaire pour gérer XSLT et XPaths.

  • Les responsables de l'assurance qualité peuvent recueillir des exigences et des échantillons de données pour configurer la classe de test unitaire avant le début de la mise en œuvre.

  • Les tests unitaires pour toutes les interfaces peuvent être regroupés dans le gestionnaire de tests unitaires (Unit Test Manager), de sorte que l'ensemble des tests peut être exécuté en une seule fois pour valider la configuration et le code existants.

0
0 50
Article Iryna Mykhailova · Juin 27, 2024 6m read

Introduction

Dans les prochaines semaines, mes collègues prévoient de commencer à utiliser VSCode pour coder avec les produits d'InterSystems. Parmi les nombreux avantages, je soulignerais la possibilité de se connecter facilement à d'autres technologies, telles que GitHub. En outre, VSCode propose également une vaste boutique d'extensions, où vous pouvez trouver de nombreux add-ons gratuits qui rendent le codage plus rapide et plus efficace. Enfin, pour conquérir le cœur de tous les développeurs, c'est open source.

Cela étant dit, commençons le tutoriel. N'hésitez pas à sauter certaines étapes si vous vous sentez à l'aise pour les réaliser sans aide.

Étape 1 - Téléchargement et installation de VSCode

Recherchez "VSCode download" ou cliquez sur this linkce lien pour télécharger à partir de la page officielle. Sélectionnez l'installation correcte pour votre ordinateur et exécutez le fichier téléchargé.

Une fois l'exécutable lancé, il vous sera demandé d'accepter la licence, de sélectionner quelques préférences (qui sont très personnelles et dont je ne parlerai pas dans ce texte), et de procéder à l'installation. 
 

Étape 2 - Installation des extensions InterSystems

Ouvrez votre VSCode dans l'onglet Extensions et recherchez le paquet ObjectScript Extension Pack dans la boutique.

Installez le paquet complet.
 

Étape 3 - Configuration de votre VSCode pour vos instances

Une fois les extensions installées, vous devriez avoir un onglet InterSystems. Vous pouvez le sélectionner et cliquer sur "+" dans la section des serveurs, comme indiqué ci-dessous, et vous serez invité à fournir des informations sur la connexion, telles que l'hôte, le port, le nom d'utilisateur et le mot de passe.

Sinon, vous pouvez aller dans votre fichier VSCode general settings.json, que vous pouvez trouver en cliquant sur l'engrenage de gestion   sur le côté gauche en bas de l'écran, en sélectionnant les configurations, et en cliquant sur "Ouvrir les paramètres (JSON)" ("Open Settings (JSON)")    sur le côté droit en haut de l'écran.

Là, vous pouvez coller le fragment JSON suivant, en le modifiant pour qu'il pointe vers votre instance.

"intersystems.servers": {
        "[YOUR SERVER NAME]": {
            "webServer": {
                "scheme": "http",
                "host": "127.0.0.1",
                "port": 53472
            },
            "username": "_system"
        }

 

Étape 4.1 - Connexion à un serveur et à un espace de noms pour le développement local

Toujours dans l'onglet InterSystems, sélectionnez la section Explorer et cliquez sur le bouton "Choisir le serveur et l'espace de noms" (Choose server and namespace).

Vous devriez être invité à choisir parmi les serveurs ajoutés lors de la dernière étape, votre nom d'utilisateur et votre mot de passe, ainsi qu'un espace de noms.

Ensuite, toujours dans le même onglet, vous pouvez utiliser la section d'exploration (Explore) ou la section des projets (Projects) pour choisir les classes et/ou les projets que vous souhaitez exporter. Si vous choisissez ce type de développement, vous pouvez ouvrir les fichiers exportés dans un espace de travail VSCode et vous connecter à GitHub, par exemple.

Étape 4.2 - Connection à un serveur et à un espace de noms pour développer sur le serveur (ma préférence)

Ouvrez l'onglet Intersystèmes dans la section Serveurs et choisissez un serveur.

Vous pouvez choisir un projet et cliquer sur le crayon pour l'ouvrir en mode édition sur votre espace de travail ou ou sur l'œil pour l'ouvrir en mode lecture.

De même, vous pouvez choisir entre les mêmes options directement sur l'espace de noms pour ouvrir tous ses fichiers dans l'espace de travail (ma préférence)

Dans les deux cas, il se peut que l'on vous demande à nouveau un nom d'utilisateur et un mot de passe. 
 

Étape 5 - Codage

Dans l'onglet de l'explorateur, après la dernière étape, votre espace de travail ressemble à l'image ci-dessous.

Vous pouvez créer un fichier et de nouveaux dossiers en cliquant avec le bouton droit de votre souris sur un répertoire, en sélectionnant "nouveau fichier" ("new file") et en le nommant avec le modèle FOLDERNAME.FILENAME.cls. En d'autres termes, vous devez nommer les dossiers en séparant les noms par des points. Le nom précédant le dernier point sera le nom du fichier, et le nom suivant le dernier point sera l'extension des fichiers COS, cls.
Par exemple, vous pouvez nommer votre fichier comme dans l'image ci-dessous, "folderone.foldertwo.filename.cls", dans le dossier User, et cliquer sur "Enter".

Ainsi, le répertoire et le fichier suivants devraient être créés automatiquement.

Maintenant, vous êtes prêt à coder comme vous le feriez en Studio.

 

Quelques conseils supplémentaires

- Vous pouvez appuyer sur Ctrl+Shift+V pour ouvrir les fichiers .int.

- Attention: contrairement à Studio, Ctrl + S dans VSCode compilera le fichier en plus de l'enregistrer.

- Maintenant, je vais vous montrer la meilleure fonctionnalité que j'ai rencontrée jusqu'à présent en codant avec VSCode. C'est de l'or en barre. Imaginez que vous ayez une instance de développeur pour les premières phases d'un projet, une autre instance pour les tests avec vos clients, et peut-être même encore une autre pour la production. Il peut être fastidieux de migrer les fichiers et les modifications entre les instances de Studio. Cependant, si vous utilisez VSCode, c'est assez simple.

Dans l'onglet Explorateur (Explorer), ouvrez la source et le fichier cible. Par exemple, si j'ai un fichier définissant des  données persistantes, et que j'ai ajouté des champs sur mon serveur de développement, et que je souhaite les transférer sur mon serveur de production, j'ouvrirai le fichier de développement et le fichier de production pour les mêmes données persistantes (une discussion sur l'ouverture de plusieurs serveurs ou espaces de noms est abordée dans la rubrique suivante).

Une fois que les deux sont ouverts, ils apparaissent dans la section "Éditeurs ouverts" ("Open Editors").

Sélectionnez le fichier source avec le bouton droit de votre souris et cliquez sur "Sélectionner pour comparer" ("Select to compare"). Cliquez avec le bouton droit sur le fichier cible et choisissez "Comparer avec sélectionné" ("Compare with selected").
BOUM! Vous aurez alors ce magnifique fichier de comparaison ouvert, comme illustré ci-dessous.

La barre située à droite de l'écran indique les différences entre les fichiers, et vous pouvez l'utiliser pour naviguer simultanément entre eux. Les couleurs rouge et verte signifient que quelque chose diffère dans les fichiers. Le rouge signifie que le fichier source contient du texte qui ne figure pas dans le fichier cible. Le vert signifie que le fichier cible contient du texte qui ne figure pas dans le fichier source. 

Cliquez sur les flèches du milieu pour transférer les modifications de la source vers la cible.

En outre, cliquez sur la flèche biface dans le coin supérieur droit de l'écran pour changer les côtés des fichiers : la source sera la cible et vice versa.

En appuyant sur Ctrl+S lorsque l'éditeur est ouvert, les deux fichiers sont enregistrés et compilés.

- Vous pouvez ouvrir plusieurs instances et espaces de noms à la fois dans votre espace de travail, tant que votre ordinateur peut le gérer. Cependant, pour que vous puissiez vous faire une idée, ces dernières semaines, j'ai travaillé avec deux espaces de noms lourds provenant de différentes instances, Studio, Microsoft Teams (qui est scandaleusement lourd), et deux autres applications pour se connecter à la base de données et aux API, le tout en même temps, avec un ordinateur ayant la configuration suivante: 8 Go de RAM et CPU de 2,10 GHz. La seule chose qui a parfois été un peu lente, c'est Studio.

Poursuite de la discussion

J'aimerais parler de débogage avec VSCode. Je n'ai pas encore trouvé quelqu'un qui l'apprécie plus que les outils de débogage de Studio. Personnellement moi, je ne suis pas très habitué à utiliser les outils de débogage VSCode avec les produits InterSystems, et même si Studio est beaucoup plus lourd, je préfère le laisser ouvert lorsque j'ai besoin de déboguer. Comment combinez-vous ces technologies? Quels sont les outils que vous préférez?

0
0 83
Article Sylvain Guilbaud · Juin 7, 2024 10m read

Avant-propos

Les versions 2022.2 et ultérieures d'InterSystems IRIS offrent la possibilité de s'authentifier auprès d'une API REST à l'aide de jetons web (JWT) JSON. Cette fonctionnalité renforce la sécurité en limitant le lieu et la fréquence de transfert des mots de passe sur le réseau et en fixant un délai d'expiration pour l'accès.

L'objectif de cet article est de servir de tutoriel sur la façon d'implémenter une API REST fictive en utilisant InterSystems IRIS et de verrouiller l'accès à cette API par le biais de JWT.

REMARQUE Je ne suis PAS développeur. Je ne fais aucune déclaration quant à l'efficacité, l'évolutivité ou la qualité des échantillons de code que j'utilise dans cet article. Les exemples ci-dessous sont donnés UNIQUEMENT à des fins éducatives. Ils ne sont PAS destinés à un code de production.

Prologue

Cette réserve étant faite, explorons les concepts que nous allons décortiquer ici.

Qu'est-ce que REST?

Le terme REST est l'acronyme de REpresentational State Transfer. Il s'agit d'un style d'architecture pour la conception d'applications connectées et pour l'accès à des fonctions publiées par ces applications.

Qu'est-ce qu'un JWT?

Un jeton web JSON (JWT) est un moyen compact et sûr au niveau de l'URL qui permet de représenter les demandes transférées entre deux parties et qui peuvent être signées numériquement, cryptées ou les deux à la fois. Si vous souhaitez en savoir plus sur les JWT et les autres classes web JSON prises en charge par InterSystems IRIS, lisez cet article.

Se salir les mains

Selon les spécifications

Pour consommer une API REST, il faut d'abord disposer d'une API REST. J'ai fourni ici un exemple de spécification OpenAPI 2.0 qui est adapté au jeu de rôle sur table (TTRPG). Je l'utiliserai tout au long des exemples présentés ici. Il existe de nombreux exemples de rédaction en ligne, alors n'hésitez pas à vous y plonger, mais la spécification n'est qu'un plan directeur. Il ne fait rien d'autre que de nous informer sur l'utilisation de l'API.

Génération d'API REST

InterSystems IRIS fournit une manière très soignée de générer des souches de code pour l'API REST. Cette documentation fournit une méthode complète de génération de souches de code. N'hésitez pas à utiliser la spécification OpenAPI 2.0 que j'ai fournie dans la section précédente.

Mise en œuvre

C'est là que nous allons creuser. La section de génération aura créé trois fichiers .cls pour vous :

  1. impl.cls
  2. disp.cls
  3. spec.cls

Nous allons passer le plus de temps possible dans impl.cls, peut-être toucher à disp.cls pour le débogage, et laisser spec.cls tranquille.

Dans impl.cls se trouvent les souches de code pour les méthodes que disp.cls appellera lorsqu'il recevra une requête API. La spécification OpenAPI a défini ces signatures. Elle peut dire ce que vous voulez qu'elle fasse, mais c'est vous qui devez la mettre en œuvre. Alors faisons ça!

Création

L'une des façons dont nous utilisons une base de données est d'y ajouter des objets. Ces objets servent de base à nos autres fonctions. Sans objets existants, nous n'aurons rien à voir, nous allons donc commencer par notre modèle d'objet : un caractère Character !

Un Character aura nécessairement un nom et spécifiera éventuellement sa classe, sa race et son niveau. Voici un exemple d'implémentation de la classe TTRPG.Character.

Class TTRPG.Character Extends %Persistent
{

Property Name As %String [ Required ];

Property Race As %String;

Property Class As %String;

Property Level As %String;

Index IndexName On Name [ IdKey ];

ClassMethod GetCharByName(name As %String) As TTRPG.Character
{
set character = ##class(TTRPG.Character).%OpenId(name)

Quit character
}
}

Puisque nous voulons stocker les objets Character dans la base de données, il nous faut hériter de la classe %Persistent. Nous voulons être capables de rechercher nos charactères par leur nom plutôt que de leur assigner une clé d'identification arbitraire, donc nous définissons l'attribut [ IdKey ] sur l'index pour la propriété Character.Name. Cela garantit également l'unicité du nom du caractère.

Une fois notre modèle d'objet fondamental défini, nous pouvons analyser la mise en œuvre de l'API REST. La première méthode que nous allons explorer est la méthode PostCharacter.

En résumé, cette partie consomme une requête HTTP POST vers le point de terminaison /characters avec les propriétés de caractères que nous avons définies dans le corps de la requête. Il devrait prendre les arguments fournis et créer un objet TTRPG.Character à partir de ceux-ci, le sauvegarder dans la base de données, et nous faire savoir s'il a réussi ou non.

ClassMethod PostCharacter(name As %String, class As %String, race As %String, level As %String) As %DynamicObject
{
set results = {} // create the return %DynamicObject

//créer l'objet caractère
set char = ##class(TTRPG.Character).%New()

set char.Name = name
set char.Class = class
set char.Race = race
set char.Level = level
set st = char.%Save()

if st {
set charInfo = {}
set charInfo.Name = char.Name
set charInfo.Class = char.Class
set charInfo.Race = char.Race
set charInfo.Level = char.Level
set results.Character = charInfo
Set results.Status = "success"
}
else {
Set results.Status = "error"
Set results.Message = "Unable to create the character"
}
Quit results
}

Désormais, nous pouvons créer des caractères, mais comment récupérer celui que nous venons de créer ? Selon la spécification OpenAPI, le point de terminaison /characters/{charName} nous permet de récupérer un caractère par son nom. Nous récupérons l'instance de caractère, si elle existe. S'il n'existe pas, nous renvoyons une erreur indiquant à l'utilisateur qu'un caractère avec le nom fourni n'existe pas. Ceci est mis en œuvre dans la méthode GetCharacterByName.

ClassMethod GetCharacterByName(charName As %String) As %DynamicObject
{
// Créer un nouvel objet dynamique pour stocker les résultats
Définir les résultats = {}

set char = ##class(TTRPG.Character).GetCharByName(charName)

if char {
set charInfo = {}
set charInfo.Name = char.Name
set charInfo.Class = char.Class
set charInfo.Race = char.Race
set charInfo.Level = char.Level
set results.Character = charInfo
Set results.Status = "success"
}
// Si aucun caractère n'a été trouvé, un message d'erreur est affiché dans l'objet de résultats.
else {
Set results.Status = "error"
Set results.Message = "No characters found"
}

// Renvoyer l'objet de résultats
Quit results
}

Mais c'est juste votre caractère. Qu'en est-il de tous les autres caractères créés par d'autres personnes ? Nous pouvons visualiser ces caractères en utilisant la méthode GetCharacterList. Il consomme une requête HTTP GET vers le point de terminaison /characters pour compiler et renvoyer une liste de tous les caractères de la base de données.

ClassMethod GetCharacterList() As %DynamicObject
{
// Créer un nouvel objet dynamique pour stocker les résultats
Définir les résultats = {}
set query = "SELECT Name, Class, Race, ""Level"" FROM TTRPG.""Character"""
set tStatement = ##class(%SQL.Statement).%New()
set qstatus = tStatement.%Prepare(query)
if qstatus '= 1 { Do ##class(TTRPG.impl).%WriteResponse("Error: " _ $SYSTEM.Status.DisplayError(qstatus)) }
set rset = tStatement.%Execute()
Set characterList = []
while rset.%Next(){
Set characterInfo = {}
Set characterInfo.Name = rset.Name
set characterInfo.Race = rset.Race
Set characterInfo.Class = rset.Class
Set characterInfo.Level = rset.Level

Do characterList.%Push(characterInfo)

}
if (rset.%SQLCODE < 0) {write "%Next failed:", !, "SQLCODE ", rset.%SQLCODE, ": ", rset.%Message quit}

set totalCount = rset.%ROWCOUNT

// Définit les propriétés status, totalCount et characterList dans l'objet de résultats
Set results.Status = "success"
Set results.TotalCount = totalCount
Set results.CharacterList = characterList


// Renvoyer l'objet de résultats
Quit results
}

C'est notre API! La spécification actuelle ne fournit pas de moyen de mettre à jour ou de supprimer des caractères de la base de données, et cela reste un exercice pour le lecteur!

Configuration IRIS

Maintenant que notre API REST est implémentée, comment pouvons-nous la faire communiquer avec IRIS ? Dans le portail de gestion, si vous allez sur la page Administration du système > Sécurité > Applications > Applications Web, vous pouvez créer une nouvelle application Web. Le nom de l'application est le point de terminaison que vous utiliserez lors de vos requêtes. Par exemple, si vous l'avez nommée /api/TTRPG/, les requêtes pour l'API iront à http://localhost:52773/api/TTRPG/RPG/{endpoint}. Pour une installation locale de sécurité normale d'IRIS, cela ressemble à http://localhost:52773/api/TTRPG/{endpoint}. Donnez-lui une belle description, définissez l'espace de noms souhaité et cliquez sur le bouton radio pour REST. Pour activer l'authentification JWT, cochez la case "Use JWT Authentication". Le délai d'expiration du jeton d'accès JWT détermine la fréquence à laquelle un utilisateur devra recevoir un nouveau JWT. Si vous prévoyez de tester l'API pendant une période prolongée, je vous recommande de fixer cette valeur à une heure (3 600 secondes) et le délai d'expiration du jeton JWT (JWT Refresh Token Timeout) (la période pendant laquelle vous pouvez renouveler votre jeton avant qu'il n'expire définitivement) à 900 secondes.

web app config

Maintenant que l'application est configurée, nous devons configurer IRIS lui-même pour permettre l'authentification JWT. Vous pouvez configurer cette option dans Administration système > Sécurité > Sécurité du système > Authentification/Options de session Web. Le champ de l'émetteur du JWT et l'algorithme de signature à utiliser pour signer et valider les JWT se trouvent en bas de la page. Le champ émetteur apparaît dans la section de demande d'indemnisation du JWT et a pour but d'indiquer qui vous a donné ce jeton. Vous pourriez le définir sur "InterSystems".

JWT authentication config

Temps de test

Tout est configuré et mis en œuvre, alors lançons-nous ! Chargez votre outil favori de création de requêtes API (j'utiliserai une extension Firefox appelée RESTer dans les exemples) et nous allons construire des requêtes API REST.

Tout d'abord, essayons de répertorier tous les caractères qui existent.

list no token

Nous avons reçu une erreur "HTTP 401 Unauthorized". C'est parce que nous ne sommes pas connectés. Vous vous dites peut-être, Elliott, nous n'avons pas implémenté de fonctionnalité de connexion à cette API REST. Ce n'est pas grave, car InterSystems IRIS s'en charge pour nous lorsque nous utilisons l'authentification JWT. Il fournit quatre points de terminaison que nous pouvons utiliser pour gérer notre session. Il s'agit de /login, /logout /revoke et /refresh. Ils peuvent être personnalisés dans le fichier disp.cls comme dans l'exemple ci-dessous :

Parameter TokenLoginEndpoint = "mylogin";
Parameter TokenLogoutEndpoint = "mylogout";
Parameter TokenRevokeEndpoint = "myrevoke";
Parameter TokenRefreshEndpoint = "myrefresh";

Accédons maintenant au point de terminaison /login.

logging in

Le corps de cette demande n'est pas affiché pour des raisons de sécurité, mais il reprend la structure JSON :

{"user":"{YOURUSER}", "password":"{YOURPASSWORD}"}

En échange de notre mot de passe, nous recevons un JWT! C'est la valeur de "access_token". Nous allons copier ceci et l'utiliser dans nos demandes à l'avenir afin de ne pas avoir à transmettre notre mot de passe tout le temps.

Maintenant que nous avons un JWT pour l'authentification, essayons de créer un caractère!

Nous formatons notre demande comme ci-dessous:

character creation

Utilisation du jeton "bearer token" en tant qu'en-tête au format "Authorization: Bearer {JWTValue}". Dans une requête curl, vous pouvez écrire ceci avec -H "Authorization: Bearer {JWTValue}"

Créons un autre caractère pour le plaisir, en utilisant les valeurs de votre choix.

Essayons maintenant de répertorier tous les caractères qui existent dans la base de données.

listing characters

Nous récupérons nos deux caractères que nous avons créés! Mais qu'en est-il si nous voulons simplement accéder à l'un d'entre eux ? Eh bien, nous avons implémenté cela avec le point de terminaison /characters/{charName}. Nous pouvons formater cette requête comme ceci:

retrieving specific character

C'est notre API REST qui est à l'œuvre ! Lorsque vous avez terminé votre session, vous pouvez vous déconnecter au point de terminaison /logout en utilisant votre JWT. Ceci révoquera le JWT et le mettra sur une liste noire afin que vous ne puissiez plus l'utiliser.

Conclusion

Les versions 2022.2+ d'InterSystems IRIS offrent la possibilité de s'authentifier auprès d'une API REST à l'aide de jetons web (JWT) JSON. Cette fonctionnalité améliore la sécurité en limitant l'utilisation des mots de passe et en définissant une date d'expiration pour l'accès à l'API.

J'espère que cette présentation sur la génération d'une API REST et sa sécurisation avec des JWT via IRIS vous a été utile. Faites-moi savoir si c'était le cas! J'apprécie tout commentaire.

0
1 73
Article Iryna Mykhailova · Juin 5, 2024 3m read

Le stockage en colonnes est l'une des offres les plus récentes proposées par InterSystems IRIS.Contrairement au stockage traditionnel basé sur les lignes, il optimise le traitement des requêtes en stockant les données dans des colonnes plutôt que dans des lignes, permettant ainsi un accès et une récupération plus rapides des informations pertinentes.

Quelques articles ont été rédigés sur les moments il doit être utilisé pour donner le plus grand coup de pouce à un système et sur la façon de créer des tables comme celle-ci à l'aide de SQL.

CREATETABLEtable (column1 type1, column2 type2, column3 type3) WITH STORAGETYPE = COLUMNAR  -- ex 1CREATETABLEtable (column1 type1, column2 type2, column3 type3 WITH STORAGETYPE = COLUMNAR)  -- ex 2

et même les tests de performances.

Comme nous le savons tous, InterSystems IRIS est un SGBD multimodèle et il donne un accès transparent aux mêmes données en utilisant un accès relationnel et objet. Le premier est donc couvert dans d’autres articles, mais qu’en est-il du dernier?

0
0 59
Article Iryna Mykhailova · Avr 15, 2024 7m read

Dans la partie II, vous apprendrez à exécuter n'importe quel fichier de rapport Jasper (fichier jrxml) conçu sur Jasper Studio à partir d'InterSystems IRIS. Nous allons créer une API REST pour renvoyer un rapport traité au format PDF.

Le fichier jrxml

Dans la partie I, nous avons conçu le rapport suivant :

1. Tout d'abord, renommez le rapport de Blank_A4.jrxml en sample.jrxml (onglet Explorateur de projet > Faites un clic droit sur le fichier > Renommer):

Le fichier renommé s'affiche :

2. Faites un clic droit sur le fichier sample.jrxml > Propriétés et visualisez l'emplacement du fichier :

3. Copiez le fichier de cet emplacement vers l'instance docker (instance docker créée dans la Partie I) dans le dossier /home/irisowner/dev:

docker cp C:\Users\yurim\JaspersoftWorkspace\MyReports\sample.jrxml jirisreport-api-sample-iris-1:/home/irisowner/dev

Installez JIRISReport pour être en mesure d'exécuter Jasper à partir d'IRIS

1. Ouvrez le code source sur VSCode (installez ObjectScript et les extensions InterSystems si vous ne les avez pas encore) et sélectionnez en bas docker:iris52773[USER] pour ouvrir les options :

2. Sélectionnez l'option Ouvrir un terminal dans Docker :

3. Le terminal s'affiche :

4. Tapez zpm pour lancer l'interpréteur de commandes zpm :

5. Tapez, exécutez et attendez l'installation (cela prend un certain temps) :

zpm:USER>install jirisreport -verbose

6. Découvrez les résultats de l'installation :




Les informations d'identification du rapport

Le JIRISReport se connecte à la base de données en utilisant l'utilisateur et le mot de passe configurés dans l'interopérabilité > informations d'identification. Pour définir les informations d'identification, procédez comme suit :

1. Ouvrez le portail de gestion (http://localhost:52773/csp/sys/UtilHome.csp?$NAMESPACE=USER):

2. Accédez à l'Interopérabilité > Configurez > Les informations d'identification:

3. Créez les informations d'identification de ReportCreds :

  • Identifiant : ReportCreds
  • Nom d'utilidateur : _SYSTEM
  • Mot de passe : SYS

L' API REST :

1. Accédez à src\dc\Sample\PersonREST.cls, modifiez le fichier pour inclure une méthode REST sur les routes :

<!-- All persons Report -->
<Route Url="/report" Method="GET" Call="GetReport" Cors="true"/>

2. Mise en œuvre de la méthode :

/// Get all persons reportClassMethod GetReport() As%Status
{
    Set Parameters = {}
<span class="hljs-keyword">Set</span> result = <span class="hljs-keyword">##class</span>(dc.jirisreport.JIRISReport).GenerateReportAsFile(
    <span class="hljs-string">"jdbc:IRIS://localhost:1972/USER"</span>, 
    <span class="hljs-string">"/home/irisowner/dev/sample.jrxml"</span>,
    <span class="hljs-string">"/tmp/sample.pdf"</span>,
    Parameters 
)
    
<span class="hljs-keyword">Set</span> <span class="hljs-built_in">%response.ContentType</span> = <span class="hljs-string">"application/pdf"</span>
<span class="hljs-keyword">Do</span> <span class="hljs-built_in">%response.SetHeader</span>(<span class="hljs-string">"Content-Disposition"</span>,<span class="hljs-string">"attachment;filename=""sample.pdf"""</span>)
<span class="hljs-keyword">Set</span> <span class="hljs-built_in">%response.NoCharSetConvert</span>=<span class="hljs-number">1</span>
<span class="hljs-keyword">Set</span> <span class="hljs-built_in">%response.Headers</span>(<span class="hljs-string">"Access-Control-Allow-Origin"</span>)=<span class="hljs-string">"*"</span>
<span class="hljs-keyword">Set</span> stream=<span class="hljs-keyword">##class</span>(<span class="hljs-built_in">%Stream.FileBinary</span>).<span class="hljs-built_in">%New</span>()
<span class="hljs-keyword">Set</span> sc=stream.LinkToFile(<span class="hljs-string">"/tmp/sample.pdf"</span>)
<span class="hljs-keyword">Do</span> stream.OutputToDevice() 

<span class="hljs-keyword">Set</span> tSC=<span class="hljs-built_in">$$$OK</span>

}

  • La classe dc.jirisreport.JIRISReport est une classe utilitaire pour générer des rapports à l'aide de la bibliothèque JasperReports.
  • La méthode GenerateReportAsFile récupère l'URL JDBC, le chemin d'accès au fichier de rapport et le chemin de sortie PDF et génère le rapport sur le chemin de sortie.

3. Enregistrez le fichier PersonREST.cls pour le compiler sur le serveur (VSCode doit être connecté pour envoyer la nouvelle version au serveur). Découvrez la version finale du fichier :

Class dc.Sample.PersonREST Extends Sample.REST.Base
{

Parameter Version = "1.0.6"; XData UrlMap [ XMLNamespace = "http://www.intersystems.com/urlmap" ] { <Routes> <!-- All persons Report --> <Route Url="/report" Method="GET" Call="GetReport" Cors="true"/> <!-- Server Info --> <Route Url="/" Method="GET" Call="GetInfo" Cors="true"/> <!-- Get all records of Person class --> <Route Url="/persons/all" Method="GET" Call="GetAllPersons"/> <!-- Swagger specs --> <Route Url="/_spec" Method="GET" Call="SwaggerSpec" /> <!-- GET method to return JSON for a given person id--> <Route Url="/persons/:id" Method="GET" Call="GetPerson"/> <!-- Update a person with id--> <Route Url="/persons/:id" Method="PUT" Call="UpdatePerson"/> <!-- Delete a person with id--> <Route Url="/persons/:id" Method="DELETE" Call="DeletePerson"/> <!-- Create a person--> <Route Url="/persons/" Method="POST" Call="CreatePerson"/> <!-- Create random persons--> <Route Url="/persons/gen/:amount" Method="POST" Call="CreateRandomPersons"/>

</Routes> }

/// Get all persons reportClassMethod GetReport() As%Status { Set Parameters = {}

<span class="hljs-keyword">Set</span> result = <span class="hljs-keyword">##class</span>(dc.jirisreport.JIRISReport).GenerateReportAsFile(
    <span class="hljs-string">"jdbc:IRIS://localhost:1972/USER"</span>, 
    <span class="hljs-string">"/home/irisowner/dev/sample.jrxml"</span>,
    <span class="hljs-string">"/tmp/sample.pdf"</span>,
    Parameters 
) 
    
<span class="hljs-keyword">Set</span> <span class="hljs-built_in">%response.ContentType</span> = <span class="hljs-string">"application/pdf"</span>
<span class="hljs-keyword">Do</span> <span class="hljs-built_in">%response.SetHeader</span>(<span class="hljs-string">"Content-Disposition"</span>,<span class="hljs-string">"attachment;filename=""sample.pdf"""</span>)
<span class="hljs-keyword">Set</span> <span class="hljs-built_in">%response.NoCharSetConvert</span>=<span class="hljs-number">1</span>
<span class="hljs-keyword">Set</span> <span class="hljs-built_in">%response.Headers</span>(<span class="hljs-string">"Access-Control-Allow-Origin"</span>)=<span class="hljs-string">"*"</span>
<span class="hljs-keyword">Set</span> stream=<span class="hljs-keyword">##class</span>(<span class="hljs-built_in">%Stream.FileBinary</span>).<span class="hljs-built_in">%New</span>()
<span class="hljs-keyword">Set</span> sc=stream.LinkToFile(<span class="hljs-string">"/tmp/sample.pdf"</span>)
<span class="hljs-keyword">Do</span> stream.OutputToDevice() 

<span class="hljs-keyword">Set</span> tSC=<span class="hljs-built_in">$$$OK</span>

}

/// PersonsREST general informationClassMethod GetInfo() As%Status { SET version = ..#Version SET info = { "version": (version) } RETURN ..%ProcessResult($$$OK, info) }

/// Retreive all the records of dc.Sample.PersonClassMethod GetAllPersons() As%Status {

<span class="hljs-keyword">#dim</span> tSC <span class="hljs-keyword">As</span> <span class="hljs-built_in">%Status</span> = <span class="hljs-built_in">$$$OK</span>
<span class="hljs-keyword">Set</span> rset = <span class="hljs-keyword">##class</span>(dc.Sample.Person).ExtentFunc()

<span class="hljs-keyword">Set</span> <span class="hljs-built_in">%response.ContentType</span> = ..#CONTENTTYPEJSON
<span class="hljs-keyword">Write</span> <span class="hljs-string">"["</span>
<span class="hljs-keyword">if</span> rset.<span class="hljs-built_in">%Next</span>() {
    <span class="hljs-keyword">Set</span> person = <span class="hljs-keyword">##class</span>(dc.Sample.Person).<span class="hljs-built_in">%OpenId</span>(rset.ID)    
    <span class="hljs-keyword">Do</span> person.<span class="hljs-built_in">%JSONExport</span>()
}
<span class="hljs-keyword">While</span> rset.<span class="hljs-built_in">%Next</span>() {   
    <span class="hljs-keyword">Write</span> <span class="hljs-string">","</span>
    <span class="hljs-keyword">Set</span> person = <span class="hljs-keyword">##class</span>(dc.Sample.Person).<span class="hljs-built_in">%OpenId</span>(rset.ID)    
    <span class="hljs-keyword">Do</span> person.<span class="hljs-built_in">%JSONExport</span>()
}
<span class="hljs-keyword">Write</span> <span class="hljs-string">"]"</span>
<span class="hljs-keyword">Quit</span> tSC

}

/// Return one record fo dc.Sample.PersonClassMethod GetPerson(id As%Integer) As%Status { #dim tSC As%Status = $$$OK#dim e As%Exception.AbstractException #; Set the response header to plain textSet%response.ContentType = ..#CONTENTTYPEJSON

<span class="hljs-keyword">Set</span> person = <span class="hljs-keyword">##class</span>(dc.Sample.Person).<span class="hljs-built_in">%OpenId</span>(id)

<span class="hljs-keyword">If</span> '<span class="hljs-built_in">$IsObject</span>(person) <span class="hljs-keyword">Quit</span> <span class="hljs-built_in">..Http</span>404()

<span class="hljs-keyword">Do</span> person.<span class="hljs-built_in">%JSONExport</span>()

<span class="hljs-keyword">Quit</span> tSC

}

/// Creates a new dc.Sample.Person recordClassMethod CreatePerson() As%Status { #dim tSC As%Status = $$$OK#dim e As%Exception.AbstractExceptionSet person = ##class(dc.Sample.Person).%New() Set data=%request.Content$$$TOE(tSC,person.%JSONImport(data)) $$$TOE(tSC,person.%Save())

<span class="hljs-keyword">Set</span> <span class="hljs-built_in">%response.Status</span> = <span class="hljs-number">204</span>
<span class="hljs-keyword">Set</span> <span class="hljs-built_in">%response.ContentType</span> = ..#CONTENTTYPEJSON
<span class="hljs-comment">//d data.%ToJSON()</span>
<span class="hljs-keyword">Do</span> person.<span class="hljs-built_in">%JSONExport</span>()

<span class="hljs-keyword">Quit</span> tSC

}

/// Update a record in dc.Sample.Person with idClassMethod UpdatePerson(id As%Integer) As%Status { #dim tSC As%Status = $$$OK#dim e As%Exception.AbstractExceptionSet person = ##class(dc.Sample.Person).%OpenId(id) If '$IsObject(person) Return..Http404() Set data=%request.Content$$$TOE(tSC,person.%JSONImport(data)) $$$TOE(tSC,person.%Save())

<span class="hljs-keyword">Set</span> <span class="hljs-built_in">%response.Status</span> = <span class="hljs-number">200</span>
<span class="hljs-keyword">Set</span> <span class="hljs-built_in">%response.ContentType</span> = ..#CONTENTTYPEJSON
<span class="hljs-keyword">Do</span> person.<span class="hljs-built_in">%JSONExport</span>()

<span class="hljs-keyword">Quit</span> tSC

}

/// Delete a record with id in dc.Sample.PersonClassMethod DeletePerson(id As%Integer) As%Status { #dim tSC As%Status = $$$OK#dim e As%Exception.AbstractExceptionSet person = ##class(dc.Sample.Person).%OpenId(id) If '$IsObject(person) Return..Http404()

<span class="hljs-built_in">$$$TOE</span>(tSC,person.<span class="hljs-built_in">%DeleteId</span>(id))

<span class="hljs-keyword">Set</span> <span class="hljs-built_in">%response.Status</span> = <span class="hljs-number">200</span>
<span class="hljs-keyword">Set</span> <span class="hljs-built_in">%response.ContentType</span> = ..#CONTENTTYPEJSON

<span class="hljs-keyword">Quit</span> tSC

}

ClassMethod CreateRandomPersons(amount As%Integer) As%Status { #dim tSC As%Status = $$$OKSet%response.ContentType = ..#CONTENTTYPEJSON

<span class="hljs-keyword">Try</span> {
    <span class="hljs-keyword">set</span> status = <span class="hljs-keyword">##class</span>(dc.Sample.Person).AddTestData(amount)
    <span class="hljs-built_in">$$$ThrowOnError</span>(status)
    <span class="hljs-keyword">Set</span> message = <span class="hljs-string">"Created "</span>_amount_<span class="hljs-string">" random persons in Sample.Person data"</span>
} <span class="hljs-keyword">Catch</span>(ex) {
    <span class="hljs-keyword">Set</span> tSC = ex.Code
}
<span class="hljs-keyword">Return</span> tSC

}

ClassMethod SwaggerSpec() As%Status { Set tSC = ##class(%REST.API).GetWebRESTApplication($NAMESPACE, %request.Application, .swagger) Do swagger.info.%Remove("x-ISC_Namespace") Set swagger.basePath = "/crud"Set swagger.info.title = "InterSystems IRIS REST CRUD demo"Set swagger.info.version = "0.1"Set swagger.host = "localhost:52773"Return ..%ProcessResult($$$OK, swagger) }

}

Création de données et obtention d'un rapport à partir de l'interface utilisateur Swagger

1. Accédez à la page de l'interface utilisateur Swagger (http://localhost:52773/swagger-ui/index.html):

2. Accédez à la méthode /persons/gen/{amount}, développez-la, fixez le montant à 10 et le contenu à {}, puis exécutez-la (bouton Exécuter) :

3. Accédez maintenant à la méthode /report et exécutez-la :

4. Cliquez sur le lien de téléchargement du fichier :

5. Découvrez les résultats :

Tout est prêt ! Vous disposez d'une API avec générateur de rapports. Dans le prochain article, nous concevrons un rapport avec des paramètres.

0
1 52
Article Pierre LaFay · Avr 9, 2024 4m read

Introduction

Il existe une option d'assistant de procédure de liaison dans le portail de gestion (Système > SQL > Assistants > Procédure de liaison) avec laquelle j'ai eu des problèmes de fiabilité, j'ai donc décidé d'utiliser cette solution à la place.

Problème

0
0 77
Article Iryna Mykhailova · Avr 1, 2024 5m read

Préparez une application d'échantillon (Sample)


1. Pour ce tutoriel, nous utiliserons le modèle iris-rest-api-template: https://openexchange.intersystems.com/package/iris-rest-api-template, en ajoutant du code pour installer un support de JIRISReport. Procédez comme suit :
2. Clonez le projet dans un dossier local :

$ git clone https://github.com/intersystems-community/iris-rest-api-template.git

3. Modifiez le fichier Dockerfile avec le contenu suivant :

ARG IMAGE=intersystemsdc/iris-community:2020.3.0.221.0-zpm
ARG IMAGE=intersystemsdc/iris-community
FROM $IMAGE

USER root

RUNecho ttf-mscorefonts-installer msttcorefonts/accepted-mscorefonts-eula select true | debconf-set-selections RUN apt-get update && \ apt-get install ttf-mscorefonts-installer -y &&
apt-get install fontconfig -y RUNfc-cache -v -f /usr/share/fonts USER ${ISC_PACKAGE_MGRUSER}

WORKDIR /home/irisowner/dev RUN --mount=type=bind,src=.,dst=.
iris start IRIS &&
iris session IRIS < iris.script &&
iris stop IRIS quietly

4. Exécutez ces commandes pour construire et exécuter l'échantillon :

docker compose build up -d

5. Ouvrez le code source sur VSCode (installez ObjectScript et les extensions InterSystems si vous ne les avez pas encore) et Choizissez en bas docker:iris52773[USER] pour ouvrir les options :

6. Choizissez l'option Ouvrir un terminal dans Docker :

7. Le terminal s'affiche :

8. Tapez zpm pour lancer l'interpréteur de commandes zpm :

9. Tapez, exécutez et attendez l'installation (cela prend un certain temps) :

zpm:USER>install jirisreport -verbose

10. Découvrez les résultats de l'installation :




11. Dans VSCode, accédez à Person.cls et exécutez la méthode AddTestData (cliquez sur Debug) avec 20 enregistrements :


12. Nous disposons à présent d'une base de données contenant des exemples de données pour vos rapports.

Téléchargez le pilote JDBC d'IRIS

1. Téléchargez à partir de https://github.com/intersystems-community/iris-driver-distribution/raw/main/JDBC/JDK18/intersystems-jdbc-3.7.1.jar et sauvegardez dans n'importe quel dossier (dans mon cas, D:\projetos\isc\jirisreport-api-sample).


Conception de rapports avec JasperReports Studio

1. Accédez à https://community.jaspersoft.com/community-download et téléchargez Jaspersoft Studio CE :


2. Choisissez la bonne version pour votre OS :


3. Maintenant que Jasper Studio est installé, exécutez-le :



4. L'explorateur de projet (Project Explorer) s'affiche :

5. Cliquez sur l'explorateur de référentiel (Repository Explorer) > Faites un clic droit sur les adaptateurs de données > Créer un adaptateur de données (Data Adapter) :

6. Choizissez Database JDBC Connection et cliquez sur Next :

7. Définissez les valeurs suivantes pour l'onglet d'emplacement de la base de données (Database Location) :

  • Nom: IRISAdapter
  • Pilote JDBC : com.intersystems.jdbc.IRISDriver
  • JDBC Url: jdbc:IRIS://127.0.0.1:51773/User
  • Nom d'utilidateur : _SYSTEM
  • Mot de passe : SYS

8. Choizissez ensuite l'onglet Driver Classpath :

9. Cliquez sur le bouton d'ajout (Add) et Choizissez l'emplacement du fichier du pilote JDBC (dans le dossier choisi dans la section Télécharger le pilote JDBC d'IRIS) :

10. Cliquez ensuite sur Test :

11. Cliquez sur Finish. Nous disposons maintenant d'une connexion à la base de données pour IRIS :

 

Créez un nouveau rapport

1. Accédez à: Fichier > Nouveau > Rapport Jasper :

2. Choisissez Blank A4 et cliquez sur Next :

3. Définissez le nom du rapport AllPersons.jrxml et cliquez sur Next :

4. Choisissez IRISAdapter et écrivez :

select * from"dc_Sample"."Person"

5. Cliquez sur Next.

6. Choisissez tous les champs, à l'exception du champ ID, et cliquez sur Next :

7. Ce rapport n'a pas de bandes, cliquez sur Next :

8. Découvrez félicitations (Congratulations) et cliquer sur Finish :

9. Nous avons maintenant un rapport vide, mais connecté aux données IRIS :

10. JasperReports travaille avec un concept de bande et nous travaillerons avec des bandes suivantes :

  • Titre : section permettant d'imprimer le titre du rapport sur la première page uniquement.
  • En-tête de colonne : utilisé pour les rapports comportant des colonnes, pour imprimer le titre de la colonne sur une nouvelle page.
  • Détail 1 : section pour les données de la base de données.

11. Dans la palette, sélectionnez Static Text et effectuez un glisser-déposer pour la section de titre (Title) :

12. Modifiez la boîte de texte contenant la valeur de la liste des personnes Person List, mettez-la en forme et augmentez la taille des caractères (Arial, 20 Bold, Center).

13. Sous l'onglet bordures, cliquez sur les bordures du haut et du bas :

14. Ajuster la section titre (Title) pour qu'elle occupe moins d'espace :

15. Faites un clic droit sur l'en-tête de la page et supprimez-le :

16. Faites de même pour les bandes "Pied de colonne", "Pied de page" et "Résumé" (Column Footer, Page Footer et Summary, respectivement) et nous n'avons plus que 3 bandes :


17. Développez les champs sur Outline (aperçu), sélectionnez le nom et faites un glisser-déposer pour la section Detail 1 :


18. Ajustez la position du nom du texte statique (Name) dans l'en-tête de colonne et du champ de nom (Name Field) dans la bande de détail (Detail band) :


19. Réduisez maintenant la hauteur de l'en-tête de colonne (Column Header) et du détail (Detail) :

20. Glissez-déposez les autres champs de la bande de détail et ajustez-les :

21. Maintenant, mettez en forme les étiquettes de titre (Arial, 14, gras) :


22. Mettez en forme les champs (Arial, 14) :


23. Cliquez sur le bouton de sauvegarde Save (ou Fichier > Sauvegarder) en haut de la page et cliquez sur l'onglet d'aperçu (Preview) pour visualiser les résultats :


24. Votre rapport est prêt !

Dans le prochain article (Partie II), nous apprendrons comment exécuter ce rapport à partir d'un rapport IRIS de l'API REST.

0
0 70
Article Iryna Mykhailova · Mars 25, 2024 4m read

Ce que je trouve vraiment utile à propos d'IRIS lorsque j'enseigne mon sujet des bases de données postrelationnelles, c'est le fait qu'il s'agit d'une base de données multi-modèles. Ce qui signifie que je peux aborder l'architecture et la structure et tout cela une seule fois, mais ensuite montrer l'utilisation de différents modèles (comme l'objet, le document, la hiérarchie) en utilisant le même langage et la même approche. Et ce n'est pas un grand pas de passer d'un langage de programmation orienté objet (comme C#, Java, etc.) à une base de données orientée objet.

Cependant, aux avantages (qui sont nombreux) s'ajoutent certains inconvénients quand on passe du modèle orienté objet au modèle relationnel. Lorsque je dis que vous pouvez accéder aux mêmes données en utilisant différents modèles, je dois également expliquer comment il est possible de travailler avec des listes et des arrays à partir d'un modèle objet dans une table relationnelle. Avec les arrays, c'est très simple : par défaut, ils sont représentés sous forme de tableaux séparés et c'est tout. Avec les listes, c'est plus difficile car par défaut c'est une $lb. Mais on veut quand même faire quelque chose sans endommager la structure et sans rendre cette liste illisible dans le modèle objet.

Ainsi, dans cet article, je présenterai quelques prédicats et une fonction qui sont utiles lorsque vous travaillez avec des listes, et pas seulement en tant que champs.

0
0 227
Article Iryna Mykhailova · Mars 19, 2024 3m read

Récemment, la question s'est posée en discutant avec mes étudiants de l'accès aux données stockées dans IRIS depuis différentes langues : s'il était possible d'initier la connexion et d'obtenir les données de la solution Cloud (InterSystems IRIS CloudSQL) à partir de Microsoft Excel, et non l'inverse. Compte tenu des nombreuses façons différentes d'obtenir des données dans Excel (importation de données à partir de sources externes, connexion à des bases de données à l'aide de pilotes ODBC, utilisation de requêtes avancées et de requêtes Web, etc.), le choix évident était d'essayer le pilote ODBC. La seule tâche qui restait était d'essayer de se connecter à la base de données dans le cloud à l'aide du pilote ODBC.

0
0 84
Article Maria Nesterenko · Mars 15, 2024 8m read

L'intelligence artificielle (IA) attire beaucoup d'attention dernièrement car elle peut changer de nombreux domaines de nos vies. Une meilleure puissance informatique et plus de données ont aidé l'IA à réaliser des choses incroyables, comme l'amélioration des tests médicaux et la création de voitures autonomes. L'IA peut également aider les entreprises à prendre de meilleures décisions et à travailler plus efficacement, c'est pourquoi elle devient de plus en plus populaire et largement utilisée.

 

0
0 76
Article Iryna Mykhailova · Mars 12, 2024 6m read

Nous savons tous qu'il est crucial de disposer d'un ensemble de données de test appropriées avant de déployer une application en production pour garantir sa fiabilité et ses performances. Il permet de simuler des scénarios du monde réel et d'identifier les problèmes ou bugs potentiels avant qu'ils n'impactent les utilisateurs finaux. De plus, les tests avec des ensembles de données représentatifs permettent d’optimiser les performances, d’identifier les goulots d’étranglement et d’affiner les algorithmes ou les processus selon les besoins. En fin de compte, disposer d’un ensemble complet de données de test permet de fournir un produit de meilleure qualité, réduisant ainsi le risque de problèmes de post-production et améliorant l’expérience utilisateur globale.

Dans cet article, voyons comment utiliser l'IA générative, par example Gemini de Google, pour générer des données significatives sur les propriétés de plusieurs objets. Pour ce faire, j'utiliserai le service RESTful pour générer des données au format JSON puis j'utiliserai les données reçues pour créer des objets.

0
0 125
Article Pierre LaFay · Mars 3, 2024 9m read

Intro

La plupart des communications serveur-client sur le web sont basées sur une structure de demande et de réponse. Le client envoie une demande au serveur et le serveur répond à cette demande. Le protocole WebSocket fournit un canal de communication bidirectionnel entre un serveur et un client, permettant aux serveurs d'envoyer des messages aux clients sans recevoir de demande au préalable. Pour plus d'informations sur le protocole WebSocket et son implémentation dans InterSystems IRIS, voir les liens ci-dessous.

Ce tutoriel est une mise à jour de ["Asynchronous Websockets -- a quick tutorial"] (https://community.intersystems.com/post/asynchronous-websockets-quick-tutorial) pour Caché 2016.2+ et InterSystems IRIS 2018.1+.

Fonctionnement asynchrone ou synchrone

Dans InterSystems IRIS, une connexion WebSocket peut être mise en œuvre de manière synchrone ou asynchrone. Le mode de fonctionnement de la connexion WebSocket entre le client et le serveur est déterminé par la propriété "SharedConnection" de la classe %CSP.WebSocket.

  • SharedConnection=1 : Fonctionnement asynchrone

  • SharedConnection=0: Fonctionnement synchrone

Une connexion WebSocket entre un client et un serveur hébergé sur une instance InterSystems IRIS comprend une connexion entre l'instance IRIS et la passerelle Web. En mode synchrone, la connexion utilise un canal privé. Dans le cas d'une opération WebSocket asynchrone, un groupe de clients WebSocket partage un pool de connexions entre l'instance IRIS et la passerelle Web. L'avantage d'une implémentation asynchrone des WebSockets est évident lorsque de nombreux clients se connectent au même serveur, car cette implémentation n'exige pas que chaque client soit traité par une connexion exclusive entre la passerelle Web et l'instance IRIS.

Dans ce tutoriel, nous mettrons en œuvre les WebSockets de manière asynchrone. Ainsi, toutes les fenêtres de chat ouvertes partagent un pool de connexions entre la passerelle Web et l'instance IRIS qui héberge la classe de serveur WebSocket.

Présentation de l'application Chat

Le "hello world" des WebSockets est une application de chat dans laquelle un utilisateur peut envoyer des messages qui sont diffusés à tous les utilisateurs connectés à l'application. Dans ce tutoriel, les composants de l'application de chat sont les suivants :

  • Serveur : implémenté dans une classe qui étend %CSP.WebSocket

  • Client: mis en œuvre par une page CSP

La mise en œuvre de cette application de chat permettra d'atteindre les objectifs suivants :

  • Les utilisateurs peuvent diffuser des messages à toutes les fenêtres de chat ouvertes

  • Les utilisateurs en ligne apparaissent dans la liste "Utilisateurs en ligne" de toutes les fenêtres de chat ouvertes.

  • Les utilisateurs peuvent changer leur nom d'utilisateur en composant un message commençant par le mot-clé "alias". Ce message ne sera pas diffusé mais mettra à jour la liste des "Utilisateurs en ligne".

  • Lorsque les utilisateurs ferment leur fenêtre de chat, ils sont retirés de la liste des "Utilisateurs en ligne".

Pour obtenir le code source de l'application de chat, veuillez consulter ce [dépôt GitHub] (https://github.com/intersystems/InterSystems-WebSockets).

Le Client

Le côté client de notre application de chat est mis en œuvre par une page CSP contenant le style de la fenêtre de chat, la déclaration de la connexion WebSocket, les événements et méthodes WebSocket qui gèrent la communication vers et depuis le serveur, et les fonctions d'aide qui regroupent les messages envoyés au serveur et traitent les messages entrants.

Tout d'abord, nous verrons comment l'application initie la connexion WebSocket à l'aide d'une bibliothèque Javascript WebSocket.

    ws = new WebSocket(((window.location.protocol === "https:")? "wss:":"ws:")
                    + "//"+ window.location.host + "/csp/user/Chat.Server.cls");

new crée une nouvelle instance de la classe WebSocket. Celle-ci ouvre une connexion WebSocket au serveur en utilisant le protocole "wss" (indique l'utilisation de TLS pour le canal de communication WebSocket) ou "ws". Le serveur est spécifié par le numéro de port du serveur web et le nom de l'hôte de l'instance qui définit la classe Chat.Server (cette information est contenue dans la variable window.location.host). Le nom de notre classe de serveur (Chat.Server.cls) est inclus dans l'URI d'ouverture de la WebSocket en tant que requête GET pour la ressource sur le serveur.

L'événement ws.onopen se déclenche lorsque la connexion WebSocket est établie avec succès, passant d'un état connecting à un état open.

    ws.onopen = function(event){
        document.getElementById("headline").innerHTML = "CHAT - CONNECTED";
    };

Cet événement met à jour l'en-tête de la fenêtre de chat pour indiquer que le client et le serveur sont connectés.

Envoi de messages

L'action d'un utilisateur qui envoie un message déclenche la fonction send. Cette fonction sert d'enveloppe à la méthode ws.send, qui contient les mécanismes d'envoi du message du client au serveur via la connexion WebSocket.

function send() {
	var line=$("#inputline").val();
	if (line.substr(0,5)=="alias"){
	    alias=line.split(" ")[1];
		if (alias==""){
		    alias="default";
		}
		var data = {}
		data.User = alias
		ws.send(JSON.stringify(data));
        } else {
	    var msg=btoa(line);
	    var data={};
	    data.Message=msg;
	    data.Author=alias;
	    if (ws && msg!="") {
		    ws.send(JSON.stringify(data));
	    }
	}
	$("#inputline").val("");
}

send compile les informations à envoyer au serveur dans un objet JSON, en définissant des paires clé/valeur en fonction du type d'information envoyée (mise à jour d'alias ou message général). btoa traduit le contenu d'un message général en une chaîne ASCII encodée en base 64.

Réception des messages

Lorsque le client reçoit un message du serveur, l'événement ws.onmessage est déclenché.

ws.onmessage = function(event) {
	var d=JSON.parse(event.data);
	if (d.Type=="Chat") {
	    $("#chat").append(wrapmessage(d));
            $("#chatdiv").animate({ scrollTop: $('#chatdiv').prop("scrollHeight")}, 1000);
	} else if(d.Type=="userlist") {
		var ul = document.getElementById("userlist");
		while(ul.firstChild){ul.removeChild(ul.firstChild)};
		$("#userlist").append(wrapuser(d.Users));
	} else if(d.Type=="Status"){
		document.getElementById("headline").innerHTML = "CHAT - connected - "+d.WSID;
	}
};

Selon le type de message reçu par le client ("Chat", "userlist" ou "status"), l'événement onmessage appelle wrapmessage ou wrapuser pour remplir les sections appropriées de la fenêtre de chat avec les données entrantes. Si le message entrant est une mise à jour d'état, l'en-tête d'état de la fenêtre de discussion est mis à jour avec l'ID WebSocket, qui identifie la connexion WebSocket bidirectionnelle associée à la fenêtre de discussion.

Composants supplémentaires du client

Une erreur dans la communication entre le client et le serveur déclenche la méthode WebSocket onerror, qui émet une alerte nous informant de l'erreur et mettant à jour l'en-tête d'état de la page.

ws.onerror = function(event) {
	document.GetElementById("headline").innerHTML = "CHAT - error";
	alert("Received error"); 
};

The onclose method is triggered when the WebSocket connection between the client and server is closed and updates the status header.

ws.onclose = function(event) {
	ws = null;
	document.getElementById("headline").innerHTML = "CHAT - disconnected";
}

Le Serveur

Le côté serveur de l'application de chat est implémenté par la classe Chat.Server, qui étend %CSP.WebSocket. Notre classe serveur hérite de diverses propriétés et méthodes de %CSP.WebSocket, dont certaines seront discutées ci-dessous. Chat.Server implémente également des méthodes personnalisées pour traiter les messages provenant du ou des client(s) et pour les diffuser.

Avant de démarrer le serveur

OnPreServer() est exécutée avant la création du serveur WebSocket et est héritée de la classe %CSP.WebSocket.

Method OnPreServer() As %Status
{
    set ..SharedConnection=1
    if (..WebSocketID '= ""){ 
        set ^Chat.WebSocketConnections(..WebSocketID)=""
    } else {
        set ^Chat.Errors($INCREMENT(^Chat.Errors),"no websocketid defined")=$HOROLOG 
    }
    Quit $$$OK
}

Cette méthode définit le paramètre de classe SharedConnection à 1, indiquant que notre connexion WebSocket sera asynchrone et supportée par plusieurs processus qui définissent les connexions entre l'instance InterSystems IRIS et la Web Gateway. Le paramètre SharedConnection ne peut être modifié que dans OnPreServer(). OnPreServer() stocke également l'identifiant WebSocket associé au client dans le global ^Chat.WebSocketConnections.

La méthode Server

L'essentiel de la logique exécutée par le serveur est contenu dans la méthode Server().``` Method Server() As %Status { do ..StatusUpdate(..WebSocketID) for { set data=..Read(.size,.sc,1) if ($$$ISERR(sc)){ if ($$$GETERRORCODE(sc)=$$$CSPWebSocketTimeout) { //$$$DEBUG("no data") } if ($$$GETERRORCODE(sc)=$$$CSPWebSocketClosed){ kill ^Chat.WebSocketConnections(..WebSocketID) do ..RemoveUser($g(^Chat.Users(..WebSocketID))) kill ^Chat.Users(..WebSocketID) quit // Client closed WebSocket } } else{ if data["User"{ do ..AddUser(data,..WebSocketID) } else { set mid=$INCREMENT(^Chat.Messages) set ^Chat.Messages(mid)=data do ..ProcessMessage(mid) } } } Quit $$$OK }

Cette méthode lit les messages entrants du client (en utilisant la méthode `Read` de la classe `%CSP.WebSockets`), ajoute les objets JSON reçus au global `^Chat.Messages`, et appelle `ProcessMessage()` pour transmettre le message à tous les autres clients de chat connectés. Lorsqu'un utilisateur ferme sa fenêtre de chat (mettant ainsi fin à la connexion WebSocket avec le serveur), l'appel à `Read` de la méthode `Server()` renvoie un code d'erreur qui évalue la macro `$$CSPWebSocketClosed` et la méthode procède à la gestion de la fermeture en conséquence.

### *Traitement et distribution des messages*

`ProcessMessage()` ajoute des métadonnées au message de chat entrant et appelle `SendData()`, en passant le message en paramètre.  

ClassMethod ProcessMessage(mid As %String) { set msg = ##class(%DynamicObject).%FromJSON($GET(^Chat.Messages(mid))) set msg.Type="Chat" set msg.Sent=$ZDATETIME($HOROLOG,3) do ..SendData(msg) }


`ProcessMessage()` récupère le message au format JSON dans le global `^Chat.Messages` et le convertit en un objet IRIS d'InterSystems en utilisant la méthode `%FromJSON` de la classe `%DynamicObject`. Cela nous permet d'éditer facilement les données avant de transmettre le message à tous les clients de chat connectés. Nous ajoutons un attribut `Type` avec la valeur "Chat", que le client utilise pour déterminer comment traiter le message entrant. `SendData()` envoie le message à tous les autres clients de chat connectés.```
ClassMethod SendData(data As %DynamicObject)
{
    set c = ""
    for {
        set c = $order(^Chat.WebSocketConnections(c))
        if c="" Quit
        set ws = ..%New()
        set sc = ws.OpenServer(c)
        if $$$ISERR(sc) { do ..HandleError(c,"open") } 
        set sc = ws.Write(data.%ToJSON())
        if $$$ISERR(sc) { do ..HandleError(c,"write") }
    }
}

SendData() convertit l'objet InterSystems IRIS en une chaîne JSON (data.%ToJSON()) et envoie le message à tous les clients du chat. SendData() récupère l'ID WebSocket associé à chaque connexion client-serveur dans le global ^Chat.WebSocketConnections et utilise l'ID pour ouvrir une connexion WebSocket via la méthode OpenServer de la classe %CSP.WebSocket. Nous pouvons utiliser la méthode OpenServer car nos connexions WebSocket sont asynchrones - nous puisons dans le pool existant de processus IRIS-Web Gateway et attribuons à l'un d'entre eux l'ID WebSocket qui identifie la connexion du serveur à un client de chat spécifique. Enfin, la méthode Write()%CSP.WebSocket` envoie la représentation JSON du message au client.

Conclusion

Cette application de chat montre comment établir des connexions WebSocket entre un client et un serveur hébergés par InterSystems IRIS. Pour en savoir plus sur le protocole et son implémentation dans InterSystems IRIS, consultez les liens dans l'introduction.

0
0 199
Article Pierre LaFay · Fév 28, 2024 5m read

Qu'est-ce que les données non structurées ?

Les données non structurées sont des informations qui n'ont pas de modèle de données ou d'organisation prédéfinis. Contrairement aux données structurées que l'on trouve dans les bases de données avec des structures claires (par exemple, des tables et des champs), les données non structurées n'ont pas de schéma fixe. Ce type de données comprend le texte, les images, les vidéos, les fichiers audio, les messages sur les médias sociaux, les courriels, etc.

0
0 63
Article Pierre LaFay · Fév 25, 2024 3m read

Je souhaite aborder les problèmes désagréables liés à la lecture d'un texte plat en ASCII, UTF*
excluant explicitement HTML, EBCDIC, et autres encodages.
D'après Wikipediail existe au moins 8 variantes de caractères de contrôle.

  • CR+LF est typique de Windows
  • LF est typique du monde Linux/UNIX
  • CR est le préféré de Mac

Comme vous pouvez le déduire des noms, l'inspiration vient des machines à écrire mécaniques.

Dans IRIS* comme dans Caché ou Ensemble ou ... les classes %Stream* et %File* offrent la même propriété avec la même valeur par défaut.

1
0 66
Article Pierre LaFay · Fév 25, 2024 13m read

La classe %CSP.Login est la classe utilitaire fournie par InterSystems IRIS pour créer des pages de connexion personnalisées. Si vous souhaitez contrôler l'interface utilisateur d'authentification de votre application IRIS, vous devez étendre %CSP.Login et surcharger certaines méthodes en fonction de vos besoins. Cet article va détailler ces méthodes et ce que vous pouvez faire avec elles. En outre, vous obtiendrez une explication du mécanisme d'authentification déléguée fourni par la routine ZAUTHENTICATE.mac. Enfin, vous serez en mesure de créer une logique d'authentification personnalisée,

0
0 64
Article Pierre LaFay · Fév 7, 2024 8m read

Introduction

Il n'y a pas si longtemps, j'ai vu l'idée de using Python Class Definition Syntax to create IRIS classes

sur le portail d'idées d'InterSystems. Elle a attiré mon attention car l'intégration d'un maximum de syntaxes donne de la visibilité aux produits d'InterSystems pour les programmeurs ayant de l'expérience dans de nombreux langages.

0
0 65
Article Pierre LaFay · Jan 7, 2024 3m read

Le sous-système Windows pour Linux (WSL) est une fonctionnalité de Windows qui vous permet d'exécuter un environnement Linux sur votre ordinateur Windows, sans avoir besoin d'une machine virtuelle distincte ni d'un double démarrage.

WSL est conçu pour offrir une expérience transparente et productive aux développeurs qui souhaitent utiliser à la fois Windows et Linux**.

0
0 104
Article Guillaume Rongier · Déc 14, 2023 10m read

Dans cette série d'articles, j'aimerais présenter et discuter de plusieurs approches possibles pour le développement de logiciels avec les technologies d'InterSystems et GitLab. J'aborderai des sujets tels que:

  • Git 101
  • Flux Git (processus de développement)
  • Installation de GitLab
  • Flux de travail GitLab
  • Diffusion continue
  • Installation et configuration de GitLab
  • GitLab CI/CD
  • Pourquoi des conteneurs?
  • Infrastructure de conteneurs
  • CD utilisant des conteneurs
  • CD utilisant ICM

Dans cet article, nous allons créer une diffusion continue avec InterSystems Cloud Manager. ICM est une solution de déploiement et de provisionnement en nuage pour les applications basées sur InterSystems IRIS. Il vous permet de définir la configuration de déploiement souhaitée et ICM la provisionne automatiquement. Pour plus d'informations, consultez : First Look : ICM.

0
0 74
Article Sylvain Guilbaud · Août 31, 2023 7m read

Description du cas

Imaginons que vous soyez un développeur Python ou que vous disposiez d'une équipe bien formée et spécialisée en Python, mais que le délai dont vous disposez pour analyser certaines données dans IRIS est serré. Bien entendu, InterSystems propose de nombreux outils pour toutes sortes d’analyses et de traitements. Cependant, dans le scénario donné, il est préférable de faire le travail en utilisant les bons vieux Pandas et de laisser l'IRIS pour une autre fois.

0
0 125
Article Guillaume Rongier · Juin 26, 2023 3m read

Introduction

Dans certains des derniers articles, j'ai parlé des types entre IRIS et Python, et il est clair qu'il n'est pas facile d'accéder aux objets d'un côté à l'autre.  

Heureusement, un travail a déjà été fait pour créer SQLAlchemy-iris (suivez le lien pour le voir sur Open Exchange), qui rend tout beaucoup plus facile pour Python d'accéder aux objets d'IRIS, et je vais montrer les starters pour cela.

Merci à @Dmitry Maslennikov !

Installation

Pour l'installer, il suffit d'ouvrir votre terminal avec un accès administrateur et de taper

pip install sqlalchemy-iris

et les pré-requis seront également installés pour vous, si nécessaire.

Utilisation

Maintenant, sur un fichier python, vous pouvez importer le module, vous connecter à la base de données et jouer avec sqlalchemy comme vous le souhaitez. Si vous vous sentez à l'aise, vous pouvez suivre les étapes suivantes :

  • Importez "create_engine" de sqlalchemy et créez le moteur avec la chaîne "iris://username:password@IP:port/namespace". Bien sûr, vous pouvez importer tout le module, mais "create_engine" crée une instance de Engine (sqlalchemy.engine, pour plus d'informations cliquez ici) qui a toutes les sous-classes nécessaires pour ce que je présente ici..
from sqlalchemy import create_engine

engine = create_engine("iris://_SYSTEM:SYS@localhost:1972/SAMPLE")
  • Créez la connexion (sqlalchemy.engine.connection, pour plus d'informations cliquez ici) ainsi vous pourrez travailler avec des transactions, des exécutions simples, etc.
conn = engine.connect()

C'est très bien ! Vous avez maintenant configuré l'accès à votre base de données.

Pour une simple requête SELECT, et pour itérer à travers l'ensemble des résultats, faites ce qui suit (comme d'habitude, en utilisant comme exemple le tableau créé dans cet article):

query = 'SELECT Name, Age  from Sample.PersistentData WHERE Age >=21'
result = conn.exec_driver_sql(query)

Maintenant, le résultat est un CursorResult (sqlalchemy.engine.CursorResult). Vous pouvez vérifier tout ce que vous pouvez faire avec un CursorResult ici, dans la documentation officielle. C'est tout ce que vous avez à faire pour une simple itération :

print("Name, Age")
for row in result:
    print(row[0], ", ", row[1])

 et avec un peu de formatage, vous pouvez avoir un résultat du type suivant :

Maintenant comme vous savez par où commencer, vous pouvez également consulter la documentation officielle pour plus de détails et de possibilités.

PS : vous pouvez également importer "text" de sqlalchemy et exécuter la requête comme suit

result = conn.execute(text(query))

ce qui produira exactement les mêmes résultats.

Conclusion

Vous pouvez également exécuter des DDL et toute autre instruction DML, et il y a un support encore plus important pour travailler avec un un mapping objet-relationnel ORM (_Object Relational Mapping), _mais comme ceci n'est qu'un "démarrage", je n'irai pas plus loin.

Souhaitez-vous plus de tutoriels avec SQLAlchemy ? Peut-être la prochaine fois en utilisant ORM ?
N'hésitez pas à me contacter si vous avez des doutes !

0
1 618
Article Guillaume Rongier · Mai 29, 2023 10m read

Introduction

L'analyse des données est un aspect crucial de la prise de décision commerciale dans le monde moderne où tout va très vite. Les organisations s'appuient fortement sur l'analyse des données pour prendre des décisions éclairées et garder une longueur d'avance sur la concurrence. Dans cet article, nous allons explorer comment l'analyse de données peut être réalisée en utilisant Pandas et Intersystems Embedded Python. Nous discuterons des bases de Pandas, des avantages de l'utilisation d'Intersystems Embedded Python et de la façon dont ils peuvent être utilisés ensemble pour réaliser des analyses de données efficaces.

Pandas : à quoi ça sert ?

Pandas est un outil polyvalent qui peut être utilisé pour une large gamme de tâches, à tel point qu'il est peut-être plus facile de dresser la liste de ce qu'il ne peut pas faire plutôt que de ce qu'il peut faire.

Essentiellement, Pandas abrite vos données. Il vous permet de nettoyer, de transformer et d'analyser vos données afin de vous familiariser avec elles. Par exemple, si vous avez un ensemble de données enregistré dans un fichier CSV sur votre ordinateur, Pandas peut extraire les données dans une structure de type tableau appelée DataFrame. Avec ce DataFrame, vous pouvez effectuer diverses tâches telles que :

  • Calculer des statistiques et répondre à des questions sur les données, par exemple trouver la moyenne, la médiane, le maximum ou le minimum de chaque colonne, déterminer s'il existe une corrélation entre les colonnes ou explorer la distribution des données dans une colonne spécifique.
  • Nettoyer les données en supprimant les valeurs manquantes ou en filtrant les lignes et les colonnes sur la base de certains critères.
  • Visualiser les données à l'aide de Matplotlib, qui vous permet de tracer des barres, des lignes, des histogrammes, des bulles, etc.
  • Renvoyer les données nettoyées et transformées dans un fichier CSV, une base de données ou un autre type de fichier.

Avant de se lancer dans la modélisation ou les visualisations complexes, il est essentiel d'avoir une solide compréhension de la nature de votre ensemble de données, et pandas constitue le meilleur moyen d'y parvenir.  

Avantages de l'utilisation de Python intégré d'Intersystems

Python intégré d'Intersystems est un environnement d'exécution Python intégré à la plate-forme de données d'Intersystems. Il fournit un moyen sûr et efficace d'exécuter du code Python au sein de la plateforme de données, sans avoir à quitter l'environnement de la plateforme. Cela signifie que les analystes de données peuvent effectuer des tâches d'analyse de données sans avoir à passer d'un environnement à l'autre, ce qui se traduit par une efficacité et une productivité accrues.

 

Combinaison de Pandas et de Python intégré d'Intersystems

En combinant Pandas et Python intégré d'Intersystems, les analystes de données peuvent effectuer des tâches d'analyse de données en toute simplicité. Python intégré d'Intersystems fournit un environnement d'exécution sécurisé et efficace pour l'exécution du code Python, tandis que Pandas fournit un ensemble puissant d'outils de manipulation de données. Ces deux solutions offrent une solution complète d'analyse de données pour les organisations.  

Installation de Pandas.

Installation d'un paquet Python

Pour utiliser Pandas avec Python intégré, vous devez l'installer en tant que paquet Python. Voici les étapes de l'installation de Pandas :

  • Ouvrez une invite de commande en mode Administrateur (sous Windows).
  • Naviguez vers le répertoire &lt;installdir>/bin dans l'invite de commande.
  • Exécutez la commande suivante pour installer Pandas : irispip install --target &lt;installdir>\mgr\python pandas Cette commande installe Pandas dans le répertoire &lt;installdir>/mgr/python, qui est recommandé par InterSystems. Notez que la commande exacte peut différer en fonction du paquet que vous installez. Remplacez simplement pandas par le nom du paquet que vous souhaitez installer.

Voilà, c'est fait ! Vous pouvez maintenant utiliser Pandas avec Python intégré d'InterSystems.

irispip install --target C:\InterSystems\IRIS\mgr\python pandas


Maintenant que nous avons installé Pandas, nous pouvons commencer à travailler avec le jeu de données sur les employés. Voici les étapes à suivre pour lire le fichier CSV dans un Pandas DataFrame et effectuer un nettoyage et une analyse des données :

Tout d'abord, créons une nouvelle instance de python

Set python = ##class(%SYS.Python).%New()

Importation de Bibliothèques Python, dans ce cas je vais importer pandas et builtins

Set pd = python.Import("pandas")

#;Pour importer les fonctions intégrées qui font partie de la bibliothèque standard de PythonSet builtins = python.Import("builtins")

Importation de données dans la bibliothèque pandas

Il existe plusieurs façons de lire des données dans un DataFrame Pandas à l'aide de Python intégré. Voici trois méthodes courantes.
J'utilise le fichier modèle suivant comme exemple.

Lecture de données à partir d'un fichier CSV.

Utilisez read_csv() avec le trajet du fichier CSV pour lire des valeurs séparées par des virgules.

Set df = pd."read_csv"("C:\InterSystems\employees.csv")

 

Importation de fichiers texte {#importing-text-files}

La lecture des fichiers texte est similaire à celle des fichiers CSV. La seule nuance est que vous devez spécifier un séparateur avec l'argument sep, comme indiqué ci-dessous. L'argument séparateur fait référence au symbole utilisé pour séparer les lignes dans un DataFrame. La virgule (sep = ","), l'espace (sep = "\s"), la tabulation (sep = "\t"), et les deux points (sep = " :") sont les séparateurs les plus couramment utilisés. Ici, \s représente un seul caractère d'espacement.

Set df = pd."read_csv"("employees.txt",{"sep":"\s"})

 

Importation de fichiers Excel

Pour importer des fichiers Excel avec une seule feuille, la fonction "read_excel()" peut être utilisée avec le chemin d'accès au fichier en entrée. Par exemple, le code df = pd.read_excel('employees.xlsx') lit un fichier Excel nommé "diabetes.xlsx" et enregistre son contenu dans un DataFrame appelé "df".

D'autres arguments peuvent également être spécifiés, comme l'argument header qui détermine quelle ligne devient l'en-tête du DataFrame. Par défaut, header est fixé à 0, ce qui signifie que la première ligne devient l'en-tête ou les noms de colonnes. Si vous souhaitez spécifier des noms de colonnes, vous pouvez passer une liste de noms à l'argument names. Si le fichier contient un index de ligne, vous pouvez utiliser l'argument index_col pour le spécifier.

Il est important de noter que dans un DataFrame pandas ou une Series pandas, l'index est un identifiant qui pointe vers l'emplacement d'une ligne ou d'une colonne. Il étiquette la ligne ou la colonne d'un DataFrame et vous permet d'accéder à une ligne ou une colonne spécifique en utilisant son index. L'index de ligne peut être une plage de valeurs, une série chronologique, un identifiant unique (par exemple, l'identifiant d'un employé) ou d'autres types de données. Pour les colonnes, l'index est généralement une chaîne de caractères indiquant le nom de la colonne.

Set df = pd."read_excel"("employees.xlsx")

 

Importation de fichiers Excel (plusieurs feuilles) {#importing-excel-files-(multiple-sheets)}

La lecture de fichiers Excel avec plusieurs feuilles n'est pas très différente. Vous devez juste spécifier un argument supplémentaire, sheet_name, où vous pouvez soit passer une chaîne pour le nom de la feuille, soit un entier pour la position de la feuille (notez que Python utilise l'indexation 0, où la première feuille est accessible avec sheet_name = 0).

#; Extracting the second sheet since Python uses 0-indexingSet df = pd."read_excel"("employee.xlsx", {"sheet_name":"1"})

 

Lecture de données à partir d'un fichier JSON.

Set df = pd."read_json"("employees.json")

Examinons les données contenues dans une dataframe.

Comment afficher des données en utilisant .head() et .tail() ?

Pour cela, nous pouvons utiliser la bibliothèque des builtins que nous avons importée (ZW fonctionne aussi wink )

do builtins.print(df.head())

 

Dressons la liste de toutes les colonnes de l'ensemble de données

Do builtins.print(df.columns)

##

Nettoyons les données

 

Convertissez la colonne " Start Date " (date de début) en un objet type datetime (heure de la journée).

Set  df."Start Date" = pd."to_datetime"(df."Start Date")

l'ensemble de données mis à jour se présente comme suit.
 

Convertissez la colonne 'Last Login Time' (heure de dernière connexion) en un objet de type 'datetime' (heure de la journée).

Set df."Last Login Time" = pd."to_datetime"(df."Last Login Time")

Les valeurs manquantes de la colonne "Salaire" sont complétées par le salaire moyen.

Set meanSal = df."Salary".mean()
Set df."Salary" = df."Salary".fillna(meanSal)

 

Réalisation d'une analyse.

Détérminaison du salaire moyen par genre.

Do builtins.print(df.groupby("Gender")."Salary".mean())

###

 

Calculation du pourcentage moyen de la prime par équipe.

Do builtins.print(df.groupby("Team")."Bonus %".mean())

###
 

Calculation du nombre de salariés recrutés chaque année.

Do builtins.print(df."Start Date".dt.year."value_counts"()."sort_index"())

###

 

CCalculation du nombre de salariés par ancienneté privilégiée.

Do builtins.print(df."Senior Management"."value_counts"())

 

Sortie de données dans pandas {#outputting-data-in-pandas}

Tout comme pandas peut importer des données à partir de différents types de fichiers, il vous permet également d'exporter des données dans différents formats. C'est notamment le cas lorsque les données sont transformées à l'aide de pandas et qu'elles doivent être sauvegardées localement sur votre machine. Voici comment exporter des DataFrames pandas dans différents formats.

Sortie d'une DataFrame dans un fichier CSV {#outputting-a-dataframe-into-a-csv-file}

Un DataFrame pandas (ici nous utilisons df) est enregistré comme fichier CSV en utilisant la méthode . "to_csv"().

do df."to_csv"("C:\Intersystems\employees_out.csv")

 

Sortie d'une DataFrame dans un fichier JSON {#outputting-a-dataframe-into-a-json-file}

Exportation de l'objet DataFrame dans un fichier JSON en appelant la méthode . "to_json"().

do df."to_json"("C:\Intersystems\employees_out.json")

 

Sortie d'une DataFrame dans un fichier Excel {#outputting-a-dataframe-into-an-excel-file}

Appelez . "to_excel"() à partir de l'objet DataFrame pour l'enregistrer dans un fichier ".xls" ou ".xlsx".

do df."to_excel"("C:\Intersystems\employees_out.xlsx")

 

Créons un diagramme à barres de base qui montre le nombre d'employés recrutés chaque année.

pour cela, j'utilise matplotlib.pyplot
 

//importer matplotlibSet plt = python.Import("matplotlib.pyplot")
//créer un nouveau cadre de données pour représenter le diagramme à barresset df2 = df."Start Date".dt.year."value_counts"()."sort_index"().plot.bar()
//exporter la sortie en pngdo plt.savefig("C:\Intersystems\barchart.png")
//nettoyagedo plt.close()

  Voilà, c'est fait ! Avec ces étapes simples, vous devriez être en mesure de lire un fichier CSV, de nettoyer les données et d'effectuer quelques analyses de base à l'aide de Pandas dans Python intégré d'InterSystems.  

Vidéo

Vous pouvez maintenant accéder à la vidéo en utilisant le lien fourni ci-dessous. La vidéo elle-même constitue une vue d'ensemble et un développement complet du tutoriel ci-dessus.
https://youtu.be/hbRQszxDTWU

Conclusion 

Le tutorial fourni ne couvre que les principes de base de ce que pandas peut faire. Avec pandas, vous pouvez effectuer une large gamme de tâches d'analyse, de visualisation, de filtrage et d'agrégation de données, ce qui en fait un outil inestimable dans tout flux de données. En outre, lorsqu'il est associé à d'autres paquets de science des données, vous pouvez créer des tableaux de bord interactifs, développer des modèles d'apprentissage automatique pour faire des prédictions, automatiser des flux de données, et bien d'autres choses encore. Pour approfondir votre compréhension de pandas, explorez les ressources répertoriées ci-dessous et accélérez votre parcours d'apprentissage.  

Avertissement

Il est important de noter qu'il existe plusieurs façons d'utiliser Pandas avec InterSystems. L'article fourni est uniquement destiné à des fins éducatives et ne garantit pas l'approche la plus optimale. En tant qu'auteur, j'apprends et j'explore continuellement les capacités de Pandas, et par conséquent, il peut y avoir des méthodes ou des techniques alternatives qui pourraient produire de meilleurs résultats. Par conséquent, les lecteurs doivent faire preuve de discernement et de prudence lorsqu'ils appliquent les renseignements présentés dans l'article à leurs projets respectifs.

0
0 497
Article Iryna Mykhailova · Mai 22, 2023 12m read

###         

Bonjour à la communauté,
Dans cet article, je vais démontrer l'utilisation d'Embedded Python, nous allons couvrir les sujets suivants :

  • 1-Aperçu d'Embedded Python
  • 2-Utilisation d'Embedded Python
    • 2.1- Utilisation d'une bibliothèque Python à partir d'ObjectScript
    • 2.2- Appel des API d'InterSystems à partir de Python
    • 2.3- Utilisation conjointe d'ObjectScript et de Python
  • 3-Utilisation des fonctions intégrées de python
  • 4-Modules et bibliothèques Python 
  • 5-Les cas d'utilisation d'Embedded Python
    • 5.1- Impression d'un PDF en utilisant la bibliothèque Python Reportlab
    • 5.2- Création d'un code QR à l'aide de la bibliothèque Python Qrcode
    • 5.3- Obtention de la localisation GEO à l'aide de la bibliothèque Python Folium
    • 5.4- Générer et marquer des emplacements sur une carte interactive en utilisant biblithèque** **Python Folium
    • 5.5- Analyse de données à l'aide de la biblithèque Python Pandas

  • 6-Résumé

Commençons donc par un aperçu

 

1-Aperçu d'Embedded Python

Python intégré est une fonctionnalité de la plateforme de données InterSystems IRIS qui permet aux développeurs Python d'obtenir un accès complet et direct aux données et aux fonctionnalités d'InterSystems IRIS.

InterSystems IRIS est livré avec un puissant langage de programmation intégré appelé ObjectScript qui est interprété, compilé et exécuté à l'intérieur de la plate-forme de données.

Comme ObjectScript s'exécute dans le contexte d'InterSystems IRIS, il a un accès direct à la mémoire et aux appels de procédure de la plate-forme de données.

Python intégré est une extension du langage de programmation Python qui permet l'exécution du code Python dans le contexte du processus InterSystems IRIS.

Comme ObjectScript et Python opèrent tous deux sur la même mémoire objet, on peut dire que les objets Python ne se contentent pas d'émuler des objets ObjectScript, mais qu'ils sont des objets ObjectScript.

La coégalité de ces langages signifie qu'il est possible de choisir le langage le plus approprié pour le travail, ou le langage que l'on est le plus à l'aise à utiliser pour écrire des applications.

 

2-Utilisation d'Embedded Python

Lorsque vous utilisez Python intégré, vous pouvez écrire votre code selon trois modalités différentes.

2.1 - Utilisation d'une bibliothèque Python à partir d'ObjectScript

Tout d'abord, vous pouvez écrire un fichier .py ordinaire et l'appeler à partir du contexte IRIS d'InterSystems. Dans ce cas, la plateforme de données lancera le processus Python et vous permettra d'importer un module appelé IRIS, qui attache automatiquement le processus Python au noyau IRIS et vous donne accès à toutes les fonctionnalités d'ObjectScript à partir du contexte de votre code Python.

2.2 - Appel des API d'InterSystems à partir de Python

Deuxièmement, vous pouvez écrire du code ObjectScript ordinaire et instancier un objet Python à l'aide du paquet %SYS.Python. Ce paquet ObjectScript vous permet d'importer des modules et des bibliothèques Python, puis de travailler avec cette base de code à l'aide de la syntaxe ObjectScript.
Le paquet %SYS.Python permet aux développeurs ObjectScript sans aucune connaissance de Python d'utiliser le riche écosystème des bibliothèques Python dans leur code ObjectScript.

2.3 - Utilisation conjointe d'ObjectScript et de Python

Troisièmement, vous pouvez créer une définition de classe InterSystems et écrire des méthodes en Python. Tout appel à cette méthode lancera l'interpréteur Python. Cette méthode a l'avantage de remplir le mot-clé self de ce bloc de code Python d'une référence à l'instance de la classe qui le contient. En outre, en utilisant Python pour écrire des méthodes de classe dans les classes InterSystems, vous pouvez facilement mettre en œuvre des méthodes qui gèrent différents événements de saisie de données en SQL, tels que l'ajout d'une nouvelle ligne à un tableau.
Cela permet également de développer rapidement des procédures stockées personnalisées en Python.

Comme vous pouvez le constater, Python intégré vous permet de choisir le langage de programmation le mieux adapté à la tâche sans compromettre les performances.

3-Utilisation des fonctions intégrées de python

L'interpréteur Python a un certain nombre de fonctions et de types intégrés qui sont toujours disponibles. Ils sont répertoriés ici par ordre alphabétique.

<colgroup><col><col><col><col></colgroup>
<td>
  E enumerate() eval() exec()   F filter() float() format() frozenset()   G getattr() globals()   H hasattr() hash() help() hex()   I id() input() int() isinstance() issubclass() iter()
</td>

<td>
  L len() list() locals()   M map() max() memoryview() min()   N next()   O object() oct() open() ord()   P pow() print() property()        
</td>

<td>
  R range() repr() reversed() round()   S set() setattr() slice() sorted() staticmethod() str() sum() super()   T tuple() type()   V vars()   Z zip()   _ __import__()
</td>
Fonctions integrées
A abs() aiter() all() any() anext() ascii()   B bin() bool() breakpoint() bytearray() bytes()   C callable() chr() classmethod() compile() complex()   D delattr() dict() dir() divmod()  

****Utilisation des fonctions intégrées de python

Pour utiliser les fonctions intégrées de Python, nous avons besoin d'importer "builtins", puis nous pouvons invoquer la fonction

set builtins = ##class(%SYS.Python).Import("builtins")

La fonction print() de Python est en fait une méthode du module intégré, de sorte que vous pouvez maintenant utiliser cette fonction à partir d'ObjectScript :

USER>do builtins.print("hello world!")
hello world!
USER>set list = builtins.list()

USER>zwrite list
list=5@%SYS.Python  ; []  ; 

De même, la méthode help() permet d'obtenir de l'aide sur l'objet liste.

USER>do builtins.help(list)
L'aide sur l'objet liste:
classe list(object)
 |  list(iterable=(), /)
 |
 |  Séquence mutable intégrée.
 |
 |  Si aucun argument n'est donné, le constructeur crée une nouvelle liste vide.
 |  L'argument doit être un itérable s'il est spécifié.
 |
 |  Les méthodes définies ici :
 |
 |  __add__(self, value, /)
 |      Renvoi de la valeur+self.
 |
 |  __contains__(self, key, /)
 |      Renvoi de la clé dans self.
 |
 |  __delitem__(self, key, /)
 |      Suppression de la [clé] self.

## 

4-Modules et bibliothèques Python

Certains modules ou bibliothèques python sont installés par défaut et déjà disponibles. La fonction help("module") permet de visualiser ces modules :
Sortie de la liste des bibliothèques Python 1
 

Installation d'un module ou d'une bibliothèque python

Outre ces modules, python a des centaines de modules ou de bibliothèques, qui peuvent être consultés sur pypi.org( L' Indice de Paquet Python (PyPI) est un dépôt de logiciels pour le langage de programmation Python).

Si nous avons besoin d'autres bibliothèques, nous devons les installer à l'aide de la commande intersystems irispip.

Par exemple, Pandas est une bibliothèque d'analyse de données en python. La commande suivante utilise le programme d'installation de paquets irispip pour installer pandas sur un système Windows :

C:\InterSystems\IRIS\bin>irispip install --target C:\InterSystems\IRIS\mgr\python pandas

Veuillez noter que C:\NInterSystems sera remplacé par le répertoire d'installation d'Intersystems.
 

5-Les cas d'utilisation d'Embedded Python

5.1-Impression d' un PDF en utilisant la bibliothèque Python Reportlab

Nous devons installer la bibliothèque Reportlab à l'aide de la commande irispip, puis créer une fonction objectcript.

Compte tenu de l'emplacement d'un fichier, la méthode ObjectScript suivante, intitulée CreateSamplePDF(), crée un exemple de fichier PDF et l'enregistre à cet emplacement.

Class Demo.PDF
{

ClassMethod CreateSamplePDF(fileloc As%String) As%Status
{
    set canvaslib = ##class(%SYS.Python).Import("reportlab.pdfgen.canvas")
    set canvas = canvaslib.Canvas(fileloc)
    do canvas.drawImage("C:\Sample\isc.png", 150, 600)
    do canvas.drawImage("C:\Sample\python.png", 150, 200)
    do canvas.setFont("Helvetica-Bold", 24)
    do canvas.drawString(25, 450, "InterSystems IRIS & Python. Perfect Together.")
    do canvas.save()
}

}

La première ligne de la méthode importe le fichier canvas.py du sous-paquet pdfgen de ReportLab. La deuxième ligne de code instancie un objet Canvas et procède ensuite à l'appel de ses méthodes, de la même manière qu'elle appellerait les méthodes de n'importe quel objet IRIS d'InterSystems.

Vous pouvez ensuite appeler la méthode de la manière habituelle : 

do ##class(Demo.PDF).CreateSamplePDF("C:\Sample\hello.pdf")

Le PDF suivant est généré et enregistré à l'emplacement spécifié :
PDF d'une page avec le logo InterSystems, le logo Python et le texte : InterSystems IRIS et Python. Une association parfaite.

 

5.2-Création d'un code QR à l'aide de la bibliothèque Python Qrcode Library

Pour générer un code QR, nous devons installer la bibliothèque Qrcode en utilisant la commande irispip, puis en utilisant le code ci-dessous, nous pouvons générer un code QR:

 

5.3-Obtention de la localisation GEO à l'aide de la bibliothèque Python Folium

Pour obtenir des données géographiques, nous devons installer la bibliothèque Folium à l'aide de la commande irispip, puis créer la fonction de script objet ci-dessous :

Class dc.IrisGeoMap.Folium Extends%SwizzleObject
{

// Fonction d'impression de la latitude, de la longitude et des détails de l'adresse ClassMethod GetGeoDetails(addr As%String) [ Language = python ]
{
    from geopy.geocoders import Nominatim
    geolocator = Nominatim(user_agent="IrisGeoApp")
    try:
    	location = geolocator.geocode(addr)
    	print("Location:",location.point)
    	print("Address:",location.address)
    	point = location.point
    	print("Latitude:", point.latitude)
    	print("Longitude:", point.longitude)
    except:
    	print("Not able to find location")
}
}

Connectez-vous au terminal IRIS et exécutez le code suivant

do ##class(dc.IrisGeoMap.Folium).GetGeoDetails("Cambridge MA 02142")

Le résultat sera le suivant ::

image

  ********

5.4-Générer et marquer des emplacements sur une carte interactive en utilisant biblithèque Python Folium

Nous utiliserons la même bibliothèque Python Folium pour générer et marquer des emplacements sur une carte interactive, la fonction de script objet ci-dessous fera le travail souhaité :

ClassMethod MarkGeoDetails(addr As%String, filepath As%String) As%Status [ Language = python ]
{
    import folium
    from geopy.geocoders import Nominatim

    geolocator = Nominatim(user_agent="IrisGeoMap")
    #split address in order to mark on the map
    locs = addr.split(",")
    if len(locs) == 0:
    	print("Veuillez saisir l'adresse")
    elif len(locs) == 1:
    	location = geolocator.geocode(locs[0])
    	point = location.point
    	m = folium.Map(location=[point.latitude,point.longitude], tiles="OpenStreetMap", zoom_start=10)
    else:
    	m = folium.Map(location=[20,0], tiles="OpenStreetMap", zoom_start=3)

    for loc in locs:
    	try:
    		location = geolocator.geocode(loc)
    		point = location.point
    		folium.Marker(
	    			location=[point.latitude,point.longitude],
	    	  		popup=addr,
	    		).add_to(m)    		
    	except:
    		print("Impossible de trouver l'emplacement : ",loc)

    map_html = m._repr_html_()
    iframe = m.get_root()._repr_html_()
    fullHtml = """

        	    

        	         """
    fullHtml = fullHtml + iframe            
    fullHtml = fullHtml + """                                             
       	        
        	    
    """try:
    	f = open(filepath, "w")
    	f.write(fullHtml)
    	f.close()
    except:
    	print("Impossible d'écrire dans un fichier")
}

Connectez-vous au terminal IRIS et invoquez la fonction MarkGeoDetails

Nous invoquerons la fonction MarkGeoDetails() de la classe dc.IrisGeoMap.Folium.
La fonction nécessite deux paramètres :

  1. location/locations(Nous pouvons passer plusieurs lieux en ajoutant "," entre les deux)
  2. fichier HTML de trajet

Exécutons la commande suivante pour marquer Cambridge MA 02142, NY, Londres, UAE, Jeddah, Lahore, et Glasgow sur la carte et l'enregistrer en tant que fichier "irisgeomap_locations.html".

do ##class(dc.IrisGeoMap.Folium).MarkGeoDetails("Cambridge MA 02142,NY,London,UAE,Jeddah,Lahore,Glasgow","d:\irisgeomap_locations.html")

Le code ci-dessus génère le fichier HTML interactif suivant********:********

##image

  ********

5.5-Analyse de données à l'aide de la biblithèque Python Pandas

Nous devons installer la bibliothèque Pandas à l'aide de la commande irispip, puis nous pouvons utiliser le code ci-dessous pour visualiser les données.
******** ********

 

6-Résumé

Python intégré d'InterSystems (IEP) est une fonctionnalité puissante qui vous permet d'intégrer du code Python de manière transparente dans vos applications InterSystems. Grâce à IEP, vous pouvez exploiter les nombreuses bibliothèques et cadres disponibles en Python pour améliorer la fonctionnalité de vos applications InterSystems. Dans cet article, nous allons explorer les fonctionnalités et les avantages clés d'IEP.

IEP est mis en œuvre sous la forme d'un ensemble de bibliothèques qui vous permettent d'interagir avec des objets Python et d'exécuter du code Python à partir d'applications InterSystems. Il s'agit d'un moyen simple et efficace d'intégrer du code Python dans vos applications InterSystems, ce qui vous permet d'effectuer des analyses de données, de l'apprentissage automatique, du traitement du langage naturel et d'autres tâches qui peuvent être difficiles à mettre en œuvre dans ObjectScript d'InterSystems.

L'un des principaux avantages de l'utilisation d'IEP est qu'il permet de faire le lien entre les mondes de Python et d'InterSystems. Il est ainsi facile d'utiliser les points forts des deux langages pour créer des applications puissantes qui combinent le meilleur des deux mondes.

IEP permet également d'étendre les fonctionnalités de vos applications InterSystems en exploitant les capacités de Python. Cela signifie que vous pouvez tirer parti du grand nombre de bibliothèques et de cadres disponibles en Python pour effectuer des tâches qui pourraient être difficiles à mettre en œuvre dans ObjectScript d'InterSystems.

Python intégré d'InterSystems offre un moyen puissant d'étendre les fonctionnalités de vos applications InterSystems en exploitant les capacités de Python. En intégrant du code Python dans vos applications InterSystems, vous pouvez profiter du grand nombre de bibliothèques et de cadres disponibles dans Python pour effectuer des tâches complexes qui pourraient être difficiles à mettre en œuvre dans ObjectScript d'Intersystems.

Merci!

0
0 144
Article Guillaume Rongier · Mai 15, 2023 4m read

Salut à tous !  

Dans cet article, j'aimerais passer en revue les extensions de VS Code que j'utilise moi-même pour travailler avec InterSystems et qui rendent mon travail beaucoup plus pratique. Je suis certain que cet article sera utile à ceux qui commencent tout juste à apprendre les technologies d'InterSystems. Cependant, j'espère également que cet article pourra être utile aux développeurs expérimentés ayant de nombreuses années d'expérience et qu'il leur ouvrira de nouvelles possibilités lors de l'utilisation de VS Code pour le développement.

Je recommande à tous ceux qui travaillent avec InterSystems d'avoir ces extensions installées et, dans cet article, je montrerai comment utiliser certaines d'entre elles.

Vous pouvez en savoir plus sur la fonctionnalité et l'utilisation de chaque extension dans la section Extensions de VS Code, où vous pouvez également télécharger, mettre à jour et désinstaller des extensions :

 Après l'installation, des icônes d'extension apparaissent sur le côté ou en bas de l'éditeur de code.

Extensions obligatoires

Je crois qu'il est logique de commencer notre voyage avec ces extensions de base, sans lesquelles il est impossible de travailler avec InterSystems dans VS Code.

  • L'extension du gestionnaire de serveur d'InterSystems pour VS Code permet de spécifier les connexions au serveur.
  • L'extension ObjectScript d'InterSystems pour VS Code permet l'écriture et la compilation des fichiers de code.
  • L'extension du serveur de langage d'InterSystems pour VS Code permet la mise en œuvre d'un serveur de langage pour ObjectScript, offrant des fonctions de coloration, de complétion de code, d'évaluation de la qualité et bien plus encore.
  • Conjointement, ces extensions offrent aux développeurs un moyen rationalisé de créer, tester et déployer des applications complètes basées sur InterSystems.

    Extensions supplémentaires

    Outre les extensions de base nécessaires, VS Code propose un grand nombre d'autres extensions. Vous pouvez écrire du code sans elles, mais leur utilisation rend le développement plus efficace lorsque vous utilisez n'importe quelle pile technologique, y compris les technologies d'InterSystems. J'en décrirai quelques-unes qui me semblent incontournables.

  • L'extension Docker rend la gestion des projets dockerisés un peu plus facile. Vous pouvez générer automatiquement un fichier Docker pour les projets, exécuter des images et gérer les conteneurs actifs.  
  • Le pilote SQLTools for InterSystems IRIS et SqlTools - sont deux extensions très pratiques qui fonctionnent conjointement. En les utilisant, vous pouvez créer et exécuter les requêtes SQL de la base de données dans VS Code sans avoir à aller dans le portail de gestion et à effectuer des requêtes sql pour interagir avec le contenu des tableaux qui s'y trouvent.
  •  

    Aujourd'hui, il est difficile d'imaginer développer un projet sans utiliser le contrôle de version. Le plus souvent, il s'agit de Git, et le code Visual Studio a un support minimal dès sa sortie de la boîte. Mais si cela ne vous suffit pas, jetez un coup d'œil aux deux extensions suivantes : 

  • Git Graph - montre les branches et leur statut de manière schématique. Ceci est utile dans les situations où vous avez besoin de comprendre rapidement l'état des branches, par exemple lorsqu'elles fusionnent.
  • Git Lens - permet de voir l'historique des modifications apportées à la ligne surlignée et à son auteur.
  •  Il est indispensable au travail d'équipe !

  • EditorConfig - une extension pour améliorer l'apparence du code, elle nécessite l'écriture d'un fichier .editorconfig, dans lequel vous pouvez spécifier tous les paramètres de formatage du code. Il est important de noter que, par défaut, cette fonctionnalité peut être mise en œuvre par l'extension du serveur de langage InterSystems pour VS Code. Pour appliquer le formatage de code ObjectScript standard dans VS Code, vous devez utiliser une combinaison de touches : Windows - [Shift + Alt + F], Mac - [Shift + Option + F], Ubuntu - [Ctrl + Shift + I]. Mais en utilisant le fichier .editorconfig, vous pouvez spécifier votre propre formatage de code pour différents fichiers au sein du projet.
  • Dans cet article, je n'ai abordé que les extensions utilisées par moi-même. Je vous serais reconnaissante de prendre le temps d'écrire dans les commentaires ce qui peut encore être utilisé pour rendre le développement plus pratique. Cet article n'en sera que plus utile !

    0
    0 297