Using one HL7 TCP business operation for multiple clients

59 views
Skip to first unread message

mikedaw99

unread,
Oct 31, 2011, 8:15:28 AM10/31/11
to Ensemble-in...@googlegroups.com

Does anyone have experience they could share of using one HL7 TCP business operation to talk to multiple clients?
This would involve dynamically allocating IP address and port for each invocation.
Thanks in advance!

MikeD

Lawrence Harris

unread,
Nov 2, 2011, 3:07:12 PM11/2/11
to <ensemble-in-healthcare@googlegroups.com>
I am doing this.

I have a table in Ens.LookupTable (for simplicity of initial setup) that has an entry for each client.  I pass the client info onwards via a temporary global using the session ID as the key.  This allows one operation to be the output portal for many clients and allows the work flow to be customized without having to generate dozens of variants of each operation (same applies for buisiness processes as well).  In essence I setup the inputs for the 'session' and the using the session ID I can lookup key data all along the path.  The temporary globals get cleaned up periodically when the system is cycled but get regenerated if you re-send a message from the beginning so that's not really a problem.

Class EDI.Operation.FileOperation Extends EnsLib.EDI.X12.Operation.BatchStandard [ ClassType = "", ProcedureBlock ]
{

Parameter ADAPTER = "EDI.Adapter.OutboundSFTPAdapter";

Method OnMessage(pRequest As EnsLib.EDI.X12.Document, Output pResponse As EnsLib.EDI.X12.Document) As %Status
{
#dim tmpObj As EDI.OutputDocument
Set tmpObj=pRequest
Set tSessionID=tmpObj.SessionID
Merge tSettings=^EDI.Temp("Request Data",tSessionID)
Set ..Filename=tSettings("SiteName")_"_%f_%Q.837"
Set ..Adapter.SiteName=tSettings("SiteName")
Set ..Adapter.ServerName=tSettings("ServerAddress")
Set ..Adapter.ServerPort=tSettings("ServerPort")
Set ..Adapter.UploadPath=tSettings("ServerUploadPath")
Set ..Adapter.DownloadPath=tSettings("ServerDownloadPath")
Set ..Adapter.Username=tSettings("Username")
Set ..Adapter.Password=tSettings("Password")
Set tFilePath=$Get(tSettings("RootFilePath"))
If tFilePath="" Set tFilePath=$Get(^Ens.LookupTable("EDIGlobalSettings","RootFilePath"),"C:\EDI")
Set ..Adapter.FilePath=tFilePath
// Do the work
Set pRequest=tmpObj.Document
Set tSc=##super(pRequest, pResponse)
Set pResponse=##class(EDI.Response.BillingBatchResponse).%New()
Set pResponse.DeliveryStatus=tSc
Quit tSc
}

Within a Business Process the look looks like this:

#dim process As Ens.BusinessProcess
Set tConfigName=process.%ConfigName
Set tSessionID=process.%PrimaryRequestHeader.SessionId
Merge tSettings=^EDI.Temp("Request Data",tSessionID)
Set context.EDIBusinessName=tSettings("BusinessName")
: etc

Hope that helps, Lawrence

ps.  If anyone knows of any gotcha's with this I would appreciate knowing.  So far I have not found any.
--
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

mikedaw99

unread,
Nov 8, 2011, 4:14:22 AM11/8/11
to Ensemble-in...@googlegroups.com
Thanks for the reply Lawrence. Using SessionID to tie everything together is the key to this.

MikeD

Tiffany Raczynski

unread,
Nov 16, 2011, 8:41:16 AM11/16/11
to InterSystems: Ensemble in Healthcare
Hi Mike,

Were you ale to get this to work with TCP? I'm curious because I have
a similar scenario. I am working with an interface where I may need
to create 30+ separate TCP operations that will potentially be
receiving the same data. The only difference may be the IP and port I
am sending to.

Thanks,
Tiffany

Lawrence Harris

unread,
Nov 16, 2011, 7:01:49 PM11/16/11
to <ensemble-in-healthcare@googlegroups.com>
For reference here is part of the code snippet I have at the beginning of my first Business Process.  The key item here is to get the SessionId from the request header, then cache all the configuration information in ^EDI.Temp.  This way as the messages flow around the various business processes and operations I can lookup any of the configuration data by grabbing the session ID from the message and looking it up in ^EDI.Temp(<sessionID>,…).

// Get Buisness Process Settings
//
//   Look at the incoming request message to find the cleint ID then use that to access
//   the customer specific parameters requried to create the basic X12 837 document.
//
//   This data is cached into ^EDI.Temp("Request Data",<ClientID>,...) so that other parts
//   of the production can work with the same set of settings and not have to look them up each time.
//
//   This roughly equivalent to the ##class(Ens.Director).GetHostSettings function except we need
//   settings based on the client and not on the Process.
//
#dim request As EDI.TransactionSetHeader
#dim process As Ens.BusinessProcess
Set tTimeStamp=$Translate($ZDateTime($Horolog,8,2),":")
Set tConfigName=process.%ConfigName
Set tBusinessName=request.BusinessName
Set tClientID=request.ClientID
Set tSessionID=process.%PrimaryRequestHeader.SessionId
//
Set tTable="EDI_Customer_"_tClientID
If '$Data(^Ens.LookupTable(tTable)) {
Set status=$$$ERROR($$$GeneralError,"Lookup table '"_tTable_"' not defined")
Quit
}
Set tClearingHouse=$Get(^Ens.LookupTable(tTable,"ClearingHouse"))
Set tCHSTable="EDIClearingHouse_"_tClearingHouse
If '$Data(^Ens.LookupTable(tCHSTable)) {
Set status=$$$ERROR($$$GeneralError,"Lookup table '"_tCHSTable_"' not defined")
Quit
}
//
// Save the settings in the temporary cache, merge the two tables so the cache contains
// the entries for both the client and the clearing house settings.
//
Merge ^EDI.Temp("Request Data",tSessionID)=^Ens.LookupTable(tTable)
Merge ^EDI.Temp("Request Data",tSessionID)=^Ens.LookupTable(tCHSTable)
//
// Add dynamic data to the table so we don't have to look it up again as well
//
Set ^EDI.Temp("Request Data",tSessionID,"ConfigName")=tConfigName
Set ^EDI.Temp("Request Data",tSessionID,"BusinessName")=tBusinessName
Set ^EDI.Temp("Request Data",tSessionID,"ClientID")=tClientID
Set ^EDI.Temp("Request Data",tSessionID,"TimeStamp")=tTimeStamp

Then to use it in later Business Processes (or Operation) I have this code at the beginning.

// Get Buisness Process Settings
//
//   Look at the incoming request message to find the business name then use that to access
//   the customer specific parameters requried to create the Interchange wrapper ISA/GS..GE/IEA
//
;Set tTimeStamp=$Translate($ZDateTime($Horolog,8,2),":")
#dim request As EDI.TransactionSetHeader
#dim process As Ens.BusinessProcess
Set tConfigName=process.%ConfigName
Set tSessionID=process.%PrimaryRequestHeader.SessionId
Merge tSettings=^EDI.Temp("Request Data",tSessionID)

In my Operation I have code like this.  The key here is to override the adapter parameters using data that I cached in ^EDI.Temp based on the incoming message.  This allows me to re-use the output operations (sFTP client in this case) and set the server address, port, usernames etc. as required.

Method OnMessage(pRequest As EnsLib.EDI.X12.Document, Output pResponse As EnsLib.EDI.X12.Document) As %Status
{
#dim tmpObj As EDI.OutputDocument
Set tmpObj=pRequest
//Set tOTrace=$Get(^Ens.Degut("TraceCat"))
//Set ^Ens.Debug("TraceCat")=1
$$$TRACE("Separators: Generic="_..ShowSep(..Separators)_", Document="_..ShowSep(tmpObj.Document.Separators))
//Set ^Ens.Debug("TraceCat")=tOTrace
// Force the Business Operations's separators to match those of the incoming document otherwise
// the output document seems to use the defaults from the Business Operation instead of any that
// were explicitly set in the incoming document.
Set tSep=..Separators
Set $Extract(tSep,3)=$Extract(tmpObj.Document.Separators,3)
Set ..Separators=tSep
// Get the session ID and then all the configuration parameters for this client/session.
Set tSessionID=tmpObj.SessionID
Merge tSettings=^EDI.Temp("Request Data",tSessionID)
Set ..Filename=tSettings("SiteName")_"_%f_%Q.837"
Set ..Adapter.SiteName=tSettings("SiteName")
Set ..Adapter.ServerName=tSettings("ServerAddress")
Set ..Adapter.ServerPort=tSettings("ServerPort")
Set ..Adapter.UploadPath=tSettings("ServerUploadPath")
Set ..Adapter.DownloadPath=tSettings("ServerDownloadPath")
Set ..Adapter.Username=tSettings("Username")
Set ..Adapter.Password=tSettings("Password")
Set tFilePath=$Get(tSettings("RootFilePath"))
If tFilePath="" Set tFilePath=$Get(^Ens.LookupTable("EDIGlobalSettings","RootFilePath"),"C:\EDI")
Set ..Adapter.FilePath=tFilePath
// Do the work
Set pRequest=tmpObj.Document
Set tSc=##super(pRequest, pResponse)
Set pResponse=##class(EDI.Response.BillingBatchResponse).%New()
Set pResponse.DeliveryStatus=tSc
Quit tSc
}

Hope that helps.

Lawrence

mikedaw99

unread,
Nov 17, 2011, 4:56:44 AM11/17/11
to Ensemble-in...@googlegroups.com
Hi Tiffany,
I only had to set up 5 operations so we haven't implemented this yet. As this design implies a connect and a disconnect for each change of IP/port the performance may not be great. Also as most systems reply with an HL7 ACK message the operation needs to wait for this before disconnecting and dealing with the next message.
Good luck!

Reply all
Reply to author
Forward
0 new messages