web stats
Message validation - Mirth Community

Go Back   Mirth Community > Mirth Connect > Support

Reply
 
Thread Tools Display Modes
  #1  
Old 02-20-2012, 09:02 PM
Linh Linh is offline
Mirth Newb
 
Join Date: Feb 2012
Posts: 6
Linh is on a distinguished road
Default Message validation

Hi All,

I am a bit stuck on how the message validation and filtering work. Reading previous posts did not solve my problem. Your help would be greatly appreciated.

My requirements and set up are like this:
- I have an LLP Listener accepting incoming HL7 messages. When messages are not valid, I will need to send a Error ACK back to the sender. In addition, I will need to write the error messages to a directory. With the LLP Listener, I cannot configure it to write error messages to a directory.
- I can write some Filtering rule in the Destination Filter, however this only marked the messages as Filtered; the sender does not get any Error ACK, and the sender sees a normal ACK as if the message was sent successfully.

Is there any way that I can fulfill the requirements: "on invalid messages, send Error ACK and write the invalid messages to a directory"?

Thank you very much for your help and guidance.

Regards,
Linh
Reply With Quote
  #2  
Old 02-20-2012, 09:07 PM
narupley's Avatar
narupley narupley is offline
Mirth Employee
 
Join Date: Oct 2010
Posts: 7,124
narupley is on a distinguished road
Default

In your Source filter, put whatever qualifications you want in one JavaScript step. That way you can call whatever custom code you want for writing the file to an error directory, in the case that the message should be filtered. Then on your LLP Listener settings, set the "rejected" code and message as appropriate.
Reply With Quote
  #3  
Old 02-20-2012, 10:22 PM
Linh Linh is offline
Mirth Newb
 
Join Date: Feb 2012
Posts: 6
Linh is on a distinguished road
Default

Thanks narupley.

I now see the difference between Source Filter (will send message rejected back to sender on filtered messages) and Destination Filter (silent on filtered messages).

I modified my LLP Listener as follow:
Send ACK: Yes
...
Rejected ACK Code: AR

In my Source filter, I have a JavaScript with "return false;" for testing purposes. Upon receiving a message, the message is filtered and I got a correct ACK:

<0x0b>MSH|^~\&|Hospital|8003621231167888|Medical|8 003614166667350|20120221165514||ACK|20120221165514 |P|2.3.1<0x0d> MSA|AR|499e58ee-2934-4d0a-8b37-8b94a0a0bb6e|Message Rejected.<0x0d> <0x1c><0x0d>


However, my LLP Listener is just a gate keeper receiving messages and forward to the next channel to do further processing. I have tried to set up a response variable with this method: ResponseFactory.getFilteredResponse('AR') and assign it to a response map variable 'ResponseMsg'. I then changed my LLP Listener to Send ACK: Respond from "ResponseMsg".

When I send a message, I got the ACK as follow:

<0x0b>AR<0x1c><0x0d>

And upon receiving that ACK, my sender complains: "Warning: Last segment have no segment termination char 0x0d ! Acknowledge message received. Invalid acknowledge message structure. Segment MSA is missing."

Is there a way to fully generate the ACK message with MSA segment? Or I have to build the response message manually?

Thanks for your help.

Linh
Reply With Quote
  #4  
Old 02-21-2012, 04:07 AM
narupley's Avatar
narupley narupley is offline
Mirth Employee
 
Join Date: Oct 2010
Posts: 7,124
narupley is on a distinguished road
Default

Unfortunately, in that case you'll have to build the ACK yourself. Fortunately, it's a relatively easy thing to do:

Code:
function setACK(sourceMsg,responseCode,responseMsg,responseStatus) {
	importPackage(com.mirth.connect.model);
	// responseStatus is an optional parameter
	if (!responseStatus)
		responseStatus = {'AA':Response.Status.SUCCESS,'AR':Response.Status.FILTERED,'AE':Response.Status.FAILURE}[responseCode] || Response.Status.UNKNOWN;
	var ack = <HL7Message/>;
	ack.MSH['MSH.1'] = sourceMsg.MSH['MSH.1'].toString();
	ack.MSH['MSH.2'] = sourceMsg.MSH['MSH.2'].toString();
	ack.MSH['MSH.3'] = sourceMsg.MSH['MSH.5'].copy();
	ack.MSH['MSH.4'] = sourceMsg.MSH['MSH.6'].copy();
	ack.MSH['MSH.5'] = sourceMsg.MSH['MSH.3'].copy();
	ack.MSH['MSH.6'] = sourceMsg.MSH['MSH.4'].copy();
	ack.MSH['MSH.7']['MSH.7.1'] = DateUtil.getCurrentDate('yyyyMMddHHmmss');
	ack.MSH['MSH.9']['MSH.9.1'] = sourceMsg.MSH['MSH.9']['MSH.9.1'].toString();
	ack.MSH['MSH.9']['MSH.9.2'] = sourceMsg.MSH['MSH.9']['MSH.9.2'].toString();
	ack.MSH['MSH.9']['MSH.9.3'] = 'ACK';
	ack.MSH['MSH.10'] = sourceMsg.MSH['MSH.10'].copy();
	ack.MSH['MSH.11'] = sourceMsg.MSH['MSH.11'].copy();
	ack.MSH['MSH.12'] = sourceMsg.MSH['MSH.12'].copy();
	ack.MSA['MSA.1']['MSA.1.1'] = responseCode;
	ack.MSA['MSA.2']['MSA.2.1'] = sourceMsg.MSH['MSH.10']['MSH.10.1'].toString();
	ack.MSA['MSA.3']['MSA.3.1'] = responseMsg;
	responseMap.put('ACK',new Response(responseStatus,SerializerFactory.getHL7Serializer().fromXML(ack)));
}
For example, if you want to send an AR NACK back for ADTs, you could do this:

Code:
if (msg['MSH']['MSH.9']['MSH.9.1'].toString() == 'ADT')
	setACK(msg,'AR',"We don't take kindly to the likes of you.");
else
	setACK(msg,'AA','Pull up a chair.');
Reply With Quote
  #5  
Old 02-21-2012, 04:06 PM
Linh Linh is offline
Mirth Newb
 
Join Date: Feb 2012
Posts: 6
Linh is on a distinguished road
Default

Hi narupley,

That is an excellent answer. Thank you very much for showing me how to build up the ACK msg.
I got the pathway of what needs to be done now. Thanks again.

Linh
Reply With Quote
  #6  
Old 02-21-2012, 05:34 PM
Linh Linh is offline
Mirth Newb
 
Join Date: Feb 2012
Posts: 6
Linh is on a distinguished road
Default

Hi narupley,

This is my setup. Hope it will helps other people and if you see any problem, please let me know. I really appreciate your and other people's feedback.

I put your ACK setAck() function in the Channels' Code Template to be able to reuse it. The function buildAckMsg will have this statement "return new Response(responseStatus,SerializerFactory.getHL7Se rializer().fromXML(ack));" at the end.

My set up has 1) HL7 Receiver Channel, which will forward to the next Channel for further processing.

1) HL7 Receiver Channel:
Source:
LLP Listener
Send ACK: Respond from "ResponseMsg" (this is a variable which will be set in Channel's postprocessor)

Destination:
Connector type: Channel Writer, write to Channel "My Next Channel")
Wait for Channel Response: Yes

Transformer: javascript: (to save a reference to the message in postprocessor)
channelMap.put('rawMsg', messageObject.getRawData());
channelMap.put('xmlMsg', msg);


Postprocessor script:
// This script executes once after a message has been processed

var responseFromChannel = responseMap.get('My Next Channel').toString();

var xmlMsg = channelMap.get('xmlMsg');

if(responseFromChannel.indexOf('Message has been filtered') >= 0)
{
var ackMsg = buildAckMsg(xmlMsg, 'AR', "Message Rejected");
responseMap.put('ResponseMsg', ackMsg);
}
else if (responseFromChannel.indexOf('ERROR') >= 0 || responseFromChannel.indexOf('FAILURE') >= 0)
{
var ackMsg = buildAckMsg(xmlMsg, 'AE', "An Error Occurred Processing Message");
responseMap.put('ResponseMsg', ackMsg);
}
else
{
var ackMsg = buildAckMsg(xmlMsg, 'AA', "Message received and processed successfully");
responseMap.put('ResponseMsg', ackMsg);
}

return;

2) My Next Channel:
Source:
Channel Reader

Destinations:
Has a Filter that has my filtering logic.



Thanks narupley, you have saved my day.

Linh
Reply With Quote
Reply

Tags
directory, filter, validation

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 04:19 AM.


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