Return ACK from Process
Hello,
We would need some help, please
First of all thanks for your time used reading this question
Also, thanks for your patience
We need to generate an ACK in a Process and return it to the Service to reply
We have currently written a code block with:
//Devolvemos ACK AA a DragoAP para indicar que no procesamos las prepeticiones
set pOutput = ##class(%GlobalCharacterStream).%New()
//set ACKer7 = ..GetAck(mensajeHL7, "AA")
set ACKer7 = ##class(ITB.HL7.BS.XMLService).GetAck(context.mensajeHL7, "AA")
set ACKxml = ##class(ITB.HL7.Util.Convert).ER7ToXML(ACKer7,.tSC)
set inicioCabecerasSOAP = "<SOAP-ENV:Envelope xmlns:SOAP-ENV=""http://schemas.xmlsoap.org/soap/envelope/""><SOAP-ENV:Header/><SOAP-ENV:Body>"
set finCabecerasSOAP = "</SOAP-ENV:Body></SOAP-ENV:Envelope>"
do pOutput.Write(inicioCabecerasSOAP_ACKxml.Read()_finCabecerasSOAP)
When we test this code, we observe:
| ERROR <Ens>ErrException: <METHOD DOES NOT EXIST>zS5+6^Procesos.Laboratorio.EnrutadorLaboratorio.Thread1.1 *GetAck,ITB.HL7.BS.XMLService -- - registrado como '-' número - @' set ACKer7 = ##class(ITB.HL7.BS.XMLService).GetAck(context.mensajeHL7, "AA")' |
Why do we get this error message?
As you would notice we have written:
set ACKer7 = ##class(ITB.HL7.BS.XMLService).GetAck(context.mensajeHL7, "AA")
When we press F12 above ITB.HL7.BS.XMLService
We observe the desired GetAck method
How could we further debug, understand, and solve this issue?
➡️ We have read:
https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cl…
https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cl…
https://community.intersystems.com/post/reply-custom-ack
https://www.intersystems.com/wp-content/uploads/sites/10/WiFISEasyConne…
➡️ Thanks for your replies
Comments
Please post the source code for ITB.HL7.BS.XMLService so we can take a look.
One thing to check: is GetAck declared as a "Method" or as a "ClassMethod"? If it is declared as a "Method" then that is the problem. The syntax you're using to call it is class method syntax, not instance method syntax.
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
You need to instantiate that class as an object and then you can call methods on the object:
https://docs.intersystems.com/irisforhealthlatest/csp/docbook/Doc.View…
If you want to be able to call that method without first creating an instance of your class, you need to define the method as a Class Method, not just a Method. Add "Class" before Method on that function definition and recompile your class, and it will probably work.
Otherwise, like Marc said, you'll have to instantiate the class then call the method on that instance.