Hi Ed,

If you have the Show Query option enabled in Message Viewer, you can build your criteria for extracting the message data there, then click the button to see the SQL it generates. The default EnsLib.HL7.SearchTable indexes the Patient ID, but it includes PID:2.1, PID:3.1 (all iterations) and PID:4.1 (all iterations). If you're searching for specific IDs or ranges you may get unintended duplicates.

You don't need a custom SearchTable to filter the messages, but it sure helps.

If you don't have it enabled, you can turn it on for your production's namespace:

USER > zn "PROD"
PROD > set ^Ens.Debug("UtilEnsMessages","sql")=1

The Message Viewer is a powerful tool and gives you access for query and display of every HL7 field. The SQL it generates should put you on the right track.

The "N" parameter always creates a new file. If you want to open a file (optionally creating it if it doesn't exist), use "E" instead,  and if you intend to Append to it, include the "A" parameter: open file:("EWA"):1. You don't need the "R" parameter unless you intend to read from it using the same device.

Depending on your Cache configuration, you may not even need the "E" parameter. The default behavior in my Windows installation is to create the file if it doesn't exist, with or without the "E" parameter (the documentation refers to "E" as  "UNIX-only", FYI).

Adding categories will  have no direct impact on message processing. As you noted, there may be a tiny incremental increase in overhead temporarily if you query for them, and you may see a slight delay in the drop-down list ... but only if  you're talking about multiple hundreds of them.

If the intent is to better document your interfaces, though, take a look at the Business Partner configuration. It's an often-overlooked option to keep details regarding the vendor, its contacts, and other information associated with each interface. This may help make the number of categories more manageable.

Wow, I would think this is a potential security risk. I'm assuming the smart IRIS/Cache Administrator would remove any permissions to create or modify web app settings ...

The answer, while very clever, also assumes access to tools other than Studio. Can the requested solution be provided with Studio alone, and, more importantly, will it be possible for the administrator to prevent this sort of access?

 The other thing that just occurred to me is that the vendor is dumping a stack trace that may contain print control characters such as carriage returns, and the operation is simply treating the first \x0d as the end of the segment. That would effectively exclude the rest of the stack trace from the message body for conventional parsing purposes. The data is likely still there, but it can't be parsed out as part of MSA;3 with the parsing rules defined in the ACK's schema.

I haven't had the need to do this yet, but my guess is you're going to have to create a custom operation that modifies the received NAK via the OnReplyDocument() method. If the stack trace is really big, it may be stored as a Stream Object rather than a %String. And if that's the case, you're going to have to scan the Stream for the string you need, and replace the contents of the MSA:3 with that string.

I'd whip up an example for you but I'm headed out the door and will be OoO for the day. I'll check back tonight to see if anyone's beaten me to it :D

As @Eduard Lebedyuk pointed out, the method should return a status as indicated by its signature, so at the very minimum you should have a "Return $$$OK" at the end of the method.

That said, %FromJSON() throws an exception when it fails, and the generic error you'll get in the Event Log won't tell you (or your support team) much. You may want to wrap a try/catch around the call to %FromJSON() so that you can return a status that provides a little more insight:

    ...

    Try {
        set tJSON = {}.%FromJSON(pInput)
    } Catch {
        Return $$$ERROR($$$GeneralError,"Badly formed JSON")
    }

...

    Return $$$OK
 }

The only reason I can think of doing it the way it was done is that there was no expectation by the original author of the code that the JSON object would be larger than 32KB. It's also possible that he/she was unfamiliar with the types of objects that %FromJSON() works with and always assumed it was a simple string ... which is what the ReadLine() method returns.

Here's the documentation for for the %FromJSON() method.

Probably something like this (I'm not sure of the full name of the osuwmc.PatientBilling... class, and you probably want to do some sort of exception handling or at least error checking):

       set callrequest = ##class(osuwmc.PatientBilling.DataStructures.SelectResearchID).%New()

       set callresponse = ##class(EnsLib.SQL.Snapshot).%New()

       set callrequest.ResearchID = context.RschMRN

       do process.SendRequestSync("PatientBillingDBPoll", callrequest, .callresponse)

       set context.ClarityRS = callresponse

The default behavior of SendRequestSync is to never timeout, but you can always include a -1 as the 4th parameter to be a bit more descriptive.

Hi Scott,

I've accomplished this in the past by calling the SQL Operation with the SendRequestSync() method in a <code> action rather than using the <call> action. The default is to wait until the response is received.

This will be problematic if you must maintain FIFO (thus setting the Pool Size to 1), since the BPL will stop processing until the response is received. And increasing the pool size could have undesirable side effects other than loss of FIFO ... so you're likely to see horrible message latency at times given the metrics you're reporting.

EDIT: Stelios of course beat me to it ... I stepped away from the keyboard before hitting the Publish button and only realized it some hours later laugh

If each Encounter element in the document contains all of the data necessary to create your individual HL7 messages, you could potentially use the EnsLib.XML.Object.Service.FileService (or FTPService) class for a Business Service that will "chunk" the document into individual Encounter documents. Those would then be mapped to HL7 via a routing rule and DTL ... no BPL required. You'll need to create an Encounter class that matches the Encounter element structure; this will be used subsequently for creating routing rules and DTLs.

I guess it's worth trying, but I have a gut feeling that it won't work. If it doesn't ...

You could accomplish this in a BPL, but you would have to build the response logic from the BO along with the filtering/routing logic.

You could alternately create a custom BO that simply generates NACKs and set the send target in your otherwise to that ... just override the OnMessage() method:

Class HICG.HL7.Operation.NackFactory Extends Ens.BusinessOperation
{

Parameter INVOCATION = "Queue";

Method OnMessage(pRequest As EnsLib.HL7.Message, Output pResponse As EnsLib.HL7.Message) As %Status
{
    Set pResponse = ##class(EnsLib.HL7.Message).%New()
    Set pResponse.DocType = "2.3.1:ACK"
    Do pResponse.SetValueAt(pRequest.GetValueAt("MSH"),"MSH")
    Do pResponse.SetValueAt("ACK","MSH:9")
    Do pResponse.SetValueAt("MSA|AE|"_pRequest.GetValueAt("MSH:10")_"|No Destination","MSA")
    Do pResponse.%Save()
    Quit $$$OK
}

This is obviously not robust code, but it does generate a NACK as a response object for every message sent to it, and if the BP is configured to forward responses from the Production BO created based on this, you'll get what you're looking for.