It's already available in English! ![]()
https://community.intersystems.com/post/using-regular-expressions-cach%C3%A9
This here is our Spanish version of the great article by Michael Brosdorf
- Inicie sesión para enviar comentarios
It's already available in English! ![]()
https://community.intersystems.com/post/using-regular-expressions-cach%C3%A9
This here is our Spanish version of the great article by Michael Brosdorf
Perfecto, gracias por compartirlo!
Hola Yunier,
El componente IAM (InterSystems API Manager) actualmente sólo está disponible como imagen Docker.
Puedes intentar configurar Docker en tu Windows, o instalar IAM en otra máquina (física o virtual) sobre la que puedas hacer la instalación de Docker.
Los puertos por defecto de IRIS son 52773 (web) y 51773 (tcp superport).
Cuando ejecutas el contenedor Docker puedes elegir cómo exponer estos puertos en tu máquina local para que puedas acceder.
Por ejemplo, si quieres utilizar los puertos 9100 y 9101 que comentas puedes hacer:
docker run --name iris -p 9100:52773 -p 9101:51773 store/intersystems/iris-community:2019.4.0.379.0
De esa forma, tendrías disponible el Portal de Gestión en http://localhost:9100/csp/sys/UtilHome.csp
Puedes echar un vistazo a la documentación o al Container Bootcamp que se hizo para el Global Summit.
Hola Luis,
Tal vez tengas el asistente de reglas mal configurado para este caso. ¿Es un enrutador HL7?
¿Nos puedes pasar la definición de la regla del enrutador (la clase) que te está causando problemas para poder echarle un vistazo?
Hola Javier! Ya he visto que te han contestado en el developer community ![]()
Por lo que preguntas parece que lo que necesitas es ejecutar los tests automáticos, convertir el resultado a JUnit e interpretarlo en Jenkins.
Como te ha dicho Timothy, échale un ojo a JUnitOutput. Te servirá para exportar los resultados de un %UnitTest a formato JUnit.
https://github.com/intersystems-community/zpm/blob/master/src/cls/_ZPM/…
Por si te sirve de "inspiración", te paso un ejemplo (anticuado - habría que adaptarlo), pero que en esencia al final hacía algo parecido a lo que buscas:
https://github.com/albertoft/widgets-direct/blob/master/WidgetsDirect/J…
Genial, muy útil!
Hola Uthman. La clase %Net.Remote.Java.JDBCGateway es una clase interna que está disponible en IRIS y Ensemble 2018.
No podrás llamarla en Ensemble 2016. Tal vez la mejor opción es que te plantees un upgrade de versión.
En cualquier caso, si necesitas que se revise tu caso en concreto lo mejor es que abras un caso a soporte WRC para estudiarlo.
Hola Jose,
No sé exactamente con qué versión estás probando pero estás utilizando %ZEN.proxyObject en lugar de las funcionalidades que incorpora IRIS para trabajar con JSON.
Échale un vistazo a Using JSON.
Por ejemplo,
USER>set json={ "participant": [ {"actor": { "reference": "Practitioner/example" } }, { "actor": { "reference": "Location/1"} } ] }
USER>write json.participant.%Get(0).actor.reference
Practitioner/example
USER>write json.participant.%Get(1).actor.reference
Location/1
Hola de nuevo José,
En la versión 2018 tienes algunas de esas funcionalidades disponible, mira la documentación aquí: https://cedocs.intersystems.com/latest/csp/docbook/Doc.View.cls?KEY=GJSON_preface
Intenta utilizar los %DynamicObjects en lugar de %ZEN.proxyObject.
En todo caso, si sólo puedes usar %ZEN.proxyObject y encuentras un problema, siempre puedes abrir un caso de soporte WRC para que investigarlo en detalle.
Hola de nuevo,
No entiendo muy bien cuál es el objetivo de lo que estás intentando hacer.
¿Estás intentando construir un objeto participant con dos actors para después obtener su representación JSON y poder enviarlo a algún sitio?
En la versión 2018, puedes construir la jerarquía de objetos que necesites y después transformarla tú mismo a un %DynamicObject con la estructura que quieras utilizando. Mira Creating and Modifying Dynamic Entities.
En IRIS / Health Connect además tendrías la posibilidad de %JSON.Adaptor que es mucho más cómodo.
¿Has recibido esa cadena JSON y estás intentando pasearla a un objeto?
Puedes convertir la cadena JSON a un %DynamicObject y acceder a todos las propiedades (e.g. arrays, objetos, etc.) en forma de objetos para poder trabajar con ellos como prefieras. Mira Converting Dynamic Entities to and from JSON
De todas formas, si no estás familiarizado con estas clases o incluso necesitas que algún especialista se conecte contigo y te echemos una mano no dudes por favor en abrir un caso de soporte WRC para que te podamos ayudar con más detalle.
Hola Kurro,
¿En qué versión lo estás probando? Me imagino que no puedes utilizar %JSON.Adaptor.
En cualquier caso, lo acabo de probar en un irishealth-community:2020.3.0.221.0 y parece que funciona:
Class MyMsg.PartialJson Extends Ens.Response
{
Property "ext_customer_id" As %String(MAXLEN = 1024);
Property "customer_name" As %String(MAXLEN = 1024);
Property "customer_surname_1" As %String(MAXLEN = 1024);
Property "customer_surname_2" As %String(MAXLEN = 1024);
Property "passport_id" As %String(MAXLEN = 250);
Property dob As %String(MAXLEN = 20);
Property sex As %String(MAXLEN = 10);
Property email As %String(MAXLEN = 1024);
Property active As %Boolean;
ClassMethod Test()
{
set file = ##class(%Stream.FileCharacter).%New()
set file.Filename = "/test/data.json"
set data = file.Read()
set objJson = ##CLASS(%DynamicObject).%FromJSON(data)
set jsonReturnValue = objJson.returnValue.data.%ToJSON()
write !!,"** jsonReturnValue:",!,jsonReturnValue
set sc = ##class(%ZEN.Auxiliary.jsonProvider).%ConvertJSONToObject(jsonReturnValue, "MyMsg.PartialJson", .pResponse)
write !!,"** %ConvertJSONToObject: ",!,sc
write !!,"** Converted object:",!
zw pResponse
}
Y el resultado de llamar al método de prueba:
USER>do ##class(MyMsg.PartialJson).Test()
** jsonReturnValue:
{"ext_customer_id":"123456789","customer_name":"FRANCISCO","customer_surname_1":"LOPEZ","customer_surname_2":"DE LAS HERAS","passport_id":"123456ZZZ","dob":"1972-02-01","sex":"M","email":"kurro.lopez@gmail.com","active":true}
** %ConvertJSONToObject:
1
** Converted object:
pResponse=5@MyMsg.PartialJson ; <OREF>
+----------------- general information ---------------
| oref value: 5
| class name: MyMsg.PartialJson
| reference count: 2
+----------------- attribute values ------------------
| %Concurrency = 1 <Set>
| active = 1
| customer_name = "FRANCISCO"
| customer_surname_1 = "LOPEZ"
| customer_surname_2 = "DE LAS HERAS"
| dob = "1972-02-01"
| email = "kurro.lopez@gmail.com"
| ext_customer_id = 123456789
| passport_id = "123456ZZZ"
| sex = "M"
+-----------------------------------------------------
Hola Kurro,
Sí, como dices es probable que tenga que ver con la versión, además la función ##class(%ZEN.Auxiliary.jsonProvider).%ConvertJSONToObject() utiliza internamente el deprecado %zen.ProxyObject y es probable que el comportamiento haya sufrido correcciones desde entonces.
En cualquier caso, si te encuentras a veces restringido por la versión que utilizas y necesitas realizar mapeos a mano (simples) de propiedades puedes apoyarte en métodos generados.
Por ejemplo, esta clase provee un método generado - muy simple - para tener un CopyProperties que puedas invocar y copie las propiedades.
/// Clase auxiliar para copiar propiedades de objetos que tengan el mismo nombre
Class MyMsg.ObjCopy Extends %RegisteredObject
{
/// Método generado que copia las propiedades (con el mismo nombre) de un objeto en el actual
/// -obj: objeto del cual se quieren copiar las propiedades
Method CopyProperties(ByRef obj) As %Status [ CodeMode = objectgenerator ]
{
set properties = %compiledclass.Properties
for i=1:1:properties.Count() {
#dim prop As %Dictionary.CompiledProperty = properties.GetAt(i)
if prop.Name'="",prop.Name'["%" {
set propName = prop.Name
if prop.Name["_" {
set propName = """"_prop.Name_""""
}
// set ..x = obj.x
do %code.WriteLine(" set .."_propName _"=obj."_propName)
}
}
quit 1
}
}
Por lo que en tu clase MyMsg.PartialJson sólo necesitas cambiar la herencia:
Class MyMsg.PartialJson Extends (Ens.Response, ObjCopy)
Y a continuación, puedes invocarlo de la siguiente manera para que te copie las propiedades (parciales) de %DynamicObject:
set partialJsonObj = ##class(MyMsg.PartialJson).%New()
do partialJsonObj.CopyProperties(objJson.returnValue.data)
write !!,"** partialJsonObj (copied):",!
zw partialJsonObj
Hola Diego,
Tal vez lo mejor es que empieces echándole un vistazo a un ejemplo: https://github.com/intersystems-ib/iris-sample-rest-angular
Saludos!
Hola @Yone Moreno,
Al final ha coincide que hemos comentado este tema online :)
Hemos descubierto finalmente que los ficheros Streams se estaban generando por otra clase de mensajes que utilizaban %Stream.FileBinary.
Recuerda que las propiedades %Stream.Global* no almacenan en fichero externos sino en la base de datos.
En cualquier caso, sean %Stream.File* o %Stream.Global* al hacer un Clear() podemos borrarlas sin problemas.
Hola Marta,
No consigo entender exactamente lo que intentas probar.
Parece que tu clase es un %JSON.Adaptor pero luego en tu código parece que estás intentando generar un %DynamicObject sobre la marcha. No sé en qué caso encuentras el problema.
Te paso un ejemplo parecido al de tu clase y un método para probar:
Class Services.IS.Data.Pe Extends (%RegisteredObject, %JSON.Adaptor)
{
Property codigo As %String;
Property descripcion As %String;
Property ListaP As list Of %String;
ClassMethod Test()
{
// Ejemplo. %JSONExport()
set obj = ##class(Services.IS.Data.Pe).%New()
set obj.codigo = "123"
set obj.descripcion = "desc"
write !,"obj.%JSONExport(): "
do obj.%JSONExportToString(.output)
write !,output
// Ejemplo. %DynamicObject
set pts = { "pts":[] }
for i=1:1:3 {
set pec = { }
set pec.codigo = "cod"_i
set pec.descripcion = "des"_i
do pts.pts.%Push(pec)
}
write !!,"%Dynamic Object"
write !,pts.%ToJSON()
}
}
Si lo pruebas, verás que en ningún caso (ni con %JSON.Adaptor ni con %DynamicObject) se genera la lista vacía que indicas:
USER>do ##class(Services.IS.Data.Pe).Test()
obj.%JSONExport():
{"codigo":"123","descripcion":"desc"}
%Dynamic Object
{"pts":[{"codigo":"cod1","descripcion":"des1"},{"codigo":"cod2","descripcion":"des2"},{"codigo":"cod3","descripcion":"des3"}]}
Aquí puedes encontrar más información sobre JSON y cómo trabajar tanto con %JSON.Adaptor como con %DynamicObject: https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls?KEY=GJSON
Hola Kurro,
¿Has probado a activar el rastreo con ^ISCSOAP en pruebas? https://docs.intersystems.com/irisforhealthlatest/csp/docbook/DocBook.UI.Page.cls?KEY=GSOAP_debug
set ^ISCSOAP("Log")="ios"
set ^ISCSOAP("LogFile")="/tmp/test.log"
Intenta comparar la petición completa (cabeceras incluidas) y la respuesta que obtienes para un servicio de otro proveedor que sí funciona Vs. este que te da problemas. Quizá sencillamente estés teniendo algún problema con la URL del Location que le estás pasando y por eso el WebService te devuelve el WSDL.
Quizá puedas comparar la petición te funciona en SoapUI Vs. la que da error en IRIS y comprobar si tienen alguna mínima diferencia en cabeceras HTTP o SOAP.
Podrías utilizar SetHttpHeader() para modificar las cabeceras HTTP de tu %SOAP.WebClienthttps://docs.intersystems.com/irisforhealthlatest/csp/docbook/DocBook.UI.Page.cls?KEY=GSOAP_cli_details
O directamente cabeceras SOAP si te hicieran falta: https://docs.intersystems.com/irisforhealthlatest/csp/docbook/DocBook.UI.Page.cls?KEY=GSOAP_HEADER
¿Entiendo que tú sólo controlas el cliente de WebService no? (el servicio web en sí, lo controla y lo mantiene otro proveedor).
A simple vista, me parece que debe haber algo que falte o sobre en la petición SOAP de forma que hace que el servicio web no lo interprete correctamente y te devuelva el WSDL sin más.
Pero vaya, básicamente habría que investigarlo en detalle. Quizá es mejor que abras directamente un caso a soporte WRC para que puedan verlo contigo.
Hola Yone,
Entiendo que quieres implementar un cliente de WebService en Ensemble que utilice MTOM.
Supongo que ya tienes creado el cliente de WebService, el Business Operation y los Mensajes a partir del WSDL del WebService.
¿Has probado a sobreescribir el parámetro MTOMREQUIRED del cliente web y activarla?
En Using MTOM for Attachments. Webclient, tienes un ejemplo de un cliente de servicio web que al invocarlo activa la propiedad MTOMRequired y donde además ha cambiado los tipos de datos por derivados de %Stream:
Hola de nuevo Yone,
Por lo que comentas, quizá te falte añadir la cabecera Content-Disposition en la petición y ahí especificar el nombre del archivo.
Creo que en el ejemplo que habías hecho originalmente con SoapUI, esa cabecera tenía este valor:
Content-Disposition: attachment; name="application.zip"
En Fine Tuning a WebClient te habla de cómo puedes especificar cabeceras en tu cliente web utilizando el método SetHttpHeader() que hereda de %SOAP.WebClient.
Así que puedes probar a especificar con SetHttpHeader() la cabecera Content-Disposition y añadir el nombre del fichero que quieras que aparezca.
Hola Yone,
En principio el ..SetHttpHeader() debería ser suficiente.
Puedes probar con:
do ..SetHttpHeader("Content-Disposition", "attachment; name=""application.zip""")
¿El Servicio Web sigue devolviendo un error respecto al Name?
Supongo que estás utilizando ^ISCSOAP para examinar lo que se envía al WebService. Dependiendo de tu versión de Ensemble o Health Connect podrás utilizar las opciones de ISCSOAP para que te muestre las cabeceras HTTP:
set ^ISCSOAP("Log")="ioshH"
set ^ISCSOAP("LogFile")="/tmp/soap.log"
Aquí en InterSystems IRIS SOAP Log te explica las diferentes opciones. Comprueba en la documentación de tu versión específica si están las opciones para las cabeceras HTTP y así asegurarte de que se muestran.
He hecho una prueba rápida en una 2020.1 y en el log de ISCSOAP debería tener una pinta así:
10/15/2021 13:39:51 *********************
Output from Web client with SOAP action =
<?xml version="1.0" encoding="UTF-8" ?>
<!-- mensaje SOAP que se haya enviado -->
**** Output HTTP headers for Web Client
User-Agent: Mozilla/4.0 (compatible; InterSystems IRIS;)
Host: xyz.es
Accept-Encoding: gzip
Content-Disposition: attachment; name="application.zip"
SOAPAction:
Si en tu versión no se pueden mostrar las cabeceras en el log quizá puedes utilizar herramientas externas como WireShark, etc.
Échale un vistazo a esto, y si no logras avanzar escríbeme por correo y quedamos y lo revisamos.
Hola Yone,
Lo que te indicaba antes. Necesitarás en ese caso otra herramienta como Wireshark que te permita capturar las cabeceras que se envían al servicio web y ver si están bien.
Dale una vuelta con eso y si no consigues avanzar me escribes por email y buscamos la forma de revisarlo conjuntamente.
Hola Yone, me alegro de que al final hayas encontrado el mecanismo de Attachment para enviarlo :)
Respecto a la autenticación, deberías revisar las especificaciones del servicio web al que te quieres conectar.
Creo que estás intentando conectar a un servicio web del Ministerio para enviar comunicaciones, por experiencias pasadas creo recordar que suelen pedir al menos:
Pero repito, confírmalo por favor con la documentación de las especificaciones del servicio web al que te quieras conectar.
Puedes echar un vistazo a la documentación aquí: https://docs.intersystems.com/irisforhealthlatest/csp/docbook/DocBook.UI.Page.cls?KEY=GSOAPSEC_bodyencr
En cualquier caso lo dicho, si necesitas algún ejemplo específico o comentar alguna cosa concreta puedes escribirme por email y buscamos un rato para echarlo un ojo.
Hola Yone,
No sé si te he entendido muy bien. ¿Quieres hacer la comprobación por código y si es así obtener el campo?
Por ejemplo:
if (request.GetValueAt("PID:3.4.1")="CAC")&&(request.GetValueAt("PID:3.5")="JHN") {
write !,request.GetValueAt("PID:3.1")
}
Si lo que necesitas es hacerlo en el buscador de mensajes, lo más rápido sería que utilizarás tablas de búsqueda para indexar esas búsquedas y que vayan más rápido.
Hola Mathew,
¿Le has echado un vistazo a Ens.Util.Time?
USER>set now = $horolog
USER>write $zdt(now,3)
2021-10-29 11:23:49
USER>write ##class(Ens.Util.Time).ConvertDateTime(now,"%q(3)","%K(-6)%Y-%m-%d %H:%M:%S",,.status,)
2021-10-29 05:23:49
Te puede servir para convertir horas entre zonas horarias, sabiendo el offset sobre UTC.
Hola Kurro,
Te valdría deshabilitar el envío de alertas desde "MyProduct.BO.SendEmail"? Podrías probar a desactivar el parámetro "Alert On Error". Normalmente se suele configurar así para evitar esos bucles que comentas.
Hola Yone,
Me parece que estás intentado hacer una prueba de envío DICOM por TCP desde Producción > Acciones > Prueba.
Ese tipo de pruebas pueden servirte para casos más sencillos pero no para enviar un mensaje DICOM, que es un poco más complejo.
Si tienes el namespace ENSDEMO, encontrarás ejemplos de producciones que usan ficheros DICOM. Te pueden servir de punto de partida.
Si estás interesado en envío DICOM a través de TCP, necesitarás contar con un simulador. Te paso un ejemplo que utiliza interoperabilidad de IRIS y un simulador (dcm4che). Puedes seguirlo paso a paso: https://github.com/intersystems-ib/iris-dicom-sample
Échale un vistazo, si no consigues avanzar o tienes dudas podemos buscar un hueco la próxima semana y lo comentamos.
Hola Yone,
Sí, puedes utilizar HS2017 para implementar integraciones con DICOM.
El ejemplo que te pasé está implementado en IRIS, pero puedes hacer lo mismo en HS2017.
En cuanto al simulador, puedes utilizar el que quieres. Yo he utilizado dcm4che en el ejemplo porque puedes utilizarlo desde línea de comandos en Linux. En el propio ejemplo está incluido cómo hacer algunas llamadas simples para enviar mensajes a través de DICOM TCP.
Hola Yone,
En tu caso, parece que el host al que intentas conectar (supongo que es un simulador), está rechazando la conexión.
Quizá porque el documento DICOM que intentas enviar tiene un TransferSyntax que no está configurado. Lo mejor sería que intentaras obtener información / logs en el host que lo está rechazando. Por ejemplo si usas el simulador dcm4che te mostrará información que te puede ayudar a investigar qué ha sucedido.
Yo te recomendaría:
1-Intenta ejecutar el ejemplo que te pasé, utilizando contenedores, y comprueba que todo te funciona bien y comprendes cómo funciona la integración con DICOM.
2-Intenta replicar el comportamiento que te interese en tu propia producción con tu propio simulador. Ten presente la información que te devuelva el simulador. Te ayudará a comprender el proceso de negociación de la conexión y la transferencia.