web stats
When Queued Messages get too high, Mirth marks all messages with same error. - Mirth Community

Go Back   Mirth Community > Mirth Connect > Support

Reply
 
Thread Tools Display Modes
  #1  
Old 05-12-2017, 01:19 PM
bensonius bensonius is offline
Mirth Newb
 
Join Date: May 2017
Posts: 7
bensonius is on a distinguished road
Question When Queued Messages get too high, Mirth marks all messages with same error.

We've recently updated to Mirth Connect Server 3.4.1.8057. There was an incident where we had to reprocess a bunch of messages. Upon doing so, the queue grew to about 3000 or more. Suddenly, every message just started erroring out with the same error message, same line number and everything...but there is not error there.

Code:
JavaScript Writer error
ERROR MESSAGE: Error evaluating JavaScript Writer
com.mirth.connect.server.MirthJavascriptTransformerException: 
CHANNEL:	CDX_POI_OE_Outbound_To_DB
CONNECTOR:	CDX_DB_Prod
SCRIPT SOURCE:	JavaScript Writer
SOURCE CODE:	
358: function CDX_BuildMessageRecipients() {
359:     var aPhysicianMnemonicArrays =$('aPhysicianMnemonicArrays');
360: 	var sMessageRecipients = "<MessageRecipients>";
361: 	
362: 	for each (var mnemonicObject in aPhysicianMnemonicArrays) {
363: 		for each (var sMnemonic in mnemonicObject.aPhysicianMnemonics) {
364: 			sMessageRecipients += "\n	<MessageRecipient>";
365: 			sMessageRecipients += "\n		<IDs>";
366: 			sMessageRecipients += "\n			<ID OID='2.16.840.1.113883.3.277.1.61' Value='" +  Util_ReplaceXMLSpecialCharacters(sMnemonic) + "' AssigningAuthorityName='IHA Provider Code: IHA-MT PVD-ID' />";				
367: 			sMessageRecipients += "\n		</IDs>";
LINE NUMBER:	363
DETAILS:	Java class "[B" has no public instance field or method named "aPhysicianMnemonics".
	at 2ac29577-2e7d-4a48-8fa2-99e62157ca7d:363 (CDX_BuildMessageRecipients)
	at 2ac29577-2e7d-4a48-8fa2-99e62157ca7d:241 (CDX_AcceptMessage)
	at 2ac29577-2e7d-4a48-8fa2-99e62157ca7d:2858 (doScript)
	at 2ac29577-2e7d-4a48-8fa2-99e62157ca7d:2861
	at com.mirth.connect.connectors.js.JavaScriptDispatcher$JavaScriptDispatcherTask.doCall(JavaScriptDispatcher.java:184)
	at com.mirth.connect.connectors.js.JavaScriptDispatcher$JavaScriptDispatcherTask.doCall(JavaScriptDispatcher.java:122)
	at com.mirth.connect.server.util.javascript.JavaScriptTask.call(JavaScriptTask.java:113)
	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)
On the source there is a transformer that creates an array of providers based on ZDR segments for each message. Then in the destination (it's a Javascript Writer) a function is called to build XML from this array and submit it to a Stored Procedure.

It seems whenever we try to reprocess more than 1000 message at a time, it will get about halfway and sudden drop all the queue and error them out with this same error message. Replaying these errored messages again (in smaller batches) they process just fine.

Now, I have to ask, could this be a memory issue? IE: there are so many messages and arrays that the server can't handle it? The memory usage on the server looks ok while processing these.

Could it be an issue with the upgrade? We've never experienced this before and had to reprocess upwards of 10000 messages at a time before.

I'm really struggling for ideas here...
Reply With Quote
  #2  
Old 05-12-2017, 01:27 PM
narupley's Avatar
narupley narupley is online now
Mirth Employee
 
Join Date: Oct 2010
Posts: 7,119
narupley is on a distinguished road
Default

Whatever you put into the variable maps (connector / channel / response) should be stateless and serializable. Remember that content gets written to the database, so the DAO needs to convert such objects to strings for purposes of DB insert. If no good toString() implementation exists, the default Java implementation applies.

That's what you're seeing here, because you're putting a Java byte array into one of the maps. It'll work as long as the message stays in memory, but if the number of queued messages passes the configured Queue Buffer Size (or if you restart/redeploy the channel), then that byte array will be replaced with an unhelpful "[B@abc123" string.

Instead of placing a byte array directly into the persisted maps, I'd suggest converting it to a Base64 string first. You can use FileUtil for that.
__________________
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
  #3  
Old 05-12-2017, 01:54 PM
bensonius bensonius is offline
Mirth Newb
 
Join Date: May 2017
Posts: 7
bensonius is on a distinguished road
Default

Ahh, ok. I looked at our "Default Queue Buffer Size:" setting and it was blank. What would that have defaulted to? In the meantime, I've actually put a setting in there and will stick to only reprocessing that many messages at a time.

In regards to converting to a "Base64 string first", first before what? and what is the accepted idiom for doing such a thing? I'm fairly green when it comes to mirth.

In this specific case, where are you suggesting I do this? Would it be in this Code Template, or in the one that populates the array on the Send transform which calls a channelMap.put() with an array of physicians?

Code:
/**
	Takes the ZDR Providers from POI and builds MessageProvider records for CDX.
*/
function CDX_BuildMessageRecipients() {
    var aPhysicianMnemonicArrays =$('aPhysicianMnemonicArrays');
	var sMessageRecipients = "<MessageRecipients>";
	
	for each (var mnemonicObject in aPhysicianMnemonicArrays) {
		for each (var sMnemonic in mnemonicObject.aPhysicianMnemonics) {
			sMessageRecipients += "\n	<MessageRecipient>";
			sMessageRecipients += "\n		<IDs>";
			sMessageRecipients += "\n			<ID OID='2.16.840.1.113883.3.277.1.61' Value='" +  Util_ReplaceXMLSpecialCharacters(sMnemonic) + "' AssigningAuthorityName='Provider Code: IHA-MT PVD-ID' />";				
			sMessageRecipients += "\n		</IDs>";
			sMessageRecipients += "\n		<ParticipationTypeCode>" + mnemonicObject.sPhysicianCategory + "</ParticipationTypeCode>";
			sMessageRecipients += "\n		<RecipientType OID='2.16.840.1.113883.3.277.100.30' Value='PROV' />";
			sMessageRecipients += "\n	</MessageRecipient>";
		}
	}	

	sMessageRecipients += "</MessageRecipients>";
	var xmlRecipient = new XML(sMessageRecipients);
	return xmlRecipient;
}
Reply With Quote
  #4  
Old 05-12-2017, 02:22 PM
bensonius bensonius is offline
Mirth Newb
 
Join Date: May 2017
Posts: 7
bensonius is on a distinguished road
Default

I'm not entirely sure I understand the "I'd suggest converting it to a Base64 string first." I mean, I know what those words mean, but at what point in the process would I do this? Would I then need to convert back from Base64 at some point?

Would I do it in this code where it is erroring? If so, at what point?

Code:
function CDX_BuildMessageRecipients() {
    var aPhysicianMnemonicArrays =$('aPhysicianMnemonicArrays');
	var sMessageRecipients = "<MessageRecipients>";
	
	for each (var mnemonicObject in aPhysicianMnemonicArrays) {
		for each (var sMnemonic in mnemonicObject.aPhysicianMnemonics) {
			sMessageRecipients += "\n	<MessageRecipient>";
			sMessageRecipients += "\n		<IDs>";
			sMessageRecipients += "\n			<ID OID='2.16.840.1.113883.3.277.1.61' Value='" +  Util_ReplaceXMLSpecialCharacters(sMnemonic) + "' AssigningAuthorityName='IHA Provider Code: IHA-MT PVD-ID' />";				
			sMessageRecipients += "\n		</IDs>";
			sMessageRecipients += "\n		<ParticipationTypeCode>" + mnemonicObject.sPhysicianCategory + "</ParticipationTypeCode>";
			sMessageRecipients += "\n		<RecipientType OID='2.16.840.1.113883.3.277.100.30' Value='PROV' />";
			sMessageRecipients += "\n	</MessageRecipient>";
		}
	}	

	sMessageRecipients += "</MessageRecipients>";
	var xmlRecipient = new XML(sMessageRecipients);
	return xmlRecipient;
}
Or in the code where I populate the "aPhysicianMnemonicArrays" channel map variable with a
Code:
channelMap.put('aPhysicianMnemonicArrays',aPhysicianMnemonicArrays);
?

I've increased the Default Queue Buffer Size in the settings and restarted the Mirth Service, but I got the errors again, which lead me to ask: is that Queue buffer for the entire server, or just on a per channel basis?

Thanks.
Reply With Quote
  #5  
Old 05-14-2017, 10:56 PM
siddharth siddharth is offline
Mirth Guru
 
Join Date: Feb 2013
Posts: 832
siddharth is on a distinguished road
Default

What Nick means is, instead of saving the byte array to the channelMap, you basically need it to convert it first into Base64 form, so that it becomes manageable and the byte does not lose its value.

What you are doing is calling the channelMap byte content and converting it into its toString() variant which is [B@abc123

So here where you are submitting a byte array to a channel Map variable,
Code:
channelMap.put('aPhysicianMnemonicArrays',aPhysicianMnemonicArrays);
change it to
Code:
channelMap.put('aPhysicianMnemonicArrays',FileUtil.encode(aPhysicianMnemonicArrays));
And a reverse decode process every time you have to take out of the maps and use it.
Reply With Quote
  #6  
Old 05-15-2017, 11:18 AM
bensonius bensonius is offline
Mirth Newb
 
Join Date: May 2017
Posts: 7
bensonius is on a distinguished road
Default

Awesome, thanks for the info, but I must be missing some steps. I have the code updated:

Code:
channelMap.put('aPhysicianMnemonicArrays',FileUtil.encode(aPhysicianMnemonicArrays));
on the way in and

Code:
var aPhysicianMnemonicArrays = FileUtil.decode($('aPhysicianMnemonicArrays'));
out.

But when I go to do the channelMap.put() an error is returned:

Code:
Cannot convert org.mozilla.javascript.NativeArray@3238f44f to byte[]
Is there something else that needs to be done, or do I need to create the array differently?

Edit: Here is how the array is being created:

Code:
function POI_ExtractPhysicianList()
{

	//create an array of arrays
	var aPhysicianMnemonicArrays = [];
	
	aPhysicianMnemonicArrays[0] = {aPhysicianMnemonics:new Array(),
					sPhysicianCategory:"ADP"};

	aPhysicianMnemonicArrays[1] = {aPhysicianMnemonics:new Array(),
					sPhysicianCategory:"ATP"};

	aPhysicianMnemonicArrays[2] = {aPhysicianMnemonics:new Array(),
					sPhysicianCategory:"OTP"};

	aPhysicianMnemonicArrays[3] = {aPhysicianMnemonics:new Array(),
					sPhysicianCategory:"FAP"};

	aPhysicianMnemonicArrays[4] = {aPhysicianMnemonics:new Array(),
					sPhysicianCategory:"ERP"};

	aPhysicianMnemonicArrays[5] = {aPhysicianMnemonics:new Array(),
					sPhysicianCategory:"PCP"};

		
	//map ZDR segment
	var xmlZDR = msg['ZDR'];
	var bPhysicianExists = false;

	for (var iFieldIndex = 1; iFieldIndex <= 6; iFieldIndex++)
	{
		//All ZDR fields are repeating so check through each 
		for each (var xmlZDRi in xmlZDR['ZDR.' + iFieldIndex])
		{
			var sPhysicianMnemonic;
			if (xmlZDRi['ZDR.' + iFieldIndex + '.1'] != undefined)	
			{
				//Mirth only creates multiple levels within XML if more than 1 component exists in a field.
				sPhysicianMnemonic = xmlZDRi['ZDR.' + iFieldIndex + '.1'].toString();
			}
			else
			{
				sPhysicianMnemonic = xmlZDRi.toString();	
			}
	
			if (sPhysicianMnemonic != "")
			{					
				bPhysicianExists = true;
				aPhysicianMnemonicArrays[iFieldIndex - 1].aPhysicianMnemonics.push(sPhysicianMnemonic);
			}
		}
		
	}

	//make the array available to the JS destination to loop through.
	channelMap.put('aPhysicianMnemonicArrays',aPhysicianMnemonicArrays);
	//channelMap.put('aPhysicianMnemonicArrays',FileUtil.encode(aPhysicianMnemonicArrays));

}

Last edited by bensonius; 05-15-2017 at 11:27 AM. Reason: Forgot to add code
Reply With Quote
  #7  
Old 05-16-2017, 02:37 AM
siddharth siddharth is offline
Mirth Guru
 
Join Date: Feb 2013
Posts: 832
siddharth is on a distinguished road
Default

From the looks of it, the code needs major re-work. You should be able to create a more decent array. Since I don't know what your end goal is I cannot help you with the code. You will figure out something, there are tonnes of example on the forum.
Reply With Quote
  #8  
Old 05-16-2017, 07:17 AM
bensonius bensonius is offline
Mirth Newb
 
Join Date: May 2017
Posts: 7
bensonius is on a distinguished road
Default

Quote:
Originally Posted by siddharth View Post
From the looks of it, the code needs major re-work. You should be able to create a more decent array. Since I don't know what your end goal is I cannot help you with the code. You will figure out something, there are tonnes of example on the forum.
Yeah, this has been around since way before my time. I was about to embark on re-vamping it. Is there a standard way that Mirth likes arrays to be created? The goal is basically a 2-dimensional array of physician mnemonics. I could split it up into multiple arrays, but I don't see why I would need to.

How would one define a "more decent array"? Is it actually possible to FileUtil.encode an array in Mirth, or am I barking up the wrong tree?

Thanks again!

Last edited by bensonius; 05-16-2017 at 07:22 AM.
Reply With Quote
Reply

Tags
array, code templates, errored messages, queue

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 02:49 AM.


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