Business rule classes store the rules as XML in an XData block with the name "RuleDefinition":

Class Demo.Rule.GenericRouter Extends Ens.Rule.Definition
{

Parameter RuleAssistClass = "EnsLib.MsgRouter.RuleAssist";

XData RuleDefinition [ XMLNamespace = "http://www.intersystems.com/rule" ]
{
<ruleDefinition alias="" context="EnsLib.MsgRouter.RoutingEngine" production="TESTINGPKG.FoundationProduction">
<ruleSet name="" effectiveBegin="" effectiveEnd="">
<rule name="">
<when condition="1">
<send transform="Demo.DTL.Generic" target="Test.DummyOperation"></send>
<return></return>
</when>
</rule>
</ruleSet>
</ruleDefinition>
}

}

One approach would be to find all of your business rule classes, retrieve the "RuleDefinition" XData block for each one, and then parse the XML to see which DTLs are called.

To find the business rule classes, have a look at %Dictionary.ClassDefinition. You could do a query like this to find your business rule classes:

select ID from %Dictionary.ClassDefinition where super='Ens.Rule.Definition'

Then, for each business rule class you can find the %Dictionary.XDataDefinition for the RuleDefinition XData block with a query like this:

select ID from %Dictionary.XDataDefinition where parent='Demo.Rule.GenericRouter' and name='RuleDefinition'

The raw XML from the XData block can be accessed via the stream object stored in the "Data" property of the %Dictionary.XDataDefinition row.

Have you considered using web services to exchange messages between the productions? This has the advantage of allowing the two productions to later be placed on separate instances.

If you want to do it through the mapped DB, you could write a custom business operation to store the records in a custom table which is mapped to from both namespaces and then write a custom business service that polls that table for new entries.

I have 2 productions A and B on the same IRIS instance sharing one operational database.

To be sure the two productions aren't conflicting with each other, I'm assuming that only custom tables/globals are mapped to the shared database and not any of the Ens* globals/tables/routines/packages.

Are these standard HL7 batch headers and footers (BHS/BTS, FHS/FTS, etc) or something custom to your organization?

If they are one of the HL7 standards, have a look at these docs on HL7 batches:
https://docs.intersystems.com/healthconnect20191/csp/docbook/Doc.View.cl...

One tricky part will be triggering when an old batch ends/new batch begins -- this will depend on your local requirements.

If they are custom, there are a few approaches you can consider:

  1. You could use the Record Mapper to define a record map class with header/footer and a single field record for the HL7 content. You would then use one of the  EnsLib.RecordMap.Operation.* classes instead of EnsLib.HL7.Operation.FileOperation: https://docs.intersystems.com/healthconnect20191/csp/docbook/DocBook.UI.... In particular, have a look at RolloverSchedule and/or RolloverLimit to control when a new batch file is created.
  2. If you're comfortable creating a custom class that extends EnsLib.HL7.Operation.FileOperation, you could override the outputDocument method. In your custom version of outputDocument you could check if the file already exists using ##class(%File).Exists(pathToFile) and if it doesn't you would write out the footer to the previous file and the header to the new file before calling the standard version of outputDocument using ##super. https://docs.intersystems.com/healthconnect20191/csp/docbook/Doc.View.cl...

A few questions:

  • You didn't mention what format these files are in -- XML? flat-file/CSV? Something else?
  • Which InterSystems product are you working with and what kind of application is this (interoperability production, web service, etc.)?

If these are flat-files or CSV, and if you're working with a Health Connect or IRIS interoperability production, you can look at using the Record Mapper, which will read a flat file using a format you define and allow you to work with records from the file as objects:
https://docs.intersystems.com/healthconnect20191/csp/docbook/DocBook.UI....

If the files are XML you can do something similar by importing an XSD and using XML virtual documents, or use %XML.Adaptor methods:
https://docs.intersystems.com/healthconnect20191/csp/docbook/DocBook.UI....

Ok, EnsLib.REST.GenericOperation also expects to receive an EnsLib.HTTP.GenericMessage.

Are you using EnsLib.File.PassthroughService to pick up the files? If so, it is sending an Ens.StreamContainer message to the target component (your business operation). You'll need to create a data transformation that creates a new EnsLib.HTTP.GenericMessage and populates it with the stream content from the Ens.StreamContainer. Then you'll need a router in the middle to run the data transformation and send the resulting EnsLib.HTTP.GenericMessage to the business operation.

Neerav, I'll just note that if you use Jenna's suggestion your code doesn't need to be a part of a business service -- it can be any normal ObjectScript code and can be called from anywhere (CSP, scheduled task, etc.). And your code can make as many calls as it needs to and can receive response messages.

It will appear in message traces as if a business service sent requests to the process or operation, but in reality it's just your code sending the requests.

Jenna's approach is a good one, and it's the standard way to achieve what you describe. Having said that, if you can provide more details on your use case and/or why this approach doesn't fit your need we can help you explore alternatives.

My understanding is that the Caché application is terminal based (accessed on the client PC through telnet).

The signature device connects to the client PC using USB.

So the question/challenge is for the terminal-based application to send a request to the signature device when a signature is needed and to receive the signature image.

Seems like you need a daemon running on the PC which uses the signature device's SDK to communicate with it. The daemon would then exchange messages with Caché to manage the signature process -- possibly via web services or web sockets.