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,

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:

¿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.

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.WebClient
https://docs.intersystems.com/irisforhealthlatest/csp/docbook/DocBook.UI...

O directamente cabeceras SOAP si te hicieran falta:
https://docs.intersystems.com/irisforhealthlatest/csp/docbook/DocBook.UI...

Hola Kurro,

¿Has probado a activar el rastreo con ^ISCSOAP en pruebas?
https://docs.intersystems.com/irisforhealthlatest/csp/docbook/DocBook.UI...

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.

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...

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 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 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 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 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 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 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 Javier! Ya he visto que te han contestado en el developer community smiley

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/P...

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/Je...

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.