Hi Daniel,

I had put together a simple diagram that describes the process.

There is a lot of custom code and also several globals on the back end of which I have yet to learn. We are pulling a lot of data and from what I understand, a lot of the work was performance-related. I don;t have a lot of documentation. Hopefully, your use case is a bit simpler than ours.

   

Hi Daniel,

We had done this at one of our clients. We have Stored Procedures that are sitting on a SQL Server and are activated by a custom Business Operation (with a SQL.OutboundAdapter) which receives a trigger message with the needed parameters from a Trigger Business Service. The Stored Procedure can return SQL Results as XML which is what we had done... it is then easy to read that XML and extract data from it.

This was a large project (which I inherited) so it is possible that you may not need something this complex. And there could be other ways to do this. I can provide more details if you are interested.

Hello Yuri,

I think you have two strategies:

1) Use Dynamic Objects to traverse your JSON Arrays in loops and extract your fields by saving them directly to your SDA Properties. This is what I had done a couple of years ago when I had to get data from a product that could only output JSON. Once you have your final SDA you can then write it to a file.

2) Since you are on IRIS, you can use %JSON.Adaptor. I had not used it but I think it works just like %XML.Adaptor. If your class inherits from %JSON.Adaptor, it is basically aware of your JSON structure. You can then create Cache Objects as your data model for your incoming JSON and simply copy their Properties to SDA Properties.

I hope this helps. 

Vitaly

Thank you Marc for your prompt response.

The only thing that led me to the Custom Pairs trail is this code in HS.Gateway.HL7.HL7ToSDA3:

#; TXA-2 : DocumentType
    #; For "DS", default Description to "DischargeSummary" (JLD190)
    if $$$TXADocumentType = "DS" {
        do ..write(cr_"<DocumentType>")
        do ..write(cr_"<Code>DS</Code>")
        do ..write(cr_"<Description>DischargeSummary</Description>")
        do ..write(cr_"</DocumentType>")
    }
    elseif $$$TXADocumentType'="" {
        do ..write(cr_"<DocumentType>")
        do ..write(cr_"<Code>"_$$$TXADocumentType_"</Code>")
        do ..write(cr_"</DocumentType>")
    }

However, since that class had already been extended, I can add 

 do ..write(cr_"<Description>"_$$$TXADocumentDescription_"</Description>")

and it will get stored in the SDA.

The one exception might be Discharge Summaries since the Clinical Viewer seems to expect "DS" in the DocumentType.Code property. Unless there is a way to modify that behavior, I may have to use CustomPairs just for that case and then alter the SDA3 to FHIR transform when it is time to store in a FHIR Resourse

Hi Virat,

From what I understand, this is very similar to Static Methods and Instance Methods in Java. Instance methods are the behaviors on a particular object... you can run them only after you create the object with .New(). Class methods, on the other hand, are available without having to create an object first. 

There is probably a more formal answer out there, but I typically use Class Methods when I write a Utility class with lots of methods that do specific tasks and that may need to be available from several entry points to the application. On the other hand, when I design Objects with Properties and Methods, the methods are typically Instance methods.

OK, try to put the following in your custom Business Operation:

Parameter OUTPUTTYPEATTRIBUTE = 0;

Your parent business operation is using a WebClient "HS.MPI.HSPI.APIWebServicesClient" (line 56); and that class has this parameter set to 1. Since your error is about Type Attribute, this might help.

Also, to troubleshoot this, login to your HSPI Server from command line, go to Cache prompt and activate SOAP logging:

NAMESPACE>Set ^ISCSOAP("LogFile")="/tmp/SOAP.log" (or ="C:\tmp\SOAP.log" if Windows)

NAMESPACE>Set ^ISCSOAP("Log") = "ios"

The 2nd line activates the logging. Then run your test you you can examine the contents of your log file. 

To turn off SOAP log, type:

NAMESPACE>Set ^ISCSOAP("Log") = ""

You can email me the SOAP Log or attach it here...

Hi Warren,

I looked at the class that you extended. I happen to think that the issue is not with the Request message but with the Business Operation that you are using.

All Ensemble Business Operations rely on Web Service calls. Under the hood, they all instantiate a WebClient object that is calling one of the exposed methods on a Web Service (which typically sits on another machine). In this case, your Business Operation is calling a PatientSearch method on HSPI.Server.APIWebService.

The issue seems to be this: InterSystems relies on SOAP almost exclusively for its internal Web Service calls. There is a lot of stuff that needs to be set correctly for a SOAP Web call to complete successfully. ISC uses Adapters for all kinds of message protocols; and in this case, you need either HS.Util.SOAPClient.OutboundAdapter or its parent, EnsLib.SOAP.OutboundAdapter (likely, you need the child here). 

The good news is, ISC had already extended HS.MPI.AbstractOperations with HS.MPI.HSPI.Operations and implemented PatientSearch in this class. HS.MPI.HSPI.Operations already has an ADAPTER set. I would advise you to extend HS.MPI.HSPI.Operations and override the PatientSearch method in your descendand class. 

Given that the ADAPTER sets 90% of needed Parameters and Properties, you might be OK. The HSPI.Server.APIWebService class has XMLIGNOREINVALIDTAG set to 1 so it should already be taking care of invalid tags.

Please write back if these changes do not help