Tuesday 19 April 2016

The prefix "s" for element "s:Envelope" is not bound

I've always found the way Mirth handles namespaces in xml painful at best - to strip namespaces or not to strip namespaces! It is particularly painful when you come from the .NET world using the Web Service Sender. Here's an error I have come across a few times now.

Transformer error
ERROR MESSAGE: Error evaluating transformer
com.mirth.connect.server.MirthJavascriptTransformerException:
CHANNEL:    Hunter outbound HL7
CONNECTOR:    Send ORU HL7
SCRIPT SOURCE:    TRANSFORMER
SOURCE CODE:   
209: var responseMessage = destination.getMessage();
210:
211: //logger.info(responseMessage);
212:
213: // Wrap the SOAP string into an XML object so that we can parse it.
214: var soapMsg = new XML(responseMessage);
215:
216: // Find the XML tag that has the RTF file. It's Base-64 encoded
217: var base64EncodedRtf = soapMsg..*::FileByteStream.toString();
218:
LINE NUMBER:    214
DETAILS:    TypeError: The prefix "s" for element "s:Envelope" is not bound.
    at 6d9945af-8559-413e-8652-3c6747667665:214 (doTransform)
    at 6d9945af-8559-413e-8652-3c6747667665:335 (doScript)
    at 6d9945af-8559-413e-8652-3c6747667665:337
    at com.mirth.connect.server.transformers.JavaScriptFilterTransformer$FilterTransformerTask.call(JavaScriptFilterTransformer.java:154)
    at com.mirth.connect.server.transformers.JavaScriptFilterTransformer$FilterTransformerTask.call(JavaScriptFilterTransformer.java:119)
    at java.util.concurrent.FutureTask.run(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)

clip_image001

So in this Channel I have a few destinations doing separate things, but the last two are supposed to pull in a medical document, then insert this into an HL7 message and send it.

It gets the document fine, but then the "Send ORU HL7" throws the above error.

Well, the error certainly looks like a namespace problem, so I jump into the channels Set Date Types dialog and start making adjustments.

clip_image002

As you can see here, I am already not stripping the namespace, but as I try changing to different combinations of stripping and not stripping I still cannot fix the problem. Finally I concede that I need to focus on the destination prior, the "Request Document From Corridor". It is indeed that message that returns the "s:" namespace.

clip_image003

So I adjust it's namespace stripping too without any luck. But then I had a thought - what if I treat it as a different datatype. Even though it is returning a xml message I simply tell Mirth it is HL7 V2.x

clip_image004

That was it. Problem solved. I certainly get why this workaround works, but what I don't really understand is why I had to do it that way.

I'd love any feedback on other peoples experiences here, an I can look at doing a future post following up on this.

Thursday 14 April 2016

What’s the difference between A04 and A28 message

HL7 seems to have a whole lot of event types that sound similar, and it is often difficult to see through the nuances in the definitions.  Today I was asked the difference between an A04 (Register a Patient) and an A28 (Add person information), so I thought I would share it.

An A04 is an event that signifies a patient has arrived or checked in for an outpatient visit, that is they are going in for a one off visit and they are not allocated a bed. An A28 is a transfer of a person’s demographic information between systems. It doesn’t need to be triggered from a patients arrival or anything like that. For instance the patient information may be of no immediate use to the other systems, but knowledge of the patient may come in handy later so they are updated with an A28. Further, an A28 isn’t necessarily about a patients, but could represent other people to other systems e.g. Patient guarantors, or records for a registry database.

Tuesday 12 April 2016

Character reference “ ” is an invalid XML character Mirth Error

I was bringing a text document into an HL7 messages today in Mirth when I found I got the following error every time for a particular document.

ER7Serializer error
ERROR MESSAGE: Error converting XML to ER7
org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 47427;
Character reference "&#12" is an invalid XML character.
    at org.apache.xerces.util.ErrorHandlerWrapper.createSAXParseException(Unknown Source)
    at org.apache.xerces.util.ErrorHandlerWrapper.fatalError(Unknown Source)
    at org.apache.xerces.impl.XMLErrorReporter.reportError(Unknown Source)
    at org.apache.xerces.impl.XMLErrorReporter.reportError(Unknown Source)
    at org.apache.xerces.impl.XMLErrorReporter.reportError(Unknown Source)
    at org.apache.xerces.impl.XMLScanner.reportFatalError(Unknown Source)
    at org.apache.xerces.impl.XMLScanner.scanCharReferenceValue(Unknown Source)
    at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanCharReference(Unknown Source)
    at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(Unknown Source)
    at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
    at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
    at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
    at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
    at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source)
    at com.mirth.connect.plugins.datatypes.hl7v2.ER7Serializer.fromXML(ER7Serializer.java:277)
    at com.mirth.connect.donkey.server.channel.FilterTransformerExecutor.processConnectorMessage(FilterTransformerExecutor.java:123)
    at com.mirth.connect.donkey.server.channel.DestinationConnector.transform(DestinationConnector.java:320)
    at com.mirth.connect.donkey.server.channel.DestinationChain.call(DestinationChain.java:151)
    at com.mirth.connect.donkey.server.channel.Channel.process(Channel.java:1653)
    at com.mirth.connect.donkey.server.channel.Channel.dispatchRawMessage(Channel.java:1156)
    at com.mirth.connect.donkey.server.channel.SourceConnector.dispatchRawMessage(SourceConnector.java:192)
    at com.mirth.connect.donkey.server.channel.SourceConnector.dispatchRawMessage(SourceConnector.java:170)
    at com.mirth.connect.connectors.ws.WebServiceReceiver.processData(WebServiceReceiver.java:238)
    at com.mirth.connect.connectors.ws.WebServiceReceiver.processData(WebServiceReceiver.java:207)
    at com.mirth.connect.connectors.ws.DefaultAcceptMessage.acceptMessage(DefaultAcceptMessage.java:24)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at sun.reflect.misc.Trampoline.invoke(Unknown Source)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at sun.reflect.misc.MethodUtil.invoke(Unknown Source)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at com.sun.xml.internal.ws.api.server.MethodUtil.invoke(Unknown Source)
    at com.sun.xml.internal.ws.api.server.InstanceResolver$1.invoke(Unknown Source)
    at com.sun.xml.internal.ws.server.InvokerTube$2.invoke(Unknown Source)
    at com.sun.xml.internal.ws.server.sei.SEIInvokerTube.processRequest(Unknown Source)
    at com.sun.xml.internal.ws.api.pipe.Fiber.__doRun(Unknown Source)
    at com.sun.xml.internal.ws.api.pipe.Fiber._doRun(Unknown Source)
    at com.sun.xml.internal.ws.api.pipe.Fiber.doRun(Unknown Source)
    at com.sun.xml.internal.ws.api.pipe.Fiber.runSync(Unknown Source)
    at com.sun.xml.internal.ws.server.WSEndpointImpl$2.process(Unknown Source)
    at com.sun.xml.internal.ws.transport.http.HttpAdapter$HttpToolkit.handle(Unknown Source)
    at com.sun.xml.internal.ws.transport.http.HttpAdapter.handle(Unknown Source)
    at com.sun.xml.internal.ws.transport.http.server.WSHttpHandler.handleExchange(Unknown Source)
    at com.sun.xml.internal.ws.transport.http.server.WSHttpHandler.handle(Unknown Source)
    at com.sun.net.httpserver.Filter$Chain.doFilter(Unknown Source)
    at sun.net.httpserver.AuthFilter.doFilter(Unknown Source)
    at com.sun.net.httpserver.Filter$Chain.doFilter(Unknown Source)
    at sun.net.httpserver.ServerImpl$Exchange$LinkHandler.handle(Unknown Source)
    at com.sun.net.httpserver.Filter$Chain.doFilter(Unknown Source)
    at sun.net.httpserver.ServerImpl$Exchange.run(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)

So, this looks like it’s caused by a funny character – the "&#12" or Form Feed.  I found the transformer that was bringing in the value and tried at first to try/catch it out, but quickly found that my JavaScript code wasn’t the problem, it was actually internal Mirth code getting all tripped up by the character.

That means that the only way to fix it now is to remove the character, but how?  I had actually written out the value to the logging window, where it was visible as a funny square box.  Very handy this as I was actually able to copy the value, and then do a string comparison to filter it out. 

image

Wednesday 6 April 2016

Mirth destinations not waiting for previous destination

The other day I had sent off a channel to one of the implementations guys and he installed it on the customers system.
It had three Web Server Sender destinations in a row that had to be executed in order.  AddPatient, AddVisit, and AddAppointment.   No problem I thought, "Wait for previous destination" was checked on all of them.

However I later received a report that the customer was getting errors of the sort that could only happen if the destinations had not been executed in the right order.  The appointment was being added without a visit, and sometimes without a patient.

I tried replicating the problem locally, but had no luck, so I gained remote access to the site. I first located an instance of the problem and checked that there wasn't an error in the first couple of destinations - there wasn't.

Sure enough though, when I look at the timing of the message, all the destinations trigger at more or less the same time, while the responses happen much later.

So I opened the channel and checked that the "Wait for previous destination" was checked.  Sure enough all looked good, but then I noticed the problem.  Someone had changed my pattern to queue the destinations.

Mirth Destination
I don't know if it was the implementation team, or the customer, but someone was making the mistake of thinking everything is more reliable if queued.  I checked the "Wait" and "Queue" tool-tips, and they don't mention that setting queuing overrides the wait, so they can't be blamed for missing this one really.  Maybe the Mirth guys might want to include this in their tool-tips.

Tuesday 5 April 2016

Sending < and > symbols to a Web Service Sender in Mirth

 

I have a Mirth channel interface that receives an HL7 message, and then the values are extracted and passed on to a web service via a Web Service Sender.

Mostly it worked well, but for a few messages I got the following error.

Web Service Sender error
ERROR MESSAGE: Error creating web service dispatch
com.sun.xml.internal.messaging.saaj.SOAPExceptionImpl: Error during saving a multipart message
    at com.sun.xml.internal.messaging.saaj.soap.MessageImpl.saveChanges(Unknown Source)
    at com.mirth.connect.connectors.ws.WebServiceDispatcher.send(WebServiceDispatcher.java:514)
    at com.mirth.connect.donkey.server.channel.DestinationConnector.handleSend(DestinationConnector.java:738)
    at com.mirth.connect.donkey.server.channel.DestinationConnector.process(DestinationConnector.java:436)
    at com.mirth.connect.donkey.server.channel.DestinationChain.call(DestinationChain.java:155)
    at com.mirth.connect.donkey.server.channel.Channel.process(Channel.java:1653)
    at com.mirth.connect.donkey.server.channel.Channel.dispatchRawMessage(Channel.java:1156)
    at com.mirth.connect.donkey.server.channel.SourceConnector.dispatchRawMessage(SourceConnector.java:192)
    at com.mirth.connect.donkey.server.channel.SourceConnector.dispatchRawMessage(SourceConnector.java:170)
    at com.mirth.connect.connectors.tcp.TcpReceiver$TcpReader.call(TcpReceiver.java:650)
    at com.mirth.connect.connectors.tcp.TcpReceiver$TcpReader.call(TcpReceiver.java:485)
    at java.util.concurrent.FutureTask.run(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
Caused by: com.sun.xml.internal.messaging.saaj.SOAPExceptionImpl: Unable to get header stream in saveChanges:
    ... 15 more
Caused by: com.sun.xml.internal.messaging.saaj.SOAPExceptionImpl: SOAP exception while trying to externalize:

If this was failing all the time, it probably means that the Soap’s XML structure has been corrupted while I was adding variables, but as this was only with certain messages I was pretty sure that the data was corrupting the XML structure.

Looking at the Mirth Dashboard, I navigated to the ‘sent message’ and found the culprit

<win:UniversalServiceText>Type < 3</win:UniversalServiceText>

Yep, that would do it. So how do you convert this to:

<win:UniversalServiceText>Type &lt; 3</win:UniversalServiceText>

I’ve always felt that Mirth should do this for you in the transformers, but every time I try to run a Soap message through the transformers I get errors that I just can’t seem to fix. Besides, I’m not even sure that this would work; it doesn’t very well with HL7 messages.

Instead, I’m back to coding the answer again, each variable at a time. So when you create your variable just include the following like so.

msg['OBR']['OBR.4']['OBR.4.2'].toString().replace('<', '&lt;').replace('>', '&gt;')

clip_image002

I’d love to get feedback about how others get around this issue.

Monday 4 April 2016

Escaping HL7 ampersands with Mirth Connect (NextGen Connect)

HL7 uses &'s to separate the subcomponents in a message, So if you need to include an '&' in a field, such as the address "Corner of High & Main St" you are going to run into problems.

MSH|^~\&|App1|Fac1|App2|Fac2|20160315121250||ADT^A31|1000|P|2.3.1

PID|1||10000||Smith^John^^^MR^^||19790708|M|||Corner of High & Main St^^City^New York^^UK|

Fortunately HL7 comes with escape characters, but they are a little bit "unique" in my eyes. Here is a great, comprehensive place to find all the escape codes. The one we are interested in for the ampersand is \T\.

MSH|^~\&|App1|Fac1|App2|Fac2|20160315121250||ADT^A31|1000|P|2.3.1

PID|1||10000||Smith^John^^^MR^^||19790708|M|||Corner of High \T\ Main St^^City^New York^^UK|

Mirth Connect actually supports automatically transforming the escaped characters for you, providing you turn on the 'Use Strict Parser' setting.

clip_image001

However, this then turns Mirth into an HL7 Nazi, constantly rejecting messages due to fields not containing the right values. I don't know about you, but I don't think I've worked on an HL7 interface that didn't have some slight breaking of the rules somewhere.

For this reason I recommend leaving the Strict Parser off and editing your source transformer code so that values are transformed with the escape characters replace.

You just need to navigate to the transformers for the fields you’d like to escape and append the following code to the string.

().replace(/\\T\\/g, "\&amp;");

e.g. the Doctors address line one becomes

msg['ZPD']['ZPD.2']['ZPD.2.1'].toString().replace(/\\T\\/g, "\&amp;");

clip_image002

(Update: Yep, I use Integration Host now by HL7 Soup so this is all just a right-click option without pain. If all this is in the too hard basket, do the same...)

Saturday 2 April 2016

Mirth Connect using SQL Server

When you first install Mirth Connect (update: now NextGen Connect)  is comes with its own Derby database.  This is fine when you are mucking around and developing channels, but I have seen my fair share of production sites going down because Derby is not up to task.  After a bit of research I even found Mirth themselves recommend that you replace this database before going live. (update: Yes, I know, I use HL7 Soup's Integration Host now too, but a lot of people are stuck with NextGen Connect) 

The first thing I do with Mirth now on a fresh install is to configure it to point to SQL Server.

Fortunately this is pretty easy to do.
Load up Mirth Connect Server Manager, then navigate to it in your task bar.




Right click it, and select "Show Manager"



Navigate across to the "Database" tab and fill it out with the settings and connection string to your SQL Server.


One thing to watch for is if your SQL is not the default instance you can't just use the normal / syntax of specifying it along with the server name. Use the following instead:
jdbc:jtds:sqlserver://SERVERNAME;instance=INSTANCENAME;DatabaseName=mirthdb


Now just restart the Mirth service from the Server Manager and Mirth will build and prepare the database for you.

If you need to migrate an existing database, and keep all the data then I suggest you take a look at this link I found.