Question
· Jun 11, 2020

How to set up a BO for XML

I'm cautious not to ask too many questions on here, but there really doesn't seem to be a good XML end to end guide that explains these things. 

I have now a Business operation that's going to call a url like  https://directory.spineservices.nhs.uk/ORD/2-0-0/organisations/Y00334?_f...

I'm looking the status of the practice- I tried date but again fell flat as i wan't able to ensure i only got the end date from the first <date> tags and not any subsequent dates. 

Managed to do it kinda in a class method like so 

  set httprequest = ##class(%Net.HttpRequest).%New()
    set httprequest.SSLConfiguration = "test"
    set httprequest.Https = 1
    set httprequest.SSLCheckServerIdentity=0
    Set status = reader.OpenURL("https://directory.spineservices.nhs.uk/ORD/2-0-0/organisations/Y00334?_f...",,httprequest)
    If $$$ISERR(status) {do $System.Status.DisplayError(status)}
    do reader.Correlate("Status","User.Writenode")
    do reader.Next(.obj)
    zw obj

(1) couldn't find anywhere as such to get the value from the property that was correlated against but anyway. 

Trued to put into a Buinsess operation which I always got a blank response evne though running the class method would work. When i called the .Next() i would get a Class not defined error 

Class Penn.EDT.BO.ODSGPCheck Extends (Ens.BusinessOperation, %XML.Adaptor)

{ Method GetGPStatus(pRequest As Penn.EDT.Messages.GetGPStatusRequest, Output pResponse As Penn.EDT.Messages.ODSGPStatus) As %Status
{
Set pResponse = ##class(Penn.EDT.Messages.ODSGPStatus).%New()
set reader = ##class(%XML.Reader).%New()
    set httprequest = ##class(%Net.HttpRequest).%New()
    set httprequest.SSLConfiguration = "test"
    set httprequest.Https = 1
    set httprequest.SSLCheckServerIdentity=0
    Set status = reader.OpenURL("https://directory.spineservices.nhs.uk/ORD/2-0-0/organisations/Y00334?_f...",,httprequest)
    If $$$ISERR(status) {do $System.Status.DisplayError(status)}
    do reader.Correlate("Status",pResponse)
    do reader.Next()
    //set pResponse.Status=obj
    
    quit status
} XData MessageMap
{
<MapItems>
<MapItem MessageType="Penn.EDT.Messages.GetGPStatusRequest">
<Method>GetGPStatus</Method>
</MapItem>
</MapItems>
} }
 

I just want to call a URL - get the response back of what that node says. Works as a class method but not a Buisness operation and can't see what suitable adapter would be required to stop it complaining. 

Discussion (4)2
Log in or sign up to continue

Hi Mark,

At first glance there seem to be the following issue with the business operation code: Correlate() method's second argument is a class name - not an object. Please take a look at the doc:

1) https://docs.intersystems.com/irislatest/csp/documatic/%25CSP.Documatic.cls?PAGE=CLASS&LIBRARY=%25SYS&CLASSNAME=%25XML.Reader#METHOD_Correlate
2) %XML.Reader usage - https://docs.intersystems.com/irislatest/csp/docbook/Doc.View.cls?KEY=GXML_import#GXML_import_example

Additionally it might be helpful to replace this line If $$$ISERR(status{do $System.Status.DisplayError(status)

with

    if $$$ISERR(status) quit status

- in order to bail out and report an error in case of an exception.

Regards,
Dmitry

I'm still confused:

I have it in a class method

I can't check it actually goes in the property as it's a classmethod and see no way to test it as a method to test the ..GPStatus 

I get this now from my BO

Method GetGPStatus(pRequest As Penn.EDT.Messages.GetGPStatusRequest, Output pResponse As Penn.EDT.Messages.ODSGPStatus) As %Status
{
Set pResponse = ##class(Penn.EDT.Messages.ODSGPStatus).%New()
set reader = ##class(%XML.Reader).%New()
    set httprequest = ##class(%Net.HttpRequest).%New()
    set httprequest.SSLConfiguration = "test"
    set httprequest.Https = 1
    set httprequest.SSLCheckServerIdentity=0
    Set status = reader.OpenURL("https://directory.spineservices.nhs.uk/ORD/2-0-0/organisations/Y00334?_f...",,httprequest)
    if $$$ISERR(status) quit status
    do reader.Correlate("Status","Penn.EDT.Messages.ODSGPStatus")
   $$$TRACE(..Status)
    do reader.Next()
     $$$TRACE(..Status)
    //set pResponse.Status=obj
    
    quit status
}

Doesn't like the .Next() for some reason. 

If i try without the .next i get no value 

Given the error message, I'd guess that Penn.EDT.Messages.ODSGPStatus class is not XML enabled, i.e. it does not inherit from %XML.Adaptor.

And you'd get an empty response anyway as you never assign anything to pResponse's properties.

One more issue is that argumentless reader.Next() call doesn't seem to make any sense. Maybe you meant reader.Next(.obj).

Also your code does not assign anything to ..Status variable, so why logging it?

Regards,
Dmitry

Yup you're 100% spot on. 

I got this to work once there then tried to sort out the error messages and it no longer correlates before realising that my firewall was starting to block the request. 

I had a lot of errors, mainly down to to Message Definition.  Will need to sort out the firewall  issue

Final code:

Method GetGPStatus(pRequest As Penn.EDT.Messages.GetGPStatusRequest, Output pResponse As Penn.EDT.Messages.ODSGPStatus) As %Status
{
Set pResponse = ##class(Penn.EDT.Messages.ODSGPStatus).%New()
Set rdr = ##class(%XML.Reader).%New()
    set httprequest = ##class(%Net.HttpRequest).%New()
    set httprequest.SSLConfiguration = "test"
    set httprequest.Https = 1
    set httprequest.SSLCheckServerIdentity=0
    Set tSC = rdr.OpenURL("https://directory.spineservices.nhs.uk/ORD/2-0-0/organisations/"_pRequest.GPCode_"?_format=xml",,httprequest)     do rdr.Correlate("Status","Penn.EDT.Messages.ODSGPStatus") If 'rdr.Next(.gpxml,.tSC) || $$$ISERR(tSC) { If '$$$ISERR(tSC) Set tSC = $$$ERROR($$$EnsErrGeneral,"Failed to correlate GPStatus")
Quit tSC
}
set pResponse.Status=gpxml.Status
    quit tSC
}

Class Penn.EDT.Messages.ODSGPStatus Extends (Ens.Response, %XML.Adaptor, )
{ Property Status As %String(XMLNAME = "value", XMLPROJECTION = "attribute"); Storage Default
{
<Data name="ODSGPStatusDefaultData">
<Subscript>"ODSGPStatus"</Subscript>
<Value name="1">
<Value>Status</Value>
</Value>
</Data>
<DefaultData>ODSGPStatusDefaultData</DefaultData>
<Type>%Library.CacheStorage</Type>
} }