Question
Yone Moreno · Feb 13, 2020

How could we store a list into a global variable?

Hello,

 

We would like to store a list into a global. The need is to get the full Web Service's Response Message, because of currently, our Operation sends the message to the Process, whith an empty list:

 

We have created a copyList which is a clone of the list which is being returned from the web service client:

 

set copyList = ##class(%ListOfObjects).%New()
 set copyList = pResponse.RSPK21QUERYRESPONSE.%ConstructClone(1)
 $$$LOGINFO("copyList: "_copyList)
 $$$LOGINFO("copyList count: "_copyList.Count())
 $$$LOGINFO("copyList.GetAt(1): "_copyList.GetAt(1))
 $$$LOGINFO("copyList.PID8: "_copyList.GetAt(1).PID.PID8.content)
 $$$LOGINFO("copyList serialize: "_copyList.Serialize())

 

We have checked that its content is being printed:

 

Now comes the challenge. We would need to store this copyList inside a global, to be able to use it inside the Process. However if we read globals' documentation it says:


" Each global node can contain a single string of up to 32K characters.  "

We have tried the following to be able to store our copyList inside a global:

 set ^globalList = copyList
 $$$LOGINFO("^globalList: "_^globalList)
 //$$$LOGINFO("^globalList count: "_^globalList.Count())
 $$$LOGINFO("^globalList.GetAt(1): "_^globalList.GetAt(1))

 

We are shocked because of it shows that ^globalList is a %Collection.ListObj

However if we uncomment the line:

 //$$$LOGINFO("^globalList count: "_^globalList.Count())

The compiler outputs: " Missing subscript"

 

And if we uncomment the line:

$$$LOGINFO("^globalList.GetAt(1): "_^globalList.GetAt(1))

It shows:

 

How could we store a list into a global? Is there a way to cast a list to string and be able to store it into a global?

 

 

We have read:

https://docs.intersystems.com/irislatest/csp/docbook/Doc.View.cls?KEY=GO...

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

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

https://cedocs.intersystems.com/latest/csp/documatic/%25CSP.Documatic.cl...

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

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

https://community.intersystems.com/post/what-best-way-serialize-objectli...

https://community.intersystems.com/post/globals-magic-swords-storing-dat...

https://cedocs.intersystems.com/latest/csp/documatic/%25CSP.Documatic.cl...

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

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

https://community.intersystems.com/post/serialize-and-deserialize-object...

https://community.intersystems.com/post/response-filled-bussiness-operat...

 

Besides we add the Operation's code:

 

Class Operaciones.SOAP.Gasometros.GestionPacientes.SeleneHL7Service Extends Ens.BusinessOperation [ ProcedureBlock ]
{ Method operacion(pRequest As Mensajes.Request.GestionPacientes.operacionRequest, Output pResponse As Mensajes.Response.GestionPacientes.operacionResponse) As %Library.Status
{
 
 SET RSPK21QUERYRESPONSE = ##class(%ListOfDataTypes).%New()
 Set ..Adapter.WebServiceClientClass = "WSCLIENTE.GestionPacientes.ConsultaCandidatos"
 Set MSH=pRequest.MSH,SFT=pRequest.SFT,QPD=pRequest.QPD,DSC=pRequest.DSC
 
 Set tSC = ..Adapter.InvokeMethod("operacion",,.MSH,.SFT,.MSA,.ERR,.QAK,.QPD,pRequest.RCP,.RSPK21QUERYRESPONSE,.DSC) Quit:$$$ISERR(tSC) tSC
 $$$LOGINFO("LLEGAN "_RSPK21QUERYRESPONSE.Count())
 
 set pResponse = ##class(Mensajes.Response.GestionPacientes.operacionResponse).%New()
 
 Set tSC = pRequest.NewResponse(.pResponse) Quit:$$$ISERR(tSC) tSC
 
 Set pResponse.MSH = $get(MSH)
 Set pResponse.SFT = $get(SFT)
 Set pResponse.MSA = $get(MSA)
 Set pResponse.ERR = $get(ERR)
 Set pResponse.QAK = $get(QAK)
 Set pResponse.QPD = $get(QPD)
 Set pResponse.DSC = $get(DSC)
 Set pResponse.RSPK21QUERYRESPONSE = $get(RSPK21QUERYRESPONSE)
 $$$LOGINFO("LLEGAN "_pResponse.RSPK21QUERYRESPONSE.Count())
 $$$LOGINFO("RSPK21QUERYRESPONSE.PID8: "_pResponse.RSPK21QUERYRESPONSE.GetAt(1).PID.PID8.content)
 
 set copyList = ##class(%ListOfObjects).%New()
 set copyList = pResponse.RSPK21QUERYRESPONSE.%ConstructClone(1)
 $$$LOGINFO("copyList: "_copyList)
 $$$LOGINFO("copyList count: "_copyList.Count())
 $$$LOGINFO("copyList.GetAt(1): "_copyList.GetAt(1))
 $$$LOGINFO("copyList.PID8: "_copyList.GetAt(1).PID.PID8.content)
 $$$LOGINFO("copyList serialize: "_copyList.Serialize())
 
 
 set ^globalList = copyList
 $$$LOGINFO("^globalList: "_^globalList)
 //$$$LOGINFO("^globalList count: "_^globalList.Count())
 //$$$LOGINFO("^globalList.GetAt(1): "_^globalList.GetAt(1))
 
 
 
 Quit $$$OK
}

 

Parameter ADAPTER = "EnsLib.SOAP.OutboundAdapter"; XData MessageMap
{
<MapItems>
<MapItem MessageType="Mensajes.Request.GestionPacientes.operacionRequest">
<Method>operacion</Method>
</MapItem>
</MapItems>
} }

00
0 2 105 2

Replies

You can't directly store an object in a global like this. In your code, you're actually just storing a text description of the object reference in the global. The way to store an object in a global is to either (1) define it as a persistent class and let the system handle storing it automatically, (2) make the list of objects a property of a parent class which is itself persistent, or (3) serialize the object into a string that can be stored directly in the global.

Can you explain why you need to store copyList in this manner? If you just want to persist the objects in copyList, you can consider making RSPK21QUERYRESPONSE a persistent class. 

https://docs.intersystems.com/healthconnect20191/csp/docbook/DocBook.UI....
https://docs.intersystems.com/healthconnect20191/csp/docbook/Doc.View.cl...
https://docs.intersystems.com/healthconnect20191/csp/docbook/Doc.View.cl...

Also, it's worth noting that when you define the property RSPK21QUERYRESPONSE  as a list of objects where the child object extends %SerialObject,  then that entire list will be stored in the same global as the parent class.

One other note:

At the top of your code example, you set RSPK21QUERYRESPONSE as a %ListOfDataTypes:
SET RSPK21QUERYRESPONSE = ##class(%ListOfDataTypes).%New()

While later you try to clone it into a %ListOfObjects, which is not equivalent:
set copyList = ##class(%ListOfObjects).%New()
set copyList = pResponse.RSPK21QUERYRESPONSE.%ConstructClone(1)

Yone, since you fixed the problem related this class in your other post, does that solve this problem also?