Question
· May 18, 2022

How to access the Settings of HL7 Router from within the HL7 Rule

Hello,

I want to access the HL7 Router settings from within the HL7 rule. Goal is to create a New class by extending  "EnsLib.HL7.MsgRouter.RoutingEngine".

Then create a PARAMETER ProcessMessage which can be set to an integer value for the HL7 Router.

Create a Rule class and based on the value of this setting ProcessMessage
process/not process the messages.

 

Class XYZRules Extends Ens.Rule.Definition [ CompileAfter = CUSTOM.Util.Rules.FunctionSet ]
{ Parameter RuleAssistClass = "EnsLib.HL7.MsgRouter.RuleAssist"; XData RuleDefinition [ XMLNamespace = "http://www.intersystems.com/rule]
{
<ruleDefinition alias="" context="EnsLib.HL7.MsgRouter.RoutingEngine" production="HL7Production">
<ruleSet name="" effectiveBegin="" effectiveEnd="">
<rule name="Discard" disabled="false">
<when condition="ProcessMessage=0">
<return></return>
</when>
</rule>.

.

.

.

Thanks,

Jimmy Christian.

Product version: HealthShare 2019.1
$ZV: Cache for Windows (x86-64) 2018.1.2 (Build 309_5_19475U)
Discussion (15)2
Log in or sign up to continue

The Settings are stored in Ens_Config.Item and can be retrieved  with

ClassMethod GetAdapterSettingValue() or ClassMethod GetHostSettingValue()

set SourceConfigName = "YourCustomRouter”  ;Must be enabled when non-unique

Set tSetting = "ProcessMessage"

Set tHostSettingValue=##class(Ens.Director).GetHostSettingValue(##class(Ens.Director).GetActiveProductionName()_"||"_SourceConfigName,tSetting,.tSC)

write !,"System.Status.GetErrorCodes "_$System.Status.GetErrorCodes(.tSC)_" : "_$System.Status.GetOneStatusText(.tSC)

write !,tSetting_" = ("_tHostSettingValue_") tSC=("_tSC_")"

Thank you Andy.

I am but not able to add a PARAMETER "RouteToDowntimeRouter
to my standard RULE Definition class. Once set i want to access it when the message goes through. Is there a way to add it in standard definition as below?

Class XYZRules Extends Ens.Rule.Definition CompileAfter CUSTOM.Util.Rules.FunctionSet ]
{ Parameter RuleAssistClass = "EnsLib.HL7.MsgRouter.RuleAssist"; XData RuleDefinition [ XMLNamespace "http://www.intersystems.com/rule]
{

Parameter SETTINGS = "RouteToDowntimeRouter";
Property  RouteToDowntimeRouter as %Boolean;


<ruleDefinition alias="" context="EnsLib.HL7.MsgRouter.RoutingEngine" production="HL7Production">
<ruleSet name="" effectiveBegin="" effectiveEnd="">
<rule name="Discard" disabled="false">
<when condition="ProcessMessage=0">
<return></return>
</when>
</rule>.

.

.

.

I meant a custom utility function, not a custom process.  It would be a class derived from Ens.Rule.FunctionSet.

An Ensemble rule expression must be constructed using + - * / Max Min etc.  That does not include the ability to use a generic ObjectScript expression.

You can add your own custom function, and inside it, you can use any ObjectScript expression that does what you want.  If you define a parameter in a class, you could make it a COSEXPRESSION; this parameter might be used by your custom function to obtain the value at run time and return it to your rule.

An alternative is to set a property in your BPL context object and simply use it in the rule. 

Have you browsed the sample rules provided in ENSDEMO?  There are some interesting examples of what you can do.

Heloisa

My mistake. I think i did not explain correctly.

So i want a setting in my HL7 Router something like below. I included it in my rule definition, but the SETTING is not showing in the Router in the management portal. Once i can have the SETTINGS  available in my Router, i can access its value. Let me know.

Property RouteToDowntimeRouter As %Boolean;

Parameter SETTINGS = "RouteToDowntimeRouter";
 

Hey @Jimmy Christian - Read through your responses to others to understand a bit more of what you're after. Short of creating a custom process class, there's no way to expose a setting on the Router in the Management Portal Production UX.

That said, if I understand what you are ultimately trying to achieve, might I suggest a simple Lookup Table named something like 'RouterDowntimeSettings' and then in that table, simply have some entries defined like:

Key Value
MyPkg.Rules.ClassName 1

Then inside your rules where you want to use this, you simply use the built-in Lookup function on that table and pass in the class name that you specified as the key. Might look something like this:

 

<rule name="Discard" disabled="false">
<when condition="Lookup('RouterDowntimeSettings','MyPkg.Rules.ClassName')=1">
<return></return>

Since Lookup returns empty string if the key is not found, this would only return true if a key was explicitly specified in the table, thus making it easy to implement as needed without causing unexpected errors or functionality.

Just an alternate approach that may work for you and reduce the amount of effort (no custom class creation that would need to be maintained). 

Edit: Fixed the boolean, didn't see your original was using returns.

Hey Craig,

Thanks for your response. Yes, that is a good alternate . I had initially thought about it but the only reason i am not planning to use a table is to avoid extra step to import this updated table in the prod environment. We cannot just make direct changes to the table because of some source control reasons also. So having a setting in the router which i can use just to flip it from 0 to 1 or vice versa would be very handy .

Thank you Craig.

That’s fair - another consideration then is something we also use - globals as “global parameters”. 
 

I.e. create a global like ^MyPkg(“DowntimeActive”) = <future $H value here> and then use a simple boolean check to see if current $H is less than the globals $H. Thus it automatically expires for us.  
 

We’ve evolved a bit beyond this now but for the source control reasons, it may be a simple solution. 

I have found another way around. Not perfect but can solve the problem i am having for the Settings valuesmiley

So i am thinking to use the Comment section of the Config Item. Then using the below function i can grab the value of it in my Standard Rule Class. Also i can change the value during downtime. Tested it and its working. If i dont find a way to create a CUSTOM Settings, i can use the "Comment" settings. !!

ClassMethod ShowComment(ConfigItem As %String) As %String
{
Set tSC=$$$OK Try{
    
     &sql(SELECT Comment INTO :tComment FROM Ens_Config.Item WHERE Name = :ConfigItem)
        If (SQLCODE = 0)
         {
Set tSC=$$$OK   
}
  } Catch(ex){
Set tSC = ex.AsStatus()
$$$LOGERROR("Error in function ShowComment: "_tStatus)  }
 tComment
}

Nice! This post is definitely a good example of a plethora of ways to solve the same challenge. :-)

We have scripts similar to yours above that use SQL on Ens_Config.Item to iterate through for auditing component settings on a daily basis to ensure our engineers don't do anything too crazy (on purpose or not!) and it has worked well for us for several years now so confident in saying it should be a decent approach for you as well!

Best of luck!

Jimmy

If you use the Comments section you eliminate the need to create your own custom routing engine.

Your ProcessMessage approach still should work.

Given your custom RoutingEngine includes the following statements:

Property ProcessMessage As %Boolean;

Parameter SETTINGS = "ProcessMessage:Catagory";

And if you issue a:

select Settings from Ens_Config.Item where Production = ‘YourProduction’

 and Name = ‘YourProcessName’

Do you see “ProcessMessage” in Settings List?