accéder à la publication Sylvain Guilbaud · Sept 28 Bonjour @Jean-Charles Cano, Stream n'est pas une méthode mais une propriété ; aussi, tout devrait aller mieux après avoir remplacé cette ligne : set esc = ..Adapter.PutStream(fileName, pRequest.Stream()) par celle-ci : set esc = ..Adapter.PutStream(fileName, pRequest.Stream)
accéder à la publication Sylvain Guilbaud · Sept 26 Je suis bien d'accord @Iryna Mykhailova Le site InterSystems Learning étant déjà disponible en français, peut-être verrons-nous prochainement des contenus de plus en plus nombreux de formations dans la langue de Molière et de Prévert.
accéder à la publication Sylvain Guilbaud · Sept 26 Réponse de @Ashok Kumar Bonjour @Muhammad Waseem Vous pouvez peut-être essayer d'extraire la ressource patient du bundle ou l'utiliser si c'est déjà une ressource. Chargez la classe du modèle patient FHIR HS.FHIR.DTL.vR4.Model.Resource.Patient avec la ressource extraite. Ensuite, vous pouvez convertir la date de naissance et valider l'âge. Vous pouvez utiliser la même logique dans votre code DTL dans un processus FHIR entre le service FHIR (HS.FHIRServer.Interop.Service) et l'opération FHIR (HS.FHIRServer.Interop.Operation). ClassMethod VaidatePatientResource(patientResourceStreram As %Stream.Object) { #dim patient As HS.FHIR.DTL.vR4.Model.Resource.Patient try { set patient = ##class(HS.FHIR.DTL.vR4.Model.Resource.Patient).FromJSON(patientResourceStreram) Set age = $horolog - $ZdateH(patient.birthDate,3)\360 if age<18 $$$ThrowStatus($$$ERROR($$$GeneralError, "Age is less than 18")) } catch ex { w ex.DisplayString() } }
accéder à la publication Sylvain Guilbaud · Sept 25 15 applications de réelle qualité 😀 Merci à tous les participants pour leur implication et leurs idées.
accéder à la publication Sylvain Guilbaud · Sept 22 Bonjour @Julia Pertin peux-tu me donner plus de détails sur l'erreur rencontrée ? Vérifies-bien si tu recrées une production from scratch, en ajoutant service-process-operation, de conserver les noms les BS-BP-BO identiques aux noms des 3 classes EP.service.replication, EP.process.replication et EP.operation.replication, et qu'ils sont bien reliés entre eux.
accéder à la publication Sylvain Guilbaud · Sept 20 L'intérêt du Ens.StreamContainer est de dépasser la limite des 3,6Mo du type %String. Exemple d'une trace avec un flux json de 5,79 Mo (stream size: 6081494) pour 100000 enregistrements :
accéder à la publication Sylvain Guilbaud · Sept 20 Le code de la Business Opération : Class EP.operation.replication Extends Ens.BusinessOperation { Property Adapter As Ens.OutboundAdapter; Parameter ADAPTER = "Ens.OutboundAdapter"; Parameter INVOCATION = "Queue"; Method sync(pRequest As Ens.StreamContainer, Output pResponse As Ens.StringContainer) As %Status { set pResponse = ##class(Ens.StringContainer).%New() set json = [].%FromJSON(pRequest.Stream) set array = json.%GetIterator() while array.%GetNext(.key,.value) { $$$TRACE("Data:"_value.%ToJSON()) set a = ##class(data.client2).%New() set sc = a.%JSONImport(value) if 'sc { $$$LOGERROR("ERROR while importing:"_$system.Status.GetErrorText(sc)) } else { set sc = a.%Save() } } set pResponse.StringValue = key _" records inserted" return sc } XData MessageMap { <MapItems> <MapItem MessageType="Ens.StreamContainer"> <Method>sync</Method> </MapItem> </MapItems> } }
accéder à la publication Sylvain Guilbaud · Sept 20 Le code du Business Process Class EP.process.replication Extends Ens.BusinessProcess [ ClassType = persistent, ProcedureBlock ] { Property Server As %String [ InitialExpression = "host.docker.internal" ]; Property Port As %Integer [ InitialExpression = 12773 ]; Property classname As %String [ InitialExpression = "data.client" ]; Parameter SETTINGS = "Server:target,Port:target,classname:target"; Method OnRequest(pRequest As Ens.Request, Output pResponse As Ens.StringContainer) As %Status { set sc = $$$OK set tHttpRequest = ##class(%Net.HttpRequest).%New() set pContainer = ##class(Ens.StreamContainer).%New() set stream = ##class(%Stream.GlobalCharacter).%New() set tHttpRequest.Server = ..Server set tHttpRequest.Port = ..Port set location = "/common/list/" _ ..classname _ "/json" set tHttpRequest.ContentType = "application/json" set tHttpRequest.Timeout = 900 set tSC = tHttpRequest.Get(location) if $ISOBJECT(tHttpRequest.HttpResponse) { Set jsonObject = [].%FromJSON(tHttpRequest.HttpResponse.Data) Do jsonObject.%ToJSON(.stream) set pContainer.Stream = stream $$$TRACE("stream size:"_stream.Size) $$$TRACE("stream data:"_stream.Read(1000)) set sc = ..SendRequestSync("EP.operation.replication",pContainer,.pResponse) } return sc } Storage Default { <Data name="replicationDefaultData"> <Subscript>"replication"</Subscript> <Value name="1"> <Value>Server</Value> </Value> <Value name="2"> <Value>Port</Value> </Value> <Value name="3"> <Value>classname</Value> </Value> </Data> <DefaultData>replicationDefaultData</DefaultData> <Type>%Storage.Persistent</Type> } }
accéder à la publication Sylvain Guilbaud · Sept 20 Le code du Business Service : Class EP.service.replication Extends Ens.BusinessService { Property Adapter As Ens.InboundAdapter; Parameter ADAPTER = "Ens.InboundAdapter"; Property TargetConfigNames As %String(MAXLEN = 1000); Property sync As %Boolean [ InitialExpression = 1 ]; Parameter SETTINGS = "sync:Advanced,TargetConfigNames:Basic:selector?multiSelect=1&context={Ens.ContextSearch/ProductionItems?targets=1&productionName=@productionId}"; Method OnProcessInput(pInput As %RegisteredObject, Output pResponse As Ens.StringResponse) As %Status { set tSC = $$$OK for iTarget=1:1:$L(..TargetConfigNames, ",") { set tOneTarget=$ZStrip($P(..TargetConfigNames,",",iTarget),"<>W") Continue:""=tOneTarget $$$TRACE("The target '"_tOneTarget_"' will be called "_$SELECT(..sync=1:"synchronously",..sync=0:"synchronously")) if ..sync { set tSC1=..SendRequestSync(tOneTarget,pInput,.pResponse) Set:$$$ISERR(tSC1) tSC=$$$ADDSC(tSC,tSC1) } else { set tSC1=..SendRequestAsync(tOneTarget,pInput) Set:$$$ISERR(tSC1) tSC=$$$ADDSC(tSC,tSC1) } } return tSC } /// Return an array of connections for drawing lines on the config diagram ClassMethod OnGetConnections(Output pArray As %String, pItem As Ens.Config.Item) { Do ##super(.pArray,pItem) If pItem.GetModifiedSetting("TargetConfigNames",.tValue) { For i=1:1:$L(tValue,",") { Set tOne=$ZStrip($P(tValue,",",i),"<>W") Continue:""=tOne Set pArray(tOne)="" } } } }
accéder à la publication Sylvain Guilbaud · Sept 20 Pour illustrer avec un exemple concret, j'ai développé un flux qui devrait t'aider à réaliser ce que tu veux : Trace avec appel asynchrone : Trace avec appel synchrone : Avec la réponse qui remonte bien jusqu'au Business Service :
accéder à la publication Sylvain Guilbaud · Sept 20 Bonjour @Julia Pertin, si j'ai bien compris ton besoin, pour régler ton problème qui consiste à éviter de récupérer plusieurs fois le même flux json, ton Business Service doit servir uniquement à appeler un Business Process, qui lui va se charger de récupérer le flux json pour le passer à une Business Operation. Dans le cas où ton Business Service appelle le Business Process de manière synchrone, il attendra bien la réponse avant de s'exécuter à nouveau.Dans le cas contraire, c'est à dire si le Business Process est appelé de manière asynchrone, le Business Service fera un nouvel appel à chaque atteinte du temps prévu par le paramètre "INTERVALLE ENTRE APPELS".
accéder à la publication Sylvain Guilbaud · Sept 15 Réponse de @Dmitry Maslennikov Pour quelques versions déjà, Caché et IRIS prennent déjà en charge OAuth2 dès le départ. Regardez la documentation. Cela dépend de votre architecture, vous pouvez utiliser cette méthode ou utiliser n'importe quel fournisseur d'identité externe comme keycloack. Et je pense qu'IAM peut également vous aider.
accéder à la publication Sylvain Guilbaud · Sept 15 Réponse de @Rob Tweed Nous avons deux produits Open Source qui prendront en charge les JWT pour vous de la manière correspondant à ce que vous demandez (c'est-à-dire les services REST avec IRIS) : - QEWD, si vous souhaitez tout implémenter en back-end dans Node.js / JavaScript - mgweb-server si vous souhaitez utiliser la logique ObjectScript pour votre logique back-end Pour QEWD et IRIS, voir : https://github.com/robtweed/qewd-starter-kit-iris-networked En particulier pour les services REST, voir : https://github.com/robtweed/qewd-starter-kit-iris-networked/blob/master/... et plus précisément cette section: https://github.com/robtweed/qewd-starter-kit-iris-networked/blob/master/... Pour le serveur mgweb, voir : https://github.com/robtweed/mgweb-server spécifiquement utilisé avec IRIS : https://github.com/robtweed/mgweb-server/blob/master/IRIS.md et dans ce document, cette section sur les JWT : https://github.com/robtweed/mgweb-server/blob/master/IRIS.md#using-json-... Rob
accéder à la publication Sylvain Guilbaud · Sept 13 Hâte de voir quels sont les gagnants des prix InterSystems 😀
accéder à la publication Sylvain Guilbaud · Sept 13 Je t'en prie, mon cher @Robert Cemper ; merci à toi de continuer de publier et d'aider la communauté à un rythme aussi soutenu.
accéder à la publication Sylvain Guilbaud · Sept 12 @Luis Angel Pérez Ramos propose une autre solution, hors Embedded Python : Eh bien, si votre instance IRIS ne prend pas en charge Embedded Python, vous pouvez procéder comme suit (si vous utilisez un serveur Linux) : Installez une application comme ImageMagick sur votre serveur À partir de votre opération commerciale, utilisez la fonction $ZF(-100) pour exécuter sur le serveur la commande magique permettant de convertir le PDG en JPG, quelque chose comme : $ZF(-100,"","magick","\usr\image.pdf","\usr\image.jpg") Peut-être que cela prend un certain temps, vous pouvez attendre la fin de l'exécution ou simplement créer un service métier pour obtenir tous les nouveaux fichiers PDF.
accéder à la publication Sylvain Guilbaud · Sept 12 Dans ce cas, @Ben Spead propose d'installer Python sur le serveur avec la bibliothèque que l'on souhaitez utiliser et d'appeler le script Python via $zf(-100). Plus tard, lorsque d'une mise à niveau de l'environnement, il sera possible de passer directement à l’utilisation de Embedded Python.
accéder à la publication Sylvain Guilbaud · Sept 12 Malheureusement, l'environnement de @Gilberto Alves n'est pas prêt à utiliser Embedded Python.
accéder à la publication Sylvain Guilbaud · Sept 12 @Ben Spead a donné une première réponse en proposant d'utiliser Embedded Python : Cela ressemble à un exemple classique d'exploitation de Python intégré dans IRIS pour utiliser le très grand nombre de bibliothèques Python qui font à peu près n'importe quoi :) Voici un article que j'ai trouvé lors d'une recherche rapide sur Google sur la façon de procéder en Python : https://www.geeksforgeeks.org/convert-pdf-to-image-using-python/ Vous pouvez simplement exploiter les capacités Python d'InterSystems IRIS pour utiliser la façon dont ce problème a été résolu en Python !
accéder à la publication Sylvain Guilbaud · Sept 12 Oui, le GRANT on SCHEMA ou GRANT on * simplifie clairement la chose 😀Cela fait partie du standard SQL mais on n'y pense pas d'emblée.