Acquiring and using the process name or source name in a routing rule condition

158 views
Skip to first unread message

LKO

unread,
Oct 2, 2012, 5:46:07 PM10/2/12
to Ensemble-in...@googlegroups.com
We have a custom function that we plan on using in the routing rules for most Business Processes. One of the function's arguments is the source system from which the HL7 message was received. Since in our environment we name a Process to match the Service with which it is associated, the name of the Business Process that has called the custom function would meet our needs. Better yet by far would be to use the Source from the rule's Constraint, because that positively identifies the source system.
 
Is either the name of the calling Business Process or the value of a Constraint's Source available as a variable or via a function call so that it can be supplied as an argument to our custom function? We currently just send the value as a string, but if we had a way of acquiring the value, we wouldn't have to worry about misspelling the argument value, and we could copy the rule from one Process to another without having to subsequently change the argument value.

Marc Lang

unread,
Oct 3, 2012, 3:46:48 AM10/3/12
to ensemble-in...@googlegroups.com
I asked a similar question (I think) not too long ago.
If you look at the business process property %PrimaryRequestHeader.SourceConfigName, this should hold the name of the service that sent the request.
You could then set it in context or such like and use it in business rules?
Does that help?

On 2 October 2012 22:46, LKO <willy...@hotmail.com> wrote:
We have a custom function that we plan on using in the routing rules for most Business Processes. One of the function's arguments is the source system from which the HL7 message was received. Since in our environment we name a Process to match the Service with which it is associated, the name of the Business Process that has called the custom function would meet our needs. Better yet by far would be to use the Source from the rule's Constraint, because that positively identifies the source system.
 
Is either the name of the calling Business Process or the value of a Constraint's Source available as a variable or via a function call so that it can be supplied as an argument to our custom function? We currently just send the value as a string, but if we had a way of acquiring the value, we wouldn't have to worry about misspelling the argument value, and we could copy the rule from one Process to another without having to subsequently change the argument value.

--
You received this message because you are subscribed to the Google Groups "InterSystems: Ensemble in Healthcare Community" group.
To post to this group, send email to Ensemble-in...@googlegroups.com
To unsubscribe from this group, send email to Ensemble-in-Healt...@googlegroups.com
For more options, visit this group at http://groups.google.com/group/Ensemble-in-Healthcare?hl=en

LKO

unread,
Oct 3, 2012, 3:55:48 PM10/3/12
to Ensemble-in...@googlegroups.com
Thanks for the reply.
 
Being new to Ensemble (training was four weeks ago), I don't know how to use the variable in the routing rule. I tried it just as you gave it, which caused an error, and I also tried it enclosed in quotation marks, which just was interpreted as a string. How would I use that variable name as an argument to a function?

Marc Lang

unread,
Oct 4, 2012, 8:18:34 AM10/4/12
to ensemble-in...@googlegroups.com
I'm not 100% clean on what you want to do, but I will try describe a process and it may work for you:

1) Create a context property on your BPL, a %String called something like "SourceConfigName"
2) Create an "Assign" action, setting the property you just created, and give it a value: ..%Process.%PrimaryRequestHeader.SourceConfigName

This will set the value when a message is received by the BPL.

3) From there, in a Business Rule, you will have access to the SourceConfigName property.
4) If within a Business Rule/Message Router you calling it from a utility function, your Condition could look something like:

IF SomeFunction(SourceConfigName) = "1"

Hopefully this helps.

--

Marc Lang

unread,
Oct 4, 2012, 8:18:56 AM10/4/12
to ensemble-in...@googlegroups.com
Not 100% *clear*,

I am in fact clean.

LKO

unread,
Oct 4, 2012, 2:50:37 PM10/4/12
to Ensemble-in...@googlegroups.com, ensemble-in...@googlegroups.com
I'm not using BPL for this Business Process; I'm using a regular routing rule.
 
What I need to do is either pass the config name as an argument to my custom function (which is called in a routing rule condition node), or get the value of the config name somehow within the custom function itself.

Ted Peck

unread,
Oct 4, 2012, 3:27:48 PM10/4/12
to ensemble-in...@googlegroups.com, LKO
Try %Ensemble("%Process").

LKO

unread,
Oct 4, 2012, 4:00:58 PM10/4/12
to Ensemble-in...@googlegroups.com, ensemble-in...@googlegroups.com, LKO, t...@intersystems.com
I tried that in my function, and it returns "3...@EnsLib.HL7.MsgRouter.RoutingEngine".
Below is the statement from my function:
 
 set myVar = %Ensemble("%Process")

On Thursday, October 4, 2012 2:27:51 PM UTC-5, Ted wrote:
Try %Ensemble("%Process").

Lexi Hayden

unread,
Oct 4, 2012, 4:05:34 PM10/4/12
to Ensemble-in...@googlegroups.com, ensemble-in...@googlegroups.com, LKO, t...@intersystems.com
That is an OREF and you can presumably use it to get the detail you want. The class in question has a property named %ConfigName.

HTH. I am not certain how to use this information in your particular context.

Ted Peck

unread,
Oct 4, 2012, 4:20:10 PM10/4/12
to Lexi Hayden, Ensemble-in...@googlegroups.com, LKO, t...@intersystems.com
Or try %Ensemble("ConfigName") - I should have suggested that first.

LKO

unread,
Oct 4, 2012, 4:38:33 PM10/4/12
to Ensemble-in...@googlegroups.com, Lexi Hayden, LKO, t...@intersystems.com
I'm getting close. Both of the approaches you suggested work. Using your most recent suggestion, the statement below returns the Business Process name:
 
set myVar = %Ensemble("ConfigName")
 
I got it to return the same value using your first approach, although it took two set statements to do so:
 
set myVar = %Ensemble("%Process")
set myVar2 = myVar.%ConfigName
 
(I couldn't get the above to work by combining the properties in a single statement.)
 
Now, if I could get the Source property for the ConfigName item, I'd be where I need to be.
Is the object model of these properties documented somewhere? I haven't been able to find such documentation.

Dale du Preez

unread,
Oct 4, 2012, 4:55:55 PM10/4/12
to ensemble-in...@googlegroups.com
Hi LKO,

Can we take a step back here? Which version of Ensemble are you running? I believe the new rules engine in 2012.1 and 2012.2 may make this easier for you. Before we start chasing after %-variables I think it may be worth looking at the standard properties first!

Dale

LKO

unread,
Oct 4, 2012, 4:59:34 PM10/4/12
to Ensemble-in...@googlegroups.com, ensemble-in...@googlegroups.com
2012.2
To unsubscribe from this group, send email to Ensemble-in-Healthcare-unsub...@googlegroups.com

Dale du Preez

unread,
Oct 4, 2012, 5:16:35 PM10/4/12
to ensemble-in...@googlegroups.com
Hi LKO,

You should simply be able to refer to the Source context property for the source of the message. This property should be available in all contexts, including in function calls.

I did some investigation into the way we handle the ConfigName, and see that we don't project it as cleanly. At present, it looks like you may need to use a custom function that includes code like the following:

ClassMethod GetRouterConfigName() As %String
{
    Set tConfigName =  $get(%Ensemble("ConfigName"))
    Quit tConfigName
}

I hope that helps,
Dale
To unsubscribe from this group, send email to Ensemble-in-Healt...@googlegroups.com

LKO

unread,
Oct 4, 2012, 5:30:28 PM10/4/12
to Ensemble-in...@googlegroups.com, ensemble-in...@googlegroups.com
In one of my earlier posts today, I explained that I used the approach you mention (although I did not use the $get; it works fine without it). That worked insofar is it does return the name of the Business Process that called the custom function. However, I am wondering whether the Source property from the Constraint is available as well.

LKO

unread,
Oct 4, 2012, 6:07:57 PM10/4/12
to Ensemble-in...@googlegroups.com, ensemble-in...@googlegroups.com
To clarify, it's not necessarily the Source from the Constraint that I need. Rather, it's the name of the Service through which the message arrived. Granted, those may be the same thing, but I wanted to make clear what I'm looking for.

Dale du Preez

unread,
Oct 4, 2012, 6:32:46 PM10/4/12
to <ensemble-in-healthcare@googlegroups.com>
Hi LKO,

If you specify the string "Source", without the quotes in an expression or condition, that should refer to the source from which the message was sent. It seems not to be showing up in my autocomplete all the time, but it should work!

Dale
To unsubscribe from this group, send email to Ensemble-in-Healt...@googlegroups.com

LKO

unread,
Oct 5, 2012, 9:52:01 AM10/5/12
to Ensemble-in...@googlegroups.com, <ensemble-in-healthcare@googlegroups.com>
That did it!
Thanks for the tip.
To post to this group, send email to Ensemble-i...@googlegroups.com

LKO

unread,
Oct 5, 2012, 9:59:54 AM10/5/12
to Ensemble-in...@googlegroups.com, <ensemble-in-healthcare@googlegroups.com>
Now that I've got the Source working, I've got another question: Is there also a property for the HL7 message by which I could pass the entire message as an argument to my custom function?
To post to this group, send email to Ensemble-i...@googlegroups.com

LKO

unread,
Oct 5, 2012, 10:13:22 AM10/5/12
to Ensemble-in...@googlegroups.com, <ensemble-in-healthcare@googlegroups.com>
Found it.
It's HL7.RawContent.

Dale du Preez

unread,
Oct 5, 2012, 10:46:09 AM10/5/12
to ensemble-in...@googlegroups.com
Hi LKO,

RawContent only returns the first 10,000 characters from the HL7 message.

What problem are you trying to solve that you need all the raw HL7 content...? I suspect that you may be able to achieve your goal without manipulating the raw string data, but it might be better to describe the end goal before we dig into implementation specifics.

Dale
To unsubscribe from this group, send email to Ensemble-in-Healt...@googlegroups.com

Ted Peck

unread,
Oct 5, 2012, 11:52:27 AM10/5/12
to ensemble-in...@googlegroups.com
If you really need the content as a string, you'd be better off using the method OutputToString() instead of property RawContent.

However I agree with Dale - it sounds like what you are trying to do may be highly inadvisable. You should really call the WRC and explain your goals and ask for advice.  Or you can ask us on this list.

Ted

LKO

unread,
Oct 5, 2012, 12:52:41 PM10/5/12
to Ensemble-in...@googlegroups.com, ensemble-in...@googlegroups.com
Our custom function checks for duplicate messages, which happens occasionally for some of our systems. Although most source systems supply a Message Control ID in MSH 10, not all do. For those that do supply an MSH 10 value, we pass that to the custom function. For those that don't we pass the entire message.
 
For this purpose, I believe that the 10,000 character limit is not be a problem because 1) we rarely if ever get messages that large, and 2) if the messages are the same through 10,000 characters, they're likely duplicates.

LKO

unread,
Oct 5, 2012, 1:00:19 PM10/5/12
to Ensemble-in...@googlegroups.com, ensemble-in...@googlegroups.com, t...@intersystems.com
How would I use the OutputToString method in a routing rules condition? I must have to pass it the message as an argument, so how would I do that?
Would that produce a string that is the entire message instead of just 10,000 characters at most?
And what is the disadvantage to using the RawContent property?

Ted Peck

unread,
Oct 5, 2012, 1:18:04 PM10/5/12
to LKO, Ensemble-in...@googlegroups.com
I forgot you were looking to use this as an argument to a custom FunctionSet function from a Rule. You're right, you'd have to use code in your function to get the current header, get the HL7 message body, and then get the HL7 content from the body.

It sounds like you're building a whole new router inside your new rule function.  Maybe you'd just like to build a custom router class instead?

LKO

unread,
Oct 5, 2012, 1:39:02 PM10/5/12
to Ensemble-in...@googlegroups.com, LKO, t...@intersystems.com
No, the custom function is pretty simple, and I shouldn't need a custom router class. It takes the source and the Message Control IDs as arguments, and returns true or false depending on whether the message is a duplicate. The custom function is called in a condition node in a regular ol' routing rule.
 
To determine whether the message is a duplicate, it retrieves a global that has the Source's previous control ID, returns true if it matches the one in the function argument; otherwise, it saves the new control ID in the global and returns false. That's it.
 
In those cases where the source system does not supply a Message Control ID, we would use the entire message as that argument. So if OutputToString is preferable to RawContent, I just need to know how to use that method in a routing rule condition.

LKO

unread,
Oct 5, 2012, 1:41:26 PM10/5/12
to Ensemble-in...@googlegroups.com, LKO, t...@intersystems.com
Regarding your comment about getting the content within the function (throught the header and message body), can you share the syntax? Or point me to the place in the documentation that explains it?

On Friday, October 5, 2012 12:18:06 PM UTC-5, Ted wrote:

Ted Peck

unread,
Oct 5, 2012, 3:04:33 PM10/5/12
to LKO, Ensemble-in...@googlegroups.com
It seems to me that 10k of content should be sufficient to uniquely identify a message so RawContent should serve you fine. You could even do a hash of that 10k and be pretty confident.  For this purpose that's what I would recommend, to save you from storing the whole message as a ControlId.

Here is a hash that we sometimes use: $$$NUM($ZHex($ZCRC(RawContent,7)),8).  This is padded with leading zeroes in case the CRC value comes out short.

However if you're only storing it for one single message then using the RawContent as is should also be fine. That implies that duplicate messages will only ever arrive back-to-back which sounds like what you're expecting.

Ted

PS. Although I don't think you'll need it, here is how you could get the full content as a string (assuming it's less than the max string size of your system)

Set RawContent=##class(EnsLib.HL7.Message).%OpenId(%Ensemble("%Process).%PrimaryRequestHeader.MessageBodyId).OutputToString()

PPS. Looking at the code I see that RawContent is only truncated when retrieved via SQL. When retrieved as an object property as it would be in the Rules engine it is exactly the same as OutputToString() with no arguments. The reason we don't recommend it is because it will still be truncated at the max string length and you don't have control over separators and other optional parameters. Neither of these really matter for your use case however. String length is no longer such an issue because we now ship with long strings enabled which bumps the number from 32k to 4G I believe.

LKO

unread,
Oct 5, 2012, 4:13:59 PM10/5/12
to Ensemble-in...@googlegroups.com, LKO, t...@intersystems.com
I might give your statement a try.
 
Can the Message Control ID itself be obtained within a function in a similar fashion?
What about the Source?
 
If I can get all these values using statements within my function, I wouldn't need to use function arguments (other than one argument to let the function know whether it should use the Message Control ID or the entire message as the comparison value).
 
And your assumption is correct: The intention of this function is to catch back-to-back duplicates.

LKO

unread,
Oct 5, 2012, 5:13:11 PM10/5/12
to Ensemble-in...@googlegroups.com, LKO, t...@intersystems.com
It doesn't like something about the syntax of your set statement. For one thing, there is only one quotation mark.

On Friday, October 5, 2012 2:04:35 PM UTC-5, Ted wrote:

Ted Peck

unread,
Oct 5, 2012, 5:43:56 PM10/5/12
to LKO, Ensemble-in...@googlegroups.com, t...@intersystems.com
Source is in %Ensemble("%Process").%PrimaryRequestHeader.SourceConfigName
MessageControlId is in ##class(EnsLib.HL7.Message).%OpenId(%Ensemble("%Process").%PrimaryRequestHeader.MessageBodyId).Identifier
or HL7.Identifier or HL7.{1:10}

One problem with not using arguments is you can't test your function or your rule outside of a running BusinessProcess.

LKO

unread,
Oct 5, 2012, 6:05:03 PM10/5/12
to Ensemble-in...@googlegroups.com, LKO, t...@intersystems.com
Works great. Thanks again.
I suppose I could enable the function to be tested outside a Business Process by defining arguments, but making them optional.
Reply all
Reply to author
Forward
0 new messages