Thanks

Hello Eduard thanks for your reply

msg is a %GlobalCharacterStream

it is defined before, here is the code:

                            set msg=##class(%GlobalCharacterStream).%New()
                            if ('tSC) || (response.error '= "")||(response.informacion.mensaje '= "") {
                                do msg.Write("<br></br><H1>No existe el informe solicitado</H1>")
                            } else {
                                do ..Adapter.AssignOneSetting("Pdf","1","")
                                Do msg.Write($SYSTEM.Encryption.Base64Decode(response.datos.pdf))
                            }

Hello, thanks for your time reading our questions and doubts,

We have studied how to use the following data types: %Stream.TmpCharacter and %Stream.TmpBinary

We have used both as follows:

              

               set pOutput = ##class(%Stream.TmpBinary).%New()
                //set pOutput = msg
                while(msg.AtEnd=0){
                    do pOutput.Write(msg.Read())
                }
                do msg.Clear()
                Quit $$$OK
 
                do pOutput.Clear()
                $$$LOGWARNING("Despues de borrar en el Servicio: pOutput.Clear()")

However we still observing a .stream being created at: /opt/ensemble/ESBHCDSNS/stream

How could we delete a .stream which represents a pdf being returned from a REST Service to POSTMAN?

Thanks for your help 🙇‍♂️  and time reading our questions and code ⌚️

➡️ We would need some help if you could explain to us how would you recommend to delete a .stream in a REST Service? , please.

We have also read:

https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls...

https://docs.intersystems.com/irislatest/csp/documatic/%25CSP.Documatic....

https://docs.intersystems.com/irislatest/csp/documatic/%25CSP.Documatic....

https://docs.intersystems.com/latest/csp/documatic/%25CSP.Documatic.cls?...

Thanks Jeffrey for your kind help, and thanks for your time.

We have wrote your method in a class called "Util.FuncionesComunes"

Namespace "ESBSSCC"

We have wrote in the terminal:

ESBSSCC 2e1>Set hosts=##class(Util.FuncionesComunes).GetHostsByAdapter("Producion.ESBSSCC","EnsLib.HTTP.InboundAdapter")
 

We observe:


SET hosts=##class(Util.FuncionesComunes).GetHostsByAdapter("Produccion.ESBSSCC",
^
"EnsLib.HTTP.InboundAdapter")
<COMMAND>^Util.FuncionesComunes.1

ESBSSCC 2e1>

Production's name is: Producion.ESBSSCC

How could we debug this to be able to execute the code and list all REST services in the current namespace?

Thanks for your help, time and replies Jeffrey

Thanks Jeffrey

We have placed your function in a class called "Util.FuncionesComunes"

We have tried to execute it as follows:

Set hosts=##class(Util.FuncionesComunes).GetHostsByAdapter("Produccion.ESBSSCC","EnsLib.HTTP.InboundAdapter")

It shows:

SET hosts=##class(Util.FuncionesComunes).GetHostsByAdapter("Produccion.ESBSSCC",
^
"EnsLib.HTTP.InboundAdapter")
<COMMAND>^Util.FuncionesComunes.1

When we write: "w $ZERROR" it outputs:

SET hosts=##class(Util.FuncionesComunes).GetHostsByAdapter("Produccion.ESBSSCC",
^
"EnsLib.HTTP.InboundAdapter")
<COMMAND>^Util.FuncionesComunes.1

How could we solve this?

Hello Marc Mundt,

ITB.HL7.BS.XMLService code is the following:

/// HL7 XML services common class
Class ITB.HL7.BS.XMLService Extends (Ens.BusinessService, ITB.HL7.XMLHost)
{

/// Location and Revision of this file in Perforce (Auto-updating)
Parameter SrcVer = "$Id$";

Property UseAckCommitCodes As %Boolean [ InitialExpression = 1 ];

Property BadMessageHandler As %String(MAXLEN = 1000);

/// Name of the element to send the incoming XML stream received by this Service if message is processed OK
Property XMLInputHandler As %String(MAXLEN = 1000);

/// Colon-separated LocalFacility:LocalApplication:MessageStructure codes representing this (receiving) facility, application, returning MessageStructure, AcceptAcknowledgmentType and ApplicationAcknowledgmentType<br/>
/// These are used in constructing reply ACK message headers as SendingFacility, SendApplication and MessageStructure. <br/>
/// The '@' symbol represents using the corresponding field from the incoming message. <br/>
/// If your ID must contain a literal @ symbol, escape it with backslash: '\@'
Property LocalFacilityApplication As %String [ InitialExpression = "ISC:EnsembleHL7:ACK:NE:NE" ];

/// Strip namespace in HL7 XML (ACK message).
Property StripNamespace As %Boolean [ InitialExpression = 1 ];

/// Control of ACK handling; options: <br/>
/// - Never : Do not send back any ACK <br/>
/// - Immediate : Send back (commit) ACK reply message immediately upon receipt of the inbound message <br/>
/// - Application : If message passes validation, wait for ACK from target config item and forward it back when it arrives <br/>
Property AckMode As %String(DISPLAYLIST = ",Never,Immediate,Application", VALUELIST = ",Never,Immed,App") [ InitialExpression = "Immed", Required ];

/// Names the target(s) from which an ACK response should be forwarded back to the caller, if the AckMode="Application".
Property ResponseFrom As %String(MAXLEN = 1000);

Parameter SETTINGS = "StripNamespace,LocalFacilityApplication,AckMode,ResponseFrom::selector?context={Ens.ContextSearch/ProductionItems?targets=1&productionName=@productionId},UseAckCommitCodes,TargetConfigNames:Basic:selector?multiSelect=1&context={Ens.ContextSearch/ProductionItems?targets=1&productionName=@productionId},BadMessageHandler:Basic:selector?context={Ens.ContextSearch/ProductionItems?targets=1&productionName=@productionId},XMLInputHandler:Basic:selector?context={Ens.ContextSearch/ProductionItems?targets=1&productionName=@productionId},SearchTableClass::selector?context={Ens.ContextSearch/SearchTableClasses?host=EnsLib.HL7.Service.Standard},MessageSchemaCategory:Basic:selector?context={Ens.ContextSearch/SchemaCategories?host=EnsLib.HL7.Service.Standard},AlertGracePeriod:Alerting";

/// HL7 XML (Stream) process input
Method StreamProcessInput(pInput As %Stream.Object, Output pOutput As %Stream.Object, pSendAck As %Boolean = 0, pCallTargets As %Boolean = 1, Output pER7 As EnsLib.HL7.Message) As %Status
{
    set ret = $$$OK
    
    try {
        // convert XML input to ER7
        set tER7 = ##class(ITB.HL7.Util.Convert).XMLToER7(pInput,.tSC,..MessageSchemaCategory)
        if $$$ISERR(tSC) $$$ThrowStatus(tSC)
        set pER7 = tER7
        
        // send ACK
        if pSendAck,..AckMode="Immed" {
            set tAckCode = $case(..UseAckCommitCodes, 1:"CA", 0:"AA")
            set tAckER7 = ..GetAck(tER7, tAckCode)
            set tAckXML = ##class(ITB.HL7.Util.Convert).ER7ToXML(tAckER7,.tSC,,,,..StripNamespace)
            if $$$ISERR(tSC) $$$ThrowStatus(tSC)
            set pOutput = tAckXML
        }
        
        // send EnsLib.HL7.Message to targets
        if pCallTargets {
            for i=1:1:$l(..TargetConfigNames, ",") {
                set tTarget=$zstrip($p(..TargetConfigNames,",",i),"<>W")
                if pSendAck,..AckMode="App",..ResponseFrom=tTarget {
                    $$$THROWONERROR(tSC,..SendRequestSync(tTarget, tER7, .tAckER7))
                    set tAckXML = ##class(ITB.HL7.Util.Convert).ER7ToXML(tAckER7,.tSC,,,,..StripNamespace)
                    if $$$ISERR(tSC) $$$ThrowStatus(tSC)
                    set pOutput = tAckXML
                } else {
                    $$$THROWONERROR(tSC,..SendRequestAsync(tTarget, tER7))
                }
            }
        }
        
        // index HL7 in SearchTable
        if ..SearchTableClass'="" {
            set tSC = $zobjclassmethod(..SearchTableClass,"IndexDoc",tER7)
            if $$$ISERR(tSC) $$$LOGERROR("SearchTableClass Error: "_##class(%SYSTEM.Status).GetErrorText(tSC))
        }
        
        // ok. send XML input to XMLInputHandler if any
        do:..XMLInputHandler'="" ..SendStreamToTarget(..XMLInputHandler,pInput)
        
    } catch ex {
        set ret = ex.AsStatus()
        $$$LOGERROR($$$StatusDisplayString(ret))
        
        // error occured. send service input to BadMessageHandler if any
        do:..BadMessageHandler'="" ..SendStreamToTarget(..BadMessageHandler,pInput)
        
        // send alert when HL7 XML has not been processed correctly
        do:..AlertOnError ..SendAlert(##class(Ens.AlertRequest).%New($LB(..%ConfigName,$$$StatusDisplayString(ret))))
    }
    
    quit ret
}

/// Get ACK message for a given HL7 message
Method GetAck(pMsg As EnsLib.HL7.Message, pReplyCode As %String) As EnsLib.HL7.Message
{
    // create ACK and copy the control id to the ack control id
    set tReply = pMsg.NewReplyDocument(,..LocalFacilityApplication)
    set tReply.Source = pMsg.%Id()
    do tReply.SetValueAt(pMsg.GetValueAt("1:10"),"1:10")
    do tReply.SetValueAt($p(..LocalFacilityApplication,":",3),"1:9.3")
    do tReply.SetValueAt($p(..LocalFacilityApplication,":",4),"1:15")
    do tReply.SetValueAt($p(..LocalFacilityApplication,":",5),"1:16")
    
    // MSA segment
    set tMSA=##class(EnsLib.HL7.Segment).%New($LB("",1))
    set tMSA.Separators=tReply.Separators
    do tMSA.SetValueAt("MSA",0)
    do tMSA.SetValueAt(pReplyCode,1)
    do tMSA.SetValueAt(pMsg.GetValueAt("1:10"),2)
    do tReply.AppendSegment(tMSA)
    
    quit tReply
}

/// Send pInput stream to a production target
Method SendStreamToTarget(pTarget As %String, pInput As %Stream.Object) As %Status
{
    set tMsg = ##class(Ens.StreamContainer).%New(pInput)
    set tSC = ..SendRequestAsync(pTarget, tMsg)
    if $$$ISERR(tSC) $$$LOGERROR(##class(%SYSTEM.Status).GetOneErrorText((tSC)))
    quit 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) {
        
        set:pItem.GetModifiedSetting("BadMessageHandler",.tBadMessageHandler) tValue=tValue_","_tBadMessageHandler
        set:pItem.GetModifiedSetting("XMLInputHandler",.tXMLInputHandler) tValue=tValue_","_tXMLInputHandler
        
        for i=1:1:$L(tValue,",") {
            set tOne=$zstrip($p(tValue,",",i),"<>W")
            continue:""=tOne
            set pArray(tOne)=""
        }
    }
}

}

GetAck is a "Method"

How should we call it using method syntax, Marc Mundt?

Thanks for your replies

Thanks Marc Mundt for your attention, and your helpful reply

 
Our current code is:

When we dig deeper using Whireshark:

First, we find that the method in the example that uses GET, the retrievePerson, does answers with a JSON to POSTMAN, so it works:

GET request:

GET response:

In POSTMAN:

However,

Our custom method: consultarImagen which is a POST

Shows nothing in POSTMAN

Why?

POST request:

POST response:

In POSTMAN:

Could you help us?

Thanks for your replies

Thanks Marc Mundt for your reply

Yes you are right, we should use POST

We have changed it:

<Route Url="/consultarImagen" Method="POST" Call="consultarImagen"/>

However we do not see the response in POSTMAN:

And the headers are:

Content-Type: text/html

Content-Length: 0

CACHE-CONTROL: no-cache

PRAGAM: no-cache

We send the POST to the following URL:

http://localhost:19622/aplicaciones/scs/test/miscs/consultarImagen
 

Besides we observe the response message being converted from Ensemble object to JSON in the service:

We do see the Response Message from the Operation to the Service

Why we do not see the JSON being replied from the Service in POSTMAN?

How could we debug this behaviour?

Thanks for your replies

Thanks Marc Mundt for your help,

We have tried to make objetoSalida.binario as %Binary

Exactly we do the following:

1) We read the image as binary directly from the external system in the REST Operation:

set linea=""
    if (tResponse.Data.AtEnd = 0) {
        set linea = tResponse.Data.Read()
    }
    
    set pResponse.binario = linea
    
    $$$LOGINFO("pResponse.binario: "_pResponse.binario)

We observe the binary correctly written in the LOGINFO:

2) In the Service, we have a LOGINFO  before writing it to JSON

 $$$LOGINFO("objetoSalida.binario: "_objetoSalida.binario)        

 set tSC = claseAux.%WriteJSONStreamFromObject(.pOutput,.objetoSalida,,,,"aeloqtuw")

We see it correctly:

3) However when we convert it to JSON we see that there are strange characters like "\x00"

set tSC = claseAux.%WriteJSONStreamFromObject(.pOutput,.objetoSalida,,,,"aeloqtuw")

$$$LOGINFO("pOutput.Read(): "_pOutput.Read())

How would you recommend us to continue?

What documents or code examples would you study or write to handle this issue?

Thanks for your help

Hello,

We have continued the development,

The output system now replies to us

However we do see that the 2nd MIME part, the image, is being sent from ENSEMBLE, different than the image sent with POSTMAN

1 Let's see what we send from Ensemble:

2 The following image show us what POSTMAN correctly sends:

If we examine and compare both images, we observe that the image sent with Postam is being recognized as a JPEG, however the one sent with Ensemble is not being sent as a JPEG

The code which we have written is:

Class Operaciones.REST.miSCS.miSCS Extends EnsLib.REST.Operation
{

Parameter INVOCATION = "Queue";

/// 📤 Subir la imagen 
Method SubirImagen(pRequest As Mensajes.Request.miSCS.SubirImagen, pResponse As Mensajes.Response.miSCS.SubirImagen) As %Library.Status
{
    
    //Crear Request y Response HTTP
    Set httpRequest=##class(%Net.HttpRequest).%New()
    set tResponse = ##class(%Net.HttpResponse).%New()
    
    // Create root MIMEPart, la parte que contiene al resto
    Set RootMIMEPart=##class(%Net.MIMEPart).%New()
    
    //Crear parte con el expediente
     Set ExpedienteMIMEPart=##class(%Net.MIMEPart).%New()
     Set contentdisp="form-data; name=""expediente"""
     Do ExpedienteMIMEPart.SetHeader("Content-Disposition",contentdisp)
     Set ExpedienteMIMEPart.Body=pRequest.expediente
     //Do ExpedienteMIMEPart.SetHeader("Content-Type","text/plain")
     
    // Crear parte con la imagen
    Set ImagenMIMEPart=##class(%Net.MIMEPart).%New()
    Set ImagenMIMEPart.Body=##class(%GlobalCharacterStream).%New()
    //Probamos a leer una imagen local
    Set stream=##class(%Stream.FileCharacter).%New()
      Set sc=stream.LinkToFile("C:\Users\ext-ymorjim\Pictures\miSCS.jpg")
      While 'stream.AtEnd {
          Set linea=stream.Read()
      }
      $$$LOGINFO("linea: "_linea)
      //Escribir la imagen en el mensaje MIME
     Do ImagenMIMEPart.Body.Write(linea)
    //Do ImagenMIMEPart.Body.Write(pRequest.imagen)

    // Cabeceras de la imagen
    Set ImagenMIMEPart.ContentType="image/jpeg"
    Set contentdisp="form-data; name=""imagen""; filename="""_stream.Filename_""
    Do ImagenMIMEPart.SetHeader("Content-Disposition",contentdisp)

    // Insertar las partes en la raiz
    Do RootMIMEPart.Parts.Insert(ExpedienteMIMEPart)
    Do RootMIMEPart.Parts.Insert(ImagenMIMEPart)
    
    // create MIME writer; write root MIME message
    Set writer=##class(%Net.MIMEWriter).%New()

    // Prepare outputting to the HttpRequestStream
    Set httpRequest=##class(%Net.HttpRequest).%New()
    Set status=writer.OutputToStream(httpRequest.EntityBody)
    if $$$ISERR(status) {do $SYSTEM.Status.DisplayError(status) Quit}

    // Now write down the content
    Set status=writer.WriteMIMEBody(RootMIMEPart)
    if $$$ISERR(status) {do $SYSTEM.Status.DisplayError(status) Quit}

    // Creamos la URL
    set url      = ##class(Util.TablasMaestras).getValorMaestra("MISCS.PARAMETRIZACIONES","url")
    set path     = ##class(Util.TablasMaestras).getValorMaestra("MISCS.PARAMETRIZACIONES","path")
    set servicio = ##class(Util.TablasMaestras).getValorMaestra("MISCS.PARAMETRIZACIONES","servicio")
    set recurso  = ##class(Util.TablasMaestras).getValorMaestra("MISCS.PARAMETRIZACIONES","subirImagen")
            
    set URL = "http://"_url_path_servicio_recurso
    $$$LOGINFO("URL: "_URL)
    
    
    //Escribimos el tipo de contenido que enviamos
    Set httpRequest.ContentType="multipart/form-data; boundary="_RootMIMEPart.Boundary
    $$$LOGINFO("> httpRequest.ContentType: "_httpRequest.ContentType)
    
    //Enviamos
    set tSC=httpRequest.Post(URL,0)
    $$$LOGINFO("tSC: "_tSC)
    
    if $$$ISERR(tSC){
            $$$ThrowOnError(tSC)
    }
    if (tResponse.Data.AtEnd = 0) {
        $$$LOGINFO("En SubirImagen, tamaño de tResponse: "_tResponse.Data.Size)
        set linea = tResponse.Data.Read()
        $$$LOGINFO("Linea: "_linea)
    }
    
    set pResponse = ##class(Mensajes.Response.miSCS.SubirImagen).%New()
    set pResponse.resultado = 1
    set pResponse.informacion = linea

    Quit pResponse
}

How could we continue
 

Could you point us to some example??, please

We have read:

https://docs.intersystems.com/irisforhealthlatest/csp/docbook/DocBook.UI...

Thanks in advance

Hello,

Thanks Marc Mundt for your help,

1 We have tried with the following code which reads a String which represents an image in pRequest.imagen and we send it into a MIME:

Class Operaciones.REST.miSCS.miSCSSubirImagenJPGlocal Extends EnsLib.REST.Operation { Parameter INVOCATION = "Queue";

/// 📤 Subir la imagenSanitaria
Method SubirImagen(pRequest As Mensajes.Request.miSCS.SubirImagen, pResponse As Mensajes.Response.miSCS.SubirImagen) As %Library.Status
{
    
    Set httpRequest=##class(%Net.HttpRequest).%New()
    set tResponse = ##class(%Net.HttpResponse).%New()
    
    Set msg=##class(%Net.MIMEPart).%New()
     Set msg.Body=##class(%GlobalCharacterStream).%New()
    Do msg.Body.Write(pRequest.imagen)
    Set msg.ContentType="multipart/form-data"
    
    // create MIME writer; write root MIME message
    Set writer=##class(%Net.MIMEWriter).%New()

    // Prepare outputting to the HttpRequestStream
    Set status=writer.OutputToStream(httpRequest.EntityBody)
    if $$$ISERR(status) {do $SYSTEM.Status.DisplayError(status) Quit}

    // Now write down the content
    Set status=writer.WriteMIMEBody(msg)
    if $$$ISERR(status) {do $SYSTEM.Status.DisplayError(status) Quit}
    
    set url      = ##class(Util.TablasMaestras).getValorMaestra("MISCS.PARAMETRIZACIONES","url")
    set path     = ##class(Util.TablasMaestras).getValorMaestra("MISCS.PARAMETRIZACIONES","path")
    set servicio = ##class(Util.TablasMaestras).getValorMaestra("MISCS.PARAMETRIZACIONES","servicio")
    set recurso  = ##class(Util.TablasMaestras).getValorMaestra("MISCS.PARAMETRIZACIONES","subirImagen")
            
    set URL = "http://"_url_path_servicio_recurso
    $$$LOGINFO("URL: "_URL)

    set tFormVarNames = "expediente,imagen"
    set tData("expediente") = pRequest.expediente
    set tData("imagen") = pRequest.imagen

    set tSC = ..Adapter.SendFormDataArray(.tResponse,"POST",httpRequest,.tFormVarNames,.tData,URL)
    $$$LOGINFO("tSC: "_tSC)
    
    if $$$ISERR(tSC){
            $$$ThrowOnError(tSC)
    }
    if (tResponse.Data.AtEnd = 0) {
        $$$LOGINFO("En SubirImagen, tamaño de tResponse: "_tResponse.Data.Size)
        set linea = tResponse.Data.Read()
        $$$LOGINFO("Linea: "_linea)
    }
    
    set pResponse = ##class(Mensajes.Response.miSCS.SubirImagen).%New()
    do pResponse.return.Write(linea)

    Quit pResponse
}

However when we see it using Whireshark we observe that it is being sent as text/html

2 We have also used the following approach, to read a JPG directly and send it into the MIME:

Class Operaciones.REST.miSCS.miSCSSubirImagenJPGlocal Extends EnsLib.REST.Operation
{

Parameter INVOCATION = "Queue";

/// 📤 Subir la imagenSanitaria
Method SubirImagen(pRequest As Mensajes.Request.miSCS.SubirImagen, pResponse As Mensajes.Response.miSCS.SubirImagen) As %Library.Status
{
    
    //Crear Request y Response HTTP
    Set httpRequest=##class(%Net.HttpRequest).%New()
    set tResponse = ##class(%Net.HttpResponse).%New()
    
    //Crear MIME
    Set msg=##class(%Net.MIMEPart).%New()
     Set msg.Body=##class(%GlobalCharacterStream).%New()
     
    //Probamos a leer una imagen local y a enviarla
    Set stream=##class(%Stream.FileCharacter).%New()
      Set sc=stream.LinkToFile("C:\Users\ext-ymorjim\Pictures\miSCS.jpg")
      While 'stream.AtEnd {
          Set linea=stream.Read()
      }
      $$$LOGINFO("linea: "_linea)
      
      //Escribir la imagen en el mensaje MIME
     Do msg.Body.Write(linea)
    //Do msg.Body.Write(pRequest.imagen)
    Set msg.ContentType="multipart/form-data"
    
    // create MIME writer; write root MIME message
    Set writer=##class(%Net.MIMEWriter).%New()

    // Prepare outputting to the HttpRequestStream
    Set status=writer.OutputToStream(httpRequest.EntityBody)
    if $$$ISERR(status) {do $SYSTEM.Status.DisplayError(status) Quit}

    // Now write down the content
    Set status=writer.WriteMIMEBody(msg)
    if $$$ISERR(status) {do $SYSTEM.Status.DisplayError(status) Quit}
    

    set url      = ##class(Util.TablasMaestras).getValorMaestra("MISCS.PARAMETRIZACIONES","url")
    set path     = ##class(Util.TablasMaestras).getValorMaestra("MISCS.PARAMETRIZACIONES","path")
    set servicio = ##class(Util.TablasMaestras).getValorMaestra("MISCS.PARAMETRIZACIONES","servicio")
    set recurso  = ##class(Util.TablasMaestras).getValorMaestra("MISCS.PARAMETRIZACIONES","subirImagen")
            
    set URL = "http://"_url_path_servicio_recurso
    $$$LOGINFO("URL: "_URL)

    set tFormVarNames = "expediente,imagen"
    set tData("expediente") = pRequest.expediente
    set tData("imagen") = pRequest.imagen
    //set tData("imagen") = linea

    set tSC = ..Adapter.SendFormDataArray(.tResponse,"POST",httpRequest,.tFormVarNames,.tData,URL)
    $$$LOGINFO("tSC: "_tSC)
    
    if $$$ISERR(tSC){
            $$$ThrowOnError(tSC)
    }
    if (tResponse.Data.AtEnd = 0) {
        $$$LOGINFO("En SubirImagen, tamaño de tResponse: "_tResponse.Data.Size)
        set linea = tResponse.Data.Read()
        $$$LOGINFO("Linea: "_linea)
    }
    
    set pResponse = ##class(Mensajes.Response.miSCS.SubirImagen).%New()
    do pResponse.return.Write(linea)

    Quit pResponse
}

With the previous code we see that a text/html is being sent too:

In both cases, the external system gives us a HTTP code 400:

     ERROR <Ens>ErrException: <THROW>zSubirImagen+40^Operaciones.REST.miSCS.miSCS.1 *%Exception.StatusException ERROR <Ens>ErrHTTPStatus: Received non-OK status 400 from remote HTTP server: 'HTTP/1.1 400 ' -- logged as '-' number - @' Set sc=tSC Throw:('sc) ##class(%Exception.StatusException).ThrowIfInterrupt(sc)'

How could we achieve to send it in the correct way? as it is being sent when we use POSTMAN:

How could we send the image as multipart/form-data?

> We have read:

https://docs.intersystems.com/irisforhealthlatest/csp/docbook/DocBook.UI...

https://docs.intersystems.com/irisforhealthlatest/csp/docbook/Doc.View.c...

How could we send the image as multipart/form-data as it is being sent by Postman?

➡️ Could you point us to same code examples, please?

Hello Kevin,

We are using the following Java version:

java version "1.8.0_65"
Java(TM) SE Runtime Environment (build 1.8.0_65-b17)
Java HotSpot(TM) 64-Bit Server VM (build 25.65-b01, mixed mode)

If we execute the command with our jar (which includes the Java program and its dependencies):

jar -tf "AppSeguimientoAnadidaReferenciaJARSexternos.jar"

We see:

META-INF/MANIFEST.MF
org/
org/eclipse/
org/eclipse/jdt/
org/eclipse/jdt/internal/
org/eclipse/jdt/internal/jarinjarloader/
org/eclipse/jdt/internal/jarinjarloader/JIJConstants.class
org/eclipse/jdt/internal/jarinjarloader/JarRsrcLoader$ManifestInfo.class
org/eclipse/jdt/internal/jarinjarloader/JarRsrcLoader.class
org/eclipse/jdt/internal/jarinjarloader/RsrcURLConnection.class
org/eclipse/jdt/internal/jarinjarloader/RsrcURLStreamHandler.class
org/eclipse/jdt/internal/jarinjarloader/RsrcURLStreamHandlerFactory.class
radarCovidcrearToken/
radarCovidcrearToken/CCAATokenGeneratorTest.class
generated_private_base64.pem
aether-api-1.7.jar
aether-impl-1.7.jar
aether-spi-1.7.jar
aether-util-1.7.jar
asm-6.2.jar
bcpkix-jdk15on-1.58.jar
bcprov-jdk15on-1.58.jar
classworlds-1.1.jar
commons-cli-1.0.jar
commons-codec-1.14.jar
commons-io-2.5.jar
jackson-annotations-2.10.3.jar
jackson-core-2.10.3.jar
jackson-databind-2.10.3.jar
java-jwt-3.10.3.jar
junit-3.8.1.jar
plexus-build-api-0.0.4.jar
plexus-cipher-1.4.jar
plexus-classworlds-2.2.3.jar
plexus-compiler-api-2.8.4.jar
plexus-compiler-javac-2.8.4.jar
plexus-compiler-manager-2.8.4.jar
plexus-component-annotations-1.7.1.jar
plexus-container-default-1.0-alpha-9-stable-1.jar
plexus-interactivity-api-1.0-alpha-4.jar
plexus-interpolation-1.13.jar
plexus-interpolation-1.14.jar
plexus-java-0.9.10.jar
plexus-sec-dispatcher-1.3.jar
plexus-utils-2.0.4.jar
plexus-utils-2.0.5.jar
qdox-2.0-M9.jar
sisu-guice-2.1.7-noaop.jar
sisu-inject-bean-1.4.2.jar
sisu-inject-plexus-1.4.2.jar
java-jwt-3.10.3_2.jar
jackson-databind-2.10.3_2.jar
jackson-annotations-2.10.3_2.jar
jackson-core-2.10.3_2.jar
commons-codec-1.14_2.jar
bcpkix-jdk15on-1.58_2.jar
bcprov-jdk15on-1.58_2.jar

If we execute the command to locate the jar where is the class which generates the NoClassDefFoundError :

jar -tf "bcprov-jdk15on-1.58.jar"

We get:

...

org/bouncycastle/util/io/pem/
org/bouncycastle/util/io/pem/PemGenerationException.class
org/bouncycastle/util/io/pem/PemHeader.class
org/bouncycastle/util/io/pem/PemObject.class
org/bouncycastle/util/io/pem/PemObjectGenerator.class
org/bouncycastle/util/io/pem/PemObjectParser.class
org/bouncycastle/util/io/pem/PemReader.class
org/bouncycastle/util/io/pem/PemWriter.class
org/bouncycastle/util/test/

...

As you would notice it outputs the name of the missing class:

org/bouncycastle/util/io/pem/PemReader.class

What could we do?

Hello Eduard

We would need to be able to send a REST POST meesage with the following body:

{
"provider":"provider",
"group""group",
"location""location",
"data""data",
"checkin""checkin",
"client""client",
"admin""admin",
"apiUrl""apiUrl"
}
 
 

And get the previous body inside our Service.

We have written as a Service:

Class Servicios.REST.HistoriaClinica.Videoconsulta Extends Ens.BusinessService
{ Parameter ADAPTER = "EnsLib.HTTP.InboundAdapter"; Method OnProcessInput(pInput As %RegisteredObject, Output pOutput As %RegisteredObject) As %Status
{
do ..enviarCitaCrearSala(pInput,.pOutput)
quit $$$OK
} Method enviarCitaCrearSala(pInput As %Stream.Object, Output pOutput As %Stream.Object) As %Status
{
//TODO: Get body


set tSC = ..SendRequestSync("Videoconsulta",body,.objetoSalida)
set claseAux = ##class(%ZEN.Auxiliary.jsonProvider).%New()
set tSC = claseAux.%WriteJSONStreamFromObject(.pOutput,.objetoSalida,,,,"aeloqtuw")

Quit tSC
}