web stats
Mirth validates '?' as correct HL7 response - Mirth Community

Go Back   Mirth Community > Mirth Connect > Support

Reply
 
Thread Tools Display Modes
  #1  
Old 11-25-2013, 01:02 AM
seaston seaston is offline
OBX.3 Kenobi
 
Join Date: Feb 2010
Location: London, UK
Posts: 168
seaston is on a distinguished road
Default Mirth validates '?' as correct HL7 response

I am really puzzled by the responses that are being validated as HL7 acks from the channel I have just set up.

I am sending via TCP MLLP to another system using Mirth Connect version 3.0. I have "Process HL7 Ack" set to 'Yes', but I am seeing '?' in the response window coming back as the ack, even when I sent a bad message. The messages are all marked as SENT.

I have attached a screenshot showing the response, and the channel concerned.

Is anyone able to explain what I am seeing?
Attached Images
File Type: jpg Screenshot - 25_11_2013 , 09_52_48.jpg (71.9 KB, 50 views)
Attached Files
File Type: xml TEST iCM Theatre Visit Cancellations.xml (29.2 KB, 10 views)
Reply With Quote
  #2  
Old 11-25-2013, 04:58 AM
seaston seaston is offline
OBX.3 Kenobi
 
Join Date: Feb 2010
Location: London, UK
Posts: 168
seaston is on a distinguished road
Default

Just a little further information to help. The character that is sent back in the response is in fact ascii 6 (ACK), but I did not expect the TCP interface to have validated this as an HL7 positive acknowledgement so I am still puzzled.
Reply With Quote
  #3  
Old 11-25-2013, 08:41 AM
narupley's Avatar
narupley narupley is online now
Mirth Employee
 
Join Date: Oct 2010
Posts: 7,119
narupley is on a distinguished road
Default

Thanks for finding that; I've opened an issue for it: MIRTH-3069

You're right, the message should say ERROR (or QUEUED if queuing is enabled) when a response like that is received. Is the server you're sending to expecting MLLPv2? The "standard" MLLP most people are used to is actually v1. The client sends a message wrapped like <0x0B>message<0x1C><0x0D>, and the server responds with <0x0B>response<0x1C><0x0D>. However in version 2 of the standard, this is what happens:
  1. The client sends a message like <0x0B>message<0x1C><0x0D>
  2. The server responds with <0x0B><0x06><0x1C><0x0D>
  3. The server sends an additional response: <0x0B>response<0x1C><0x0D>
  4. The client responds to the server with: <0x0B><0x06><0x1C><0x0D>

If all you're receiving is an ACK character, that would lead me to believe that the server is using the MLLPv2 standard. Mirth Connect 2.x did not support that transmission mode, but 3.0 actually does now. If you go into your TCP Sender settings and hit the wrench button, it will take you to the MLLP transmission mode settings. In there you can enable MLLPv2 mode (by default it uses the standard v1).

__________________
Step 1: JAVA CACHE...DID YOU CLEAR ...wait, ding dong the witch is dead?

Nicholas Rupley
Work: 949-237-6069
Always include what Mirth Connect version you're working with. Also include (if applicable) the code you're using and full stacktraces for errors (use CODE tags). Posting your entire channel is helpful as well; make sure to scrub any PHI/passwords first.


- How do I foo?
- You just bar.
Reply With Quote
  #4  
Old 11-25-2013, 09:12 AM
seaston seaston is offline
OBX.3 Kenobi
 
Join Date: Feb 2010
Location: London, UK
Posts: 168
seaston is on a distinguished road
Default

Thank you Nick. I did not want to jump straight in and create an issue because I just wasn't sure. Thank you for highlighting the MLLPv2 option.
Simon
Reply With Quote
  #5  
Old 11-25-2013, 09:23 AM
seaston seaston is offline
OBX.3 Kenobi
 
Join Date: Feb 2010
Location: London, UK
Posts: 168
seaston is on a distinguished road
Default

Actually it turns out that This system wants to give a MLLPv2 style ack back on the socket that has sent the message, but actually send the full ack back to a different socket. These leaves me with a bit of a problem because I don't think I can achieve this using Mirth Connect?

Can you also tell me if the 'Process HL7 Ack' works before or after the response transformer? (I am wondering if I could turn the ascii 6 into a fully structured ack).

Last edited by seaston; 11-25-2013 at 09:31 AM.
Reply With Quote
  #6  
Old 11-25-2013, 11:08 AM
narupley's Avatar
narupley narupley is online now
Mirth Employee
 
Join Date: Oct 2010
Posts: 7,119
narupley is on a distinguished road
Default

Quote:
Originally Posted by seaston View Post
Actually it turns out that This system wants to give a MLLPv2 style ack back on the socket that has sent the message, but actually send the full ack back to a different socket. These leaves me with a bit of a problem because I don't think I can achieve this using Mirth Connect?
You could... Basically the main channel sends the message and receives the single <ACK> control character. Then you have a separate ACK receiver channel which receives the HL7 ACK on the other socket and sends back a <ACK> control character. Then the ACK receiver channel can handle that response however it sees fit.

If you want the original channel to retrieve that response, you'll have to bring in some "statefulness" somewhere, like storing some information in the global map or in a database. I've attached a few channels to show how this is now possible in 3.0:

Channel - Sender
  • Destination 1 - Send message to bad server (TCP Sender)
    • Queue Messages: Always
    • Remote Address: 127.0.0.1
    • Remote Port: 6660
    • Process HL7 ACK: No
    • Response Transformer:
      • Step 0 - Queue the message if the response isn't an <ACK> control character (JavaScript)
        Code:
        if (msg != '\x06')
        	responseStatus = QUEUED;
  • Destination 2 - Send query to ACK Receiver to get deferred response (Channel Writer)
    • Queue Messages: Always
    • Channel Name: ACK Receiver
    • Transformer:
      • Outbound Template:
        Code:
        MSH|^~\&|||||||QRY^Q02||P|2.5
        QRD|||||||||
      • Step 0: Map MSH.3.1 from msg to tmp (Message Builder)
      • Step 1: Map MSH.4.1 from msg to tmp (Message Builder)
      • Step 2: Map MSH.5.1 from msg to tmp (Message Builder)
      • Step 3: Map MSH.6.1 from msg to tmp (Message Builder)
      • Step 4: Map MSH.7.1 with DateUtil (Message Builder)
      • Step 5: Map MSH.10.1 with UUIDGenerator (Message Builder)
      • Step 6: Map MSH.10.1 from msg to QRD.9.1 in tmp (Message Builder)

    • Response Transformer:
      • Step 0: Queue the message if the ACK code is not AA (JavaScript)
        Code:
        if (msg.MSA['MSA.1']['MSA.1.1'].toString() != 'AA')
        	responseStatus = QUEUED;

Channel - ACK Receiver
  • Source Connector (TCP Listener)
    • Port: 6661
    • Response: ACK

  • Destination 1 - Store ACK data in global map (JavaScript Writer)
    • Queue Messages: Always
    • Rotate: Enabled
    • JavaScript:
      Code:
      var messageControlId = $co('messageControlId');
      
      if (!globalMap.containsKey(messageControlId)) {
      	$g(messageControlId,{message:connectorMessage.getEncodedData(),processed:false});
      	return QUEUED;
      } else if ($g(messageControlId).processed == true) {
      	globalMap.remove(messageControlId);
      }
    • Filter
      • Step 0: Filter query messages and set response accordingly (JavaScript)
        Code:
        if (msg['MSH']['MSH.9']['MSH.9.1'].toString() == 'QRY') {
        	var messageControlId = msg['QRD']['QRD.9']['QRD.9.1'].toString();
        
        	if (globalMap.containsKey(messageControlId)) {
        		$r('ACK', ResponseFactory.getSentResponse($g(messageControlId).message));
        		$g(messageControlId).processed = true;
        	} else {
        		var serializer = SerializerFactory.getSerializer('HL7V2');
        		var ack = new XML(serializer.toXML(new ACKGenerator().generateAckResponse(connectorMessage.getRawData(),'AR','ACK Not Found.')));
        		ack.MSH['MSH.9']['MSH.9.1'] = 'QCK';
        		ack.MSH['MSH.9']['MSH.9.2'] = 'Q02';
        		$r('ACK', ResponseFactory.getErrorResponse(serializer.fromXML(ack)));
        	}
        } else {
        	return true;
        }
    • Transformer:
      • Step 0: Map the message control ID and set the MLLPv2 response (JavaScript)
        Code:
        $co('messageControlId',msg['MSA']['MSA.2']['MSA.2.1'].toString());
        responseMap.put('ACK', ResponseFactory.getSentResponse('\x06'));


So that ACK Receiver channel basically has two jobs. One is to receive the deferred ACK from the server and respond with an <ACK>. The other is to receive queries from the main channel (in the form of HL7 QRY messages) and respond with the actual deferred ACK, if it has been received yet. If it hasn't been received yet, the channel will just send a rejected QCK, and the main channel will attempt the query again. I've also attached a "Bad Server" channel that simulates the scenario you're talking about, where the server sends just the <ACK> to the main socket, and sends the actual response to a whole new connection.
Attached Files
File Type: xml Sender.xml (32.6 KB, 29 views)
File Type: xml ACK Receiver.xml (20.6 KB, 22 views)
File Type: xml Bad Server.xml (16.0 KB, 20 views)
__________________
Step 1: JAVA CACHE...DID YOU CLEAR ...wait, ding dong the witch is dead?

Nicholas Rupley
Work: 949-237-6069
Always include what Mirth Connect version you're working with. Also include (if applicable) the code you're using and full stacktraces for errors (use CODE tags). Posting your entire channel is helpful as well; make sure to scrub any PHI/passwords first.


- How do I foo?
- You just bar.
Reply With Quote
  #7  
Old 11-25-2013, 11:12 AM
narupley's Avatar
narupley narupley is online now
Mirth Employee
 
Join Date: Oct 2010
Posts: 7,119
narupley is on a distinguished road
Default

Quote:
Originally Posted by seaston View Post
Can you also tell me if the 'Process HL7 Ack' works before or after the response transformer? (I am wondering if I could turn the ascii 6 into a fully structured ack).
It works before the response transformer. So for example if you receive an AR NACK, the message status will be set to ERROR. However you can change that in the response transformer.

You technically could turn the <ACK> character into a fully structured HL7 ACK, but that would be incorrect. The <ACK> character does not indicate application-level acceptance, it only indicates that the message has been received and successfully stored by the server. In normal MLLPv2, a client could send a message, receive a <ACK>, and then receive an HL7 NACK immediately afterwards. So the <ACK> itself does not give you the information you want (unless you want to start making arbitrary assumptions).
__________________
Step 1: JAVA CACHE...DID YOU CLEAR ...wait, ding dong the witch is dead?

Nicholas Rupley
Work: 949-237-6069
Always include what Mirth Connect version you're working with. Also include (if applicable) the code you're using and full stacktraces for errors (use CODE tags). Posting your entire channel is helpful as well; make sure to scrub any PHI/passwords first.


- How do I foo?
- You just bar.
Reply With Quote
  #8  
Old 11-25-2013, 12:01 PM
seaston seaston is offline
OBX.3 Kenobi
 
Join Date: Feb 2010
Location: London, UK
Posts: 168
seaston is on a distinguished road
Default

Nick, I've read your demo and tried out these channels on my laptop. I understand what you have done and will try and put this in practice for real at work tomorrow.
Thank you
Reply With Quote
  #9  
Old 06-03-2015, 03:37 AM
seaston seaston is offline
OBX.3 Kenobi
 
Join Date: Feb 2010
Location: London, UK
Posts: 168
seaston is on a distinguished road
Default

I tried to use Nick's suggested code in some channels that I have attached, except to say that I am using the globalChannelMap and not the globalMap.

I am seeing a build up of entries in the map (please see attachment for more details).

I cannot see why the globalChannelMap.remove(key) does not appear to remove according to the administrator screen displaying the global maps.

There must be something wrong somewhere but I just can't see it.
Attached Files
File Type: xml PROD iCM Health Issues and Alerts Acks.xml (25.3 KB, 4 views)
File Type: xml PROD iCM Health Issues and Alerts.xml (72.2 KB, 4 views)
File Type: doc globalChannelMap not removed.doc (113.5 KB, 5 views)
Reply With Quote
  #10  
Old 06-04-2015, 06:48 AM
seaston seaston is offline
OBX.3 Kenobi
 
Join Date: Feb 2010
Location: London, UK
Posts: 168
seaston is on a distinguished road
Default

Still suffering from a gradual build up of entries in the globalChannelMap which do not seem to get removed.

I realised I did not have 'rotate queue' selected in the acknowledgement reader channel, but changing this did not appear to make any difference so I decided to put an expiring cache in the globalChannelMap and use that rather than the globalChannelMap to store the recent acknowledgements.

Code:
if ( !globalChannelMap.containsKey('Acknowledgement Cache') ) {
    // creating expiring cache:
    globalChannelMap.put('Acknowledgement Cache',new Packages.com.google.common.cache.CacheBuilder.newBuilder().expireAfterWrite(60,java.util.concurrent.TimeUnit.SECONDS).build());
}
I attach the amended channels.

I tried out Nick's original solution again on a seperate server and monitored the build up in the global map. There did not appear to be any acks that were 'left over' and not cleared up. However when I try against the real live system, which is slower to send back acknowlegements they appear to build up. Still don't understand why.
Attached Files
File Type: xml PROD iCM Health Issues and Alerts.xml (82.7 KB, 8 views)
File Type: xml PROD iCM Health Issues and Alerts Acks.xml (25.8 KB, 5 views)
Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -8. The time now is 08:06 AM.


Powered by vBulletin® Version 3.8.7
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Mirth Corporation