Merci!
Ce post m'a évité de perdre beaucoup de temps.
J'ai commencé à modifier les fichiers docker-compose sur mes différents repo publiques.
- Se connecter pour publier des commentaires
Merci!
Ce post m'a évité de perdre beaucoup de temps.
J'ai commencé à modifier les fichiers docker-compose sur mes différents repo publiques.
Je vous souhaite un excellent salon!
Excellent!
@Damiano Porrovecchio : Je pense que tu as testé et même modifié ce module.
N'hésite pas à laisser un feedback ![]()
Une super première journée avec la visite de Seattle guidée par @Irène Mykhailova
suivie d'une réception.
Cette après-midi, nous commençons les conférences techniques "AutoML" et la suivante "The futur of HealthShare in the cloud".
Let's go !
Félicitations pour ta certification @Irène Mykhailova !
Super première journée de conférence.
Au niveau technique ma préférée a été AutoML. Très facile a prendre en main, même sans connaissance en machine learning.
Une belle dernière journée, l'après-midi a été rythmée par une présentation CI/CD par l'équipe Benelux, des discussions avec des intervenants de différents pays sur des sujets techniques ainsi que UCR. Aussi c'était l'occasion d'avoir un premier contact avec Intersystems Italia.
Nous avons finalement passé cette dernière soirée dans la ville.
Au plaisir de vous revoir lors d'un prochain événement !
Merci pour cet article @Robert Cemper
Ce sera j'en suis sûr très utile!
Merci pour ces explications très claires!
Tout juste reçu avec les points du Global Master!
Ce sera parfait pour coder lors des soirées les plus fraîches.
Hahaha.
Oui, j'en avais déjà un, mais on me le prend souvent à la maison parce qu'on le trouve confortable ![]()
Un deuxième ne sera pas de trop ![]()
Félicitations et merci à tous pour vos contributions !!
J'ai hâte de vous y retrouver pour la seconde année consécutive!
Bonjour @lilian taroua,
Quel type de documentation cherchez-vous?
La documentation technique officiel est effectivement en anglais et disponible en ligne ici. Elle peut aussi être téléchargée en version PDF via ce lien. Sur le site officiel FR, vous pourrez trouver des informations relatives aux différents produits. Des formations sur IRIS en français sont également possible à ma connaissance.
Bonjour @Franck Hanotin ,
Le plus simple est de passer par une custom class query, je vais vous mettre un exemple avec vos données
dans un prochain commentaire .
Voilà @Franck Hanotin ,
Vous pouvez créer une custom class query comme ceci :
Class dc.Frank
{
Query QueryAFO() As%Query(ROWSPEC = "key1:%String,key2:%String,key3:%String,key4:%String,key5:%String,key6:%String,datavalue:%String") [ SqlProc ]
{
}
ClassMethod QueryAFOExecute(ByRef qHandle As%Binary) As%Status
{
Set qHandle("node") = $Name(^AFO)
Quit$$$OK
}
ClassMethod QueryAFOFetch(
ByRef qHandle As%Binary,
ByRef Row As%List,
ByRef AtEnd As%Boolean) As%Status [ PlaceAfter = QueryAFOExecute ]
{
Set sc = $$$OKSet qHandle("node") = $Query(@qHandle("node"), 1, data)
If qHandle("node") = ""Set Row = "", AtEnd = $$$YESQuit$$$OK; alimente les champs key x sur base des subscripts de la globalFor i=1:1:$QLength(qHandle("node")) Set$List(Row, i) = $QSubscript(qHandle("node"), i)
If i < 6 { ; si nous n'avons pas 6 subscripts, on alimente le reste avec une chaine videForj = i+1:1:6Set$List(Row, j) = ""
}
Set$List(Row, 7) = data, AtEnd = $$$NOQuit sc
}
ClassMethod QueryAFOClose(ByRef qHandle As%Binary) As%Status [ PlaceAfter = QueryAFOExecute ]
{
Kill qHandle Quit$$$OK
}
/// juste pour quelques data de testsClassMethodset()
{
s^AFO("Site","Ville")="66722,3743"s^AFO("Site","Ville","111BB","OBT")=",MMM,XXX,"s^AFO("Site","Ville","111OW","OBT")=",XXX,MMM,"s^AFO("Site","Ville","AANVRBIBS","zzz") = "1^^1"s^AFO("Site","Ville","AANVRBIBS","zzz","*","dut") = "*afhalen waar gevonden"s^AFO("Site","Ville","AANVRBIBS","zzz","*","eng") = "*Pickup where found"s^AFO("Site","Ville","AANVRBIBS","zzz","*","fre") = "*Lieu où trouvé"
}
}
Vous pourrez ensuite facilement l'exploiter avec la requête suivante :
select *
from dc.Frank_QueryAFO()
En mode terminal, vous pouvez aussi simplement utiliser cette ligne pour afficher les résultats :
Do##class(dc.Frank).QueryAFOFunc().%Display()De mon coté, j'ai effectué le test sur IRIS 2023.2, il ne devrait pas y avoir d'incompatibilité, mais si toutefois vous constatez un problème n'hésitez pas à répondre avec le message d'erreur.
Ravi que cette proposition ait pu vous aider @Franck Hanotin
Merci pour le partage de cette astuce @Sylvain Guilbaud ,
Il y a quelques années j'ai du écrire un script pour faire la même chose et j'ai effectué un select sur INFORMATION_SCHEMA et des insert dans Security.SQLPrivileges. C'était assez fastidieux. J'utiliserai cette technique si je dois mettre le script à jour.
hey @Alexandre Lucas ,
Tu en as déjà entendu parlé ?
Bonjour,
ISC devrait conserver une copie du repository lors d'une nouvelle release sur OEX (peut être que c'est déjà le cas).
Si un package devient orphelin, il me parait difficile de remettre le package entre les mains d'un autre membre de communauté si nous n'avons pas cette copie.
Le compte GitHub pourrait être fermé, le repository supprimé, ce qui rendrait les choses compliquées.
Bien sûr, nous pourrions toujours tenter de le reconstruire à partir du package ZPM, mais ça demanderait du temps en reverse engineering.
Au sujet de la suppression de package.
Je ne suis pas contre cette idée si elle est motivée.
Il m'est déjà arrivé de supprimer un package, car une nouvelle fonctionalité de IRIS le rendait obsolète.
Toutefois, j'ai laissé le repository GitHub public pour éviter la perte de connaissance.
Pour ces cas là, peut être devrions-nous disposer d'une notion "archived package".
Tout le monde ne travaille pas sur les dernières versions de IRIS, il pourrait donc y avoir un intérêt.
Bonjour @Julia Pertin ,
Pouvez-vous nous donner quelques détails sur l'input?
Je vois bien dans le code le tHttpRequest, mais dans l'état il ne sert à rien.
Est-ce que le JSON devrait être dans le pInput?
Comment le call est-il fait vers ce business service?
Merci.
Bonjour @Cyril Grosjean
En ce qui concerne la configuration de l'application Web, vous pouvez exporter la configuration dans un fichier xml avec la classe Security.Applications:
zn"%SYS"Set sc = ##class(Security.Applications).Export("c:\export\webapp.xml",,"/votreweb/application")Pour l'import, sur l'autre serveur, il suffira d'utiliser la méthode Import
zn"%SYS"Set sc = ##class(Security.Applications).Import("c:\export\webapp.xml")Pour le code, c'est autre chose. Une solution serait de créer un projet à partir du Studio (fichier -> nouveau projet), faites ensuite clique droit "ajouter au projet" pour tous les fichiers sources (CSP ou classes) que vous devez récupérer.
Sauvegarder le projet et aller ensuite dans "Outils -> Export". Vous aurez la possibilité d'exporter tout le projet en un seul XML. Il suffira de faire "Outils -> Import local" depuis le studio de l'autre serveur.
Il y a d'autres possibilités en utilisant la classe $SYSTEM.OBJ.
Lorenzo.
Pour exporter la configuration ça doit être se faire via les lignes de commandes que je vous ai communiqué dans le premier message. Pour le exporter le code, en effetça peut être effectué depuis le portail.
Allez dans "Explorateur système -> classes".
L'interface vous permettra de sélectionner les classes (également les routines et globals) et les exporter\importer:
.png)
A ma connaissance, le portail d'administration ne permet pas d'exporter les pages CSP. Si vous en avez, il faut les copier directement à partir du disque.
Bonsoir @Jean-Charles.Cano ,
Avez-vous déjà essayé avec runw? Voici un exemple de structure de la commande pour démarrer une classmethod:
iris runw INSTANCENAME ##class(Package.Class).ClassMethod(\"argument\") NAMESPACEL'exe iris se trouve dans le sous répertoire bin de l'instance IRIS.
pour démarrer un terminal en ligne de commande utilisez irissession:
irissession INSTANCENAME -U NAMESPACE
# ex:
irissession IRIS -U USER
# il est également possible de démarrer un programme, ex:
irissession IRIS -U %SYS ^%SS
Bonjour @Julia Pertin ,
Voici un exemple avec votre xml:
La classe de test avec votre XML (par facilité pour je l'ai mis dans un XData):
Class demo.correlate.Test
{
/// Do ##class(demo.correlate.Test).Test() As %StatusClassMethod Test()
{
#dim data As demo.correlate.structure.Data
#dim tableName As demo.correlate.structure.TableName
Set xmlTest = ##class(%Dictionary.CompiledXData).%OpenId($classname()_"||XMLTest",,.sc).Data
Quit:$$$ISERR(sc) sc
Set reader=##class(%XML.Reader).%New()
Do reader.Correlate("data","demo.correlate.structure.Data")
Set sc = reader.OpenStream(.xmlTest)
Do reader.Next(.data)
Set key = ""Set tableName = data.tablename.GetNext(.key)
While key '= "" {
Write !,"+ table ", tableName.Table
Set tableName = data.tablename.GetNext(.key)
}
Quit$$$OK
}
XData XMLTest
{
<?xml version="1.0" encoding="UTF-8"?>
<data>
<tablename>
<Table>Erp.BRIEFS</Table>
<Action>HAjoute</Action>
<CleIris>IDBRIEFS</CleIris>
<nIdentifiant>2</nIdentifiant>
<IdIris>137</IdIris>
<Contenu></Contenu>
</tablename>
<tablename>
<Table>Erp.COMMANDES</Table>
<Action>HAjoute</Action>
<CleIris>IDCOMMANDES</CleIris>
<nIdentifiant>5</nIdentifiant>
<IdIris>138</IdIris>
<Contenu></Contenu>
</tablename>
</data>
}
}
Ensuite les deux classes correspondantes à la structure du xml (Data et TableName):
Class demo.correlate.structure.Data Extends (%RegisteredObject, %XML.Adaptor)
{
Parameter XMLNAME = "data";Property tablename As list Of demo.correlate.structure.TableName(XMLPROJECTION = "ELEMENT");
}
Class demo.correlate.structure.TableName Extends (%RegisteredObject, %XML.Adaptor)
{
Property Table As%String;Property Action As%String;Property CleIris As%String;Property nIdentifiant As%String;Property IdIris As%String;Property Contenu As%String;
}
En exécutant la méthode Test dans le terminal, elle affichera le contenu de property "Table":
USER>Do##class(demo.correlate.Test).Test()
+ table Erp.BRIEFS
+ table Erp.COMMANDESJ'espère que cet exemple vous aidera dans votre developpement.
Bonne journée.
Re @Julia Pertin ,
Il manque %XML.Adaptor sur replic.msg.XMLStructure, essayez comme ceci :
Class replic.msg.XMLStructure Extends (%Persistent, %XML.Adaptor)
{
Parameter XMLNAME = "data";Property tablename As list Of replic.msg.XML(XMLPROJECTION = "ELEMENT");
}Ha no messages ce sont croisés.
Parfait!
Content que ce soit réglé
Re,
Attention l'utilisation de CDATA doit être :
<![CDATA[<IDBRIEFS>2</IDBRIEFS>
<Numero>8</Numero>]]>Dans ce cas, il faut modifier le type de la property "Contenu" en %Stream.GlobalCharacter:
Class demo.correlate.structure.TableName Extends (%RegisteredObject, %XML.Adaptor)
{
Property Table As%String;Property Action As%String;Property CleIris As%String;Property nIdentifiant As%String;Property IdIris As%String;Property Contenu As%Stream.GlobalCharacter;
}
Class demo.correlate.Test
{
/// Do ##class(demo.correlate.Test).Test()ClassMethod Test()
{
#dim data As demo.correlate.structure.Data
#dim tableName As demo.correlate.structure.TableName
Set xmlTest = ##class(%Dictionary.CompiledXData).%OpenId($classname()_"||XMLTest",,.sc).Data
If$$$ISERR(sc) Do$SYSTEM.Status.DisplayError(sc) Quit sc
Set reader=##class(%XML.Reader).%New()
Do reader.Correlate("data","demo.correlate.structure.Data")
Set sc = reader.OpenStream(.xmlTest)
Do reader.Next(.data)
Set key = ""Set tableName = data.tablename.GetNext(.key)
While key '= "" {
Write !,"+ table: ", tableName.Table
Write !,"+ Contenu: ", tableName.Contenu.Read()
Set tableName = data.tablename.GetNext(.key)
}
Quit$$$OK
}
XData XMLTest
{
<?xml version="1.0" encoding="UTF-8"?>
<data>
<tablename>
<Table>Erp.BRIEFS</Table>
<Action>HAjoute</Action>
<CleIris>IDBRIEFS</CleIris>
<nIdentifiant>2</nIdentifiant>
<IdIris>137</IdIris>
<Contenu>
<![CDATA[<IDBRIEFS>2</IDBRIEFS>
<Numero>8</Numero>]]>
</Contenu>
</tablename>
<tablename>
<Table>Erp.COMMANDES</Table>
<Action>HAjoute</Action>
<CleIris>IDCOMMANDES</CleIris>
<nIdentifiant>5</nIdentifiant>
<IdIris>138</IdIris>
<Contenu>
<![CDATA[<IDCOMMANDES>5</IDCOMMANDES>
<CLISId>4399</CLISId>]]>
</Contenu>
</tablename>
</data>
}
}
A l'exécution de la méthode test, vous aurez
USER>Do##class(demo.correlate.Test).Test()
+ table: Erp.BRIEFS
+ Contenu:
<IDBRIEFS>2</IDBRIEFS>
<Numero>8</Numero>
+ table: Erp.COMMANDES
+ Contenu:
<IDCOMMANDES>5</IDCOMMANDES>
<CLISId>4399</CLISId>Vous pouvez donc récupérer toutes les occurrences de "Contenu" dans des streams séparés et faire d'autres correlate :)
Bonjour @Cyril Grosjean ,
Je devrais pouvoir vous fournir quelques informations pouvant vous être utile.
Dans ma boîte, entre d'autres choses, je m'occupe de l'écriture de scripts de deploy pour nos environnements internes.
La solution que je pense la plus simple est d'écrire une classe (ou une routine) qui sera votre script principal pour toutes les actions à effectuer.
Le tuto que vous avez suivi, n'est pas vraiment adapté. Il y a quelques années, je l'ai testé par curiosité, mais c'est vraiment pour faire de l'émulation terminal.
Voici un exemple de classe qui se positionne sur un namespace, charge et compile un répertoire:
Class dc.DeployDemo
{
ClassMethod deploy(
sourceDirectory As%String,
targetNameSpace As%String)
{
Set startNameSpace = $NamespaceWrite !, $ZDateTime($Horolog, 3, 1) _ " Start deploy"; L'utilisation du new $namespace permet au système ; de revenir automatiquement sur le namspace d'origine en quittant la méthodeNew$NamespaceSet$Namespace = targetNameSpace
Write !, $ZDateTime($Horolog, 3, 1) _ " Switch to namespace "_$NamespaceWrite !, $ZDateTime($Horolog, 3, 1) _ " Load and compile directory " _ sourceDirectory
; le 4ème argument permet de faire un chargement récursif (inclusion des sous répertoires)Set sc = $SYSTEM.OBJ.LoadDir(sourceDirectory, "ck", , 1)
Set msgStatus = $Select($$$ISERR(sc):$SYSTEM.Status.GetOneErrorText(sc),1:"OK")
Write !, $ZDateTime($Horolog, 3, 1) _ " Status " _ msgStatus
Quit
}
}
Préparer ensuite un fichier texte contenant le code à exécuter (pour l'exemple le fichier texte est c:\dev\script.txt):
Do##class(dc.DeployDemo).deploy("c:\src\cls","namespace")
Haltdès que le fichier est prêt, vous pouvez utiliser irissession et y injecter les commandes:
irissession IRIS -U USER < c:\dev\script.txtCeci reste qu'un exemple assez basic, n'hésitez pas à me contacter sur Discord, nous pourrons échanger verbalement plus rapidement sur le sujet si vous le souhaitez.
Lorenzo.
Nickel, content que ça aide !
Bonsoir,
Comme l'a expliqué @Guillaume Rongier , modifier l'ordre de l'héritage peut apporter une solution, mais dans votre cas je me demande si ça ne va pas apporter d'autres problèmes.
Si c'est le cas, il faudrait que la classe "Common" n'hérite de rien du tout.
Il faut ensuite créer les méthodes avec les keywords [codemode = objectgenerator et ForceGenerate].
Cela permettra d'injecter le code dans les sous classe de AuditCommons
Par exemple, la méthode SendRequestSync pourrait ressembler à cela :
Class XXXX.Outils.BS.AuditCommons
{
..
Method SendRequestSync(pTargetDispatchName As%String, pRequest As%Library.Persistent, ByRef pResponse As%Library.Persistent, pTimeout As%Numeric = -1, pDescription As%String = "") As%Status [ CodeMode = objectgenerator, ForceGenerate ]
{
; Le code ne peut être généré que dans les sous classesIf%class.Name = "XXXX.Outils.BS.AuditCommons"Quit$$$OKDo%code.WriteLine($Char(9) _ "if ..asynchronous quit ..SendRequestAsync(pTargetDispatchName, pRequest, pDescription)")
Do%code.WriteLine($Char(9) _ "set pResponse = """"")
Do%code.WriteLine($Char(9) _ "set sc = ..initAudit(pRequest) quit:'sc sc")
Do%code.WriteLine($Char(9) _ "set req = ..setReq(pRequest, .sc) quit:'sc sc")
Do%code.WriteLine($Char(9) _ "quit ##super(pTargetDispatchName, req, .pResponse, .pTimeout, pDescription)")
Quit$$$OK
}Je vais tenter de vous fournir un exemple plus complet sur base de la classe common que vous avez envoyé.