web stats
Mirth Tools: User defined functions - Page 5 - Mirth Community

Go Back   Mirth Community > Mirth Connect > Support

Reply
 
Thread Tools Display Modes
  #41  
Old 02-05-2016, 01:38 AM
sanderson sanderson is offline
OBX.1 Kenobi
 
Join Date: Dec 2015
Posts: 45
sanderson is on a distinguished road
Default Attributes?

Hi, is there a simple method in e4x to check for the xexistence of attributes in a node. IE a countAttr() or something, without having to know what the attribute names are the XML schema I have to work with has child attributes in elements where there is no data. So using the strip function removed the element even though there is a populated attribute.

I know this goes against what I understood element/attribute to be about but the schema is not mine so I can't change it.

I haven't found a suitable method or property as yet in the docs. If anyone know such a thing off the top of their head, I'd be very grateful.

Thanks in advance

Stu.
Reply With Quote
  #42  
Old 02-05-2016, 06:31 AM
sanderson sanderson is offline
OBX.1 Kenobi
 
Join Date: Dec 2015
Posts: 45
sanderson is on a distinguished road
Default I think I have it

I modified the original strip function after finding method/props to count the number of attributes.

I have attached the updated code template.

Comments/Improvement/Suggestions invited - flame shields up
Attached Files
File Type: xml Strip Empty Nodes from XM Leaving AttributesL.xml (2.1 KB, 38 views)
Reply With Quote
  #43  
Old 03-15-2016, 01:29 AM
siddharth siddharth is offline
Mirth Guru
 
Join Date: Feb 2013
Posts: 835
siddharth is on a distinguished road
Default Submitting payload as multi-part form data

Here is my addition to this thread

Submitting payload as multi-part form data

I struggled for like 3 days straight to submit payload to a web-service as multi-part form data. Now, we did not had an HTTPS Sender with us, so I had to develop everything in JS, as a method inside code templates.

The concept behind multi-part form-data is that it has 2 or may be more different types of form-data, for eg. one can be JSON, and other XML or plain inside the same payload.


Code:
    var url = new java.net.URL(URLstring);
    var boundary = '------WebKitFormBoundary';
    var dashdash = '--';
    var crlf = '\r\n';
    var prebody = {};  //part 1 JSON
    //Define your JSON below
    var addthisbody = JSON.stringify(prebody);

    //multipart/form-data builder. sensitive, and DO NOT MODIFY.
    var content = boundary + crlf + 'Content-Type: application/json; charset=utf-8' + crlf + 'Content-Disposition: form-data' + crlf + crlf + addthisbody + crlf + crlf + crlf + boundary;
    content = content + crlf + 'Content-Disposition: form-data; name="AutomationTest.xml"; filename="' + tag + '"' + crlf + 'Content-Type: text/xml' + crlf + crlf + ccdcontent + crlf + boundary + dashdash;
    content = content + '\0';

   //Set Your individual headers per requirement.
    conn.setDoOutput(true);
    conn.setDoInput(true);
    conn.setRequestMethod("POST");
    conn.setRequestProperty("Authorization", "Bearer " + access_token); 
    conn.setRequestProperty("Content-type", "multipart/form-data; boundary=----WebKitFormBoundary");    //this step is important
    conn.setRequestProperty("Content-length", content.length);

    // Send request
    var outStream = conn.getOutputStream();
    var outWriter = new java.io.OutputStreamWriter(outStream);
    outWriter.write(content);
    outWriter.close();

//Capture response appropriately
Everything will go as a string inside form-data!

Last edited by siddharth; 03-15-2016 at 01:31 AM. Reason: forgot title
Reply With Quote
  #44  
Old 07-14-2016, 01:02 PM
tiskinty tiskinty is offline
OBX.1 Kenobi
 
Join Date: Jun 2016
Posts: 44
tiskinty is on a distinguished road
Default This is my contribution

These scripts were developed on version 3.0.3.7171, but should carry forward with minimal adjustments.

Code:
/* 
Local Auto-Failover Channel Monitor 
Javascript reader source transformer
Polling type: Interval @ frequency: 5000 
**(Polling frequency should be no greater than 7000. 5000 seems to work best for normal circumstances.)

Monitors the status of two local channels:
- "Fail_Test_Channel" (enabled, deployed and running) (Primary)
- "Fail_Test_Channel_failover" (enabled, undeployed) (Secondary)
When the script detects a channel state other than started or starting for the primary channel, it will auto deploy the secondary and fire off an email notifying the recipient.
Once a starting state is detected on the primary again, the secondary channel will be auto-undeployed.
*/

var channel = "Fail_Test_Channel";
var channel_failover = channel+"_failover";

function monitor(channel){
	if(ChannelUtil.getChannelState(channel)=="Starting"){
		logger.info("Primary Channel: "+channel+" starting. Undeploying failover channel.");
		ChannelUtil.undeployChannel(channel_failover);
		}
	else if(ChannelUtil.getChannelState(channel)!="Started"){
		if(!ChannelUtil.isChannelDeployed(channel_failover)){
			var datetimestamp = DateUtil.getCurrentDate("yyyyMMdd@HH:mm:ss");
			logger.info("WARNING! CHANNEL FAILURE! Channel: "+channel+" Recorded @ "+datetimestamp);
			ChannelUtil.deployChannel(channel_failover);
			logger.info("Deploying Failover Channel");
			var smtpConn = SMTPConnectionFactory.createSMTPConnection();
			var emNotice = channel+" has stopped responding and "+channel_failover+" is being deployed.\n@"+datetimestamp;
			var emSub = "Channel Failure: "+channel+" @"+datetimestamp;
			smtpConn.send('mirth@example.com', '', 'LOCAL_ALERT@mirth.example.com', emSub, emNotice, 'US-ASCII');
			}
		else{
			if(ChannelUtil.getChannelState(channel_failover)=="Started"){
				}
			else{
				ChannelUtil.startChannel(channel_failover);
				}
			}
		}
	return;
	}

monitor(channel);
Code:
/*
This script is mostly a proof of concept for a remote version of the above script. 
Remote Auto-Failover Channel Monitor 
Javascript reader source transformer
Polling type: Interval @ frequency: 5000 
**(Polling frequency should be no greater than 7000. 5000 seems to work best for normal circumstances.)

This script monitors two channels:
- "Remote_Failover_Test" (remote server, deployed, running) (Primary)
- "Remote_Failover_Test_failover" (local server, enabled, undeployed) (Secondary)

When the script detects a channel state other than started or starting for the primary channel, it will auto deploy the secondary.
Once a starting state is detected on the primary again, the secondary channel will be auto-undeployed.
*/
var info = {
	URL: 'https://localhost:8443',
	user: 'admin',
	pass: 'admin',
	version: '3.0.3.7171',
	timeout: 10000
	};

function monitor(channel,state){
var channel_failover = channel+"_failover"
	if(state=="Starting"){
		logger.info("Primary Channel: "+channel+" starting. Undeploying failover channel.");
		ChannelUtil.undeployChannel(channel_failover);
		}
	else if(state!="Started"){
		if(!ChannelUtil.isChannelDeployed(channel_failover)){
			logger.info("WARNING! CHANNEL FAILURE! Channel: "+channel+" Recorded @ "+DateUtil.getCurrentDate("yyyyMMdd@HH:mm:ss"));
			ChannelUtil.deployChannel(channel_failover);
			logger.info("Deploying Failover Channel");
			}
		else{
			if(ChannelUtil.getChannelState(channel_failover)=="Started"){
				}
			else{
				ChannelUtil.startChannel(channel_failover);
				}
			}
		}
	return;
	}

var monitor_list = [];
monitor_list[0] = "Remote_Failover_Test";
var monitorLog = {"Remote_Failover_Test" : "FAILED"};
var client = new com.mirth.connect.client.core.Client(info.URL,info.timeout);
var loginStatus = client.login(info.user,info.pass,info.version);
var status = client.getChannelStatusList().toString().split("channelId=");
var statLen = status.length-1;
var subStatus;
var chaName;
var chaState;


for(var i=1;i<=(statLen);i++){
	subStatus = status[i].split(",lifetimeStatistics=")[0];
	if(subStatus.indexOf("deployedDate=<null>")<0){
		chaName = subStatus.split("name=")[1].split(",state=")[0].toString();
		chaState = subStatus.split(",state=")[1].split(",")[0].toString();
		for(var k in monitor_list){
			if(monitor_list[k] == chaName){
				monitorLog[chaName]=chaState;
				}
			}
		}
	}

for(var k in monitorLog){
	//logger.info(k+" "+monitorLog[k]);
	monitor(k,monitorLog[k]);
}
__________________
Matt

http://theunofficialmirthadmin.blogspot.com/
Reply With Quote
  #45  
Old 11-22-2016, 01:16 AM
dotties5 dotties5 is offline
What's HL7?
 
Join Date: Sep 2016
Posts: 2
dotties5 is on a distinguished road
Default

Thanks for all of these contributions. This is super helpful. I bookmarked this, to take a look again in the future.

Keep up the good work!
Reply With Quote
  #46  
Old 12-22-2016, 08:54 AM
hugosoares2 hugosoares2 is offline
OBX.2 Kenobi
 
Join Date: May 2011
Posts: 64
hugosoares2 is on a distinguished road
Default Call Webservice With NTLM authentication (.NET Services)

Mirth Web Service sender and Http Sender connector types do not fully support NTLM Http Authentication scheme because it works by mantaining a persistent http connection to the server during authentication/negotiation.

This function can be used to call such services by using apache's HttpClient directly.

This function uses packages already included in Mirth (tested on 3.4.2)

Code:
var body = 
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:pub="namespacex"> <soap:Header/>
	<soap:Body> 
		<pub:query> 
			input data
		</pub:query> 
	</soap:Body> 
</soap:Envelope>;
	
var endpoint = "/WSContext/aMicrosoftService.asmx";
var response = callWebServiceNtlm("servicehost", 80, "http", "user", "pass", "domain", body.toString(), endpoint);

response.status;// holds the http status line
response.responseBody;// holds the http response body as string

function callWebServiceNtlm(host, port, protocol, username, password, domain, soapBody, endpoint) {
    importPackage(Packages.org.apache.http.impl.client);
    importPackage(Packages.org.apache.http);
    importPackage(Packages.org.apache.http.auth);
    importPackage(Packages.org.apache.http.client);
    importPackage(Packages.org.apache.http.client.methods);
    importPackage(Packages.org.apache.http.client.protocol);
    importPackage(Packages.org.apache.http.entity);
    importPackage(org.apache.commons.io);
    

    var	hostName = 'unknown';
    try{
     hostName = Packages.java.net.InetAddress.getLocalHost().getHostName();
    }catch(e){logger.error(e);}
    
    var httpclient = HttpClients.createDefault();
    
    var credsProvider = new BasicCredentialsProvider();
    credsProvider.setCredentials(AuthScope.ANY,
            new NTCredentials(username, password, hostName, domain));
    
    var target = new HttpHost(host, port, protocol);
    
    // Make sure the same context is used to execute logically related requests
    var context = HttpClientContext.create();
    context.setCredentialsProvider(credsProvider);
    
    // Execute a cheap method first. This will trigger NTLM authentication
    var httppost = new HttpPost(endpoint);
    httppost.addHeader("Content-Type", "application/soap+xml");
    httppost.setEntity(new StringEntity(soapBody));
    var response1 = httpclient.execute(target, httppost, context);
    var log = {};
    try {
        var entity1 = response1.getEntity();
        log.status = response1.getStatusLine().toString();
        var responseBody = IOUtils.toString(response1.getEntity().getContent(), "UTF-8");
        log.responseBody = responseBody;
    } finally {
        response1.close();
    }
    
    return log
}
Reply With Quote
  #47  
Old 02-12-2017, 10:23 PM
Lord Teaspoon Lord Teaspoon is offline
What's HL7?
 
Join Date: Feb 2017
Posts: 1
Lord Teaspoon is on a distinguished road
Default

I mentioned in Slack that I'd come and post this some time, so here it is...

The below function converts between any image formats supported by javax.imageio (plus JAI, which is bundled, plus any other ImageIO extensions in your custom-lib).

Code:
function convertImage(imageData, format) {
	var results = [];
	var byteInputStream = new java.io.ByteArrayInputStream(FileUtil.decode(imageData));
	var imageInputStream = javax.imageio.ImageIO.createImageInputStream(byteInputStream);
	var imageReaders = javax.imageio.ImageIO.getImageReaders(imageInputStream);
	var imageReader = imageReaders.next();
	imageReader.setInput(imageInputStream);
	for (var i=0; i<imageReader.getNumImages(true); i++){
		var bufImage = imageReader.read(i);
		var byteOutputStream = new java.io.ByteArrayOutputStream();
		var imageOutputStream = javax.imageio.ImageIO.createImageOutputStream(byteOutputStream);
		javax.imageio.ImageIO.write(bufImage, format, imageOutputStream);
		results.push(FileUtil.encode(byteOutputStream.toByteArray()));	
	}
	return results;
}
Note that this expects a string (base64-encoding) for imageData and will return an array of strings as a result. We interact with a customer's RIS by sending QRY messages and parsing base64-encoded multipage TIFFs from the response messages. The script looks like:

Code:
for each (obx in msg..OBX){
	var jpegs = convertImage(obx['OBX.5']['OBX.5.1'].toString(), 'JPEG');
	for each (jpeg in jpegs){
		jpegBytes = FileUtil.decode(jpeg);
		//do magic here
	}
}
Right now my "magic" is doing ugly things involving FileUtil.write and exec to use command line tools to wrap the jpegs in DICOM and send them on, but longer-term I hope to do that all inside the script by building a header and running DICOMUtil.mergeHeaderPixelData to get something that I can push to a DICOM-sending channel.
Reply With Quote
  #48  
Old 03-22-2017, 04:26 PM
mpatterson mpatterson is offline
Mirth Newb
 
Join Date: Dec 2008
Posts: 9
mpatterson
Default

Quote:
Originally Posted by narupley View Post
renameField: Returns a copy of the given HL7 field, changing all segment names to the given name.
I'm having trouble with renameField. I want to take the value in PV1-6 and put it into PV1-3. Easy enough:

Code:
msg.PV1['PV1.3'] = renameField(msg.PV1['PV1.6'],'PV1.3');
However, in doing this, it's changing my OBX segment.

Code:
OBX|1|TX|V&GDT||CT FACE WITHOUT CONTRAST||||||F|||20170314150729
OBX|2|TX|V&GDT|| ||||||F|||20170314150729
OBX|3|TX|V&GDT||REASON FOR EXAMINATION: Motor vehicle accident, altered mental status.||||||F|||20170314150729
Becomes

Code:
OBX|1|TX|V&GDT||CT FACE WITHOUT CONTRAST||||||F|||20170314150729
OBX|2|TX|V&GDT||||||||F|||20170314150729
OBX|3|TX|V&GDT||REASON FOR EXAMINATION: Motor vehicle accident, altered mental status.||||||F|||20170314150729
In the second OBX line, OBX-5 changed from having a space in it to being completely blank.

Is there any way to modify the code so that the spaces in OBX-5 won't be trimmed?
Reply With Quote
  #49  
Old 05-04-2017, 11:13 AM
tiskinty tiskinty is offline
OBX.1 Kenobi
 
Join Date: Jun 2016
Posts: 44
tiskinty is on a distinguished road
Default Custom Java ClassLoader

If you're like me, when I'm working on testing a new channel and I'm trying to implement custom java classes, I tend to do a lot of tweaking. I wrote this script to allow me to make quick changes to what classes are available. That way I can skip dropping them into the custom-lib folder and restarting mirth every time I need something small changed.

I probably wouldn't recommend using this in a production setting, but it's been an amazing addition to my testing environment.

Code:
/*
 Mirth Custom Java ClassLoader in Rhino Javascript
	Java Version 1.8
	Rhino Version 1.7R5

	folderpath: full URI folderpath to base folder where the package folder is located
	classpath: FQN classpath from base folder
	
	folder structure MUST follow this format to function correctly:
		C:/javaBaseFolder/
			--> hello/
				--> HelloWorld.class
		>> folderpath = 'file:/C:/javaBaseFolder/'
		>> classpath = 'hello.HelloWorld'
	
	Example Class:
	>	package hello;
	>
	>	public class HelloWorld{
	>		public static String main() {
	>			return "Hello World!";
	>		}
	>	}

	Use calling format like this:
		>> var myClass = classImport('file:/C:/javaBaseFolder/','hello.HelloWorld');
		>> myClass.getConstructor(null).newInstance(null).main();
*/ 
function classImport(folderpath,classpath) {
  var location = new java.net.URL(folderpath);
  var urlArray = java.lang.reflect.Array.newInstance(java.net.URL, 1);
  urlArray[0] = location;
  var classLoader = new java.net.URLClassLoader(urlArray);
  return classLoader.loadClass(classpath);
}

var myClass = classImport('file:/C:/javaBaseFolder/','hello.HelloWorld');

logger.info(myClass.getConstructor(null).newInstance(null).main());
Reply With Quote
  #50  
Old 05-04-2017, 11:18 AM
narupley's Avatar
narupley narupley is offline
Mirth Employee
 
Join Date: Oct 2010
Posts: 7,124
narupley is on a distinguished road
Default

Quote:
Originally Posted by tiskinty View Post
If you're like me, when I'm working on testing a new channel and I'm trying to implement custom java classes, I tend to do a lot of tweaking. I wrote this script to allow me to make quick changes to what classes are available. That way I can skip dropping them into the custom-lib folder and restarting mirth every time I need something small changed.

I probably wouldn't recommend using this in a production setting, but it's been an amazing addition to my testing environment.
That should not be necessary in MC version 3.2 and later. We added the ability to load (and reload) JARs live without requiring a restart. Look at the Settings -> Resources tab.
__________________
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
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 03:09 AM.


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