adiddigi
Tera Guru

This post is an improvement over the post Get filenames from a FTP server.
In this post we run the entire code of getting the files names in a Business Rule on a MID server Script Include.The reason why you would want to run this on the MID server is : Some times, you forget to close the connection you made to FTP, and that may result in bringing down the instance(It did happen to me). Not only closing a connection, too many sessions from SNOW to FTP will result in performance issues.

There are 3 steps involved in this entire communication :
1. Call the MID script include from the business rule(when you actually want to get the filenames in Service Now and do something)
2. In the MID server script, embed the call to an FTP server.
3.When ever you make this call, a probe will be sent to MID server and the MID server will reply(after executing the MID script include),and both these entries are found in ECC Queue;So have a business rule to process the Input we received from MID server's Script Include(I used XML helper for this)

Business Rule:
Name : Talk to MID
Type : Can be anything- depends on the requirement



fnToMidserver();

function fnToMidserver(){

try{

/* we have defined many parameters as we use it again and again at many places*/
var ftpServer = gs.getProperty("host");
var username = gs.getProperty("login");
var pswrd = gs.getProperty("password");
var port= gs.getProperty("port");
var type=gs.getProperty("type");
var timeout=gs.getProperty("timeout");
var passive=gs.getProperty("passive");
var ftpFilePath = gs.getProperty("FTP Attachment");
var StringUtil = Packages.com.glide.util.StringUtil;
/* You can actually skip these two variables binData and encData;This is specific to my requirement*/
var binData = 'test';
var encData =StringUtil.base64Encode(binData);
var jspr = new JavascriptProbe('Integration');/*Integration is the Name of MID server*/
jspr.setName('FileGetMIDServer'); /* Any description will do, this will be the name of the PROBE that will be sent and the identifier in ECC Queue*/
jspr.setJavascript("var ddr = new MidFilenameRetr();res = ddr.execute();");
/* Again you can ignore setting this parameter */
jspr.addParameter("encodedData",encData);
var cred = username+":"+pswrd;
/* this is the sys_id of the current parameter, I used it as when I get a reply from MID server and there are multiple Inputs(the MID server script include is called multiple times, and it sends the replies back, we would want to identify the particular record that made the request*/
jspr.addParameter("sysId",current.sys_id);
jspr.addParameter("ftpCred",cred);
jspr.addParameter("ftpTargetServer",ftpServer);
jspr.addParameter("ftpPort",port);
jspr.addParameter("targetPath",ftpFilePath);
jspr.addParameter("host",ftpServer);
jspr.addParameter("transportMethod",type);
jspr.create();
gs.log('Completed: Check Mid Server log');
}
catch(e){
gs.log('exception in calling mid server : '+e);

}
}


Now we have a business rule that talks to MID server. Please note, the MID server Script Include MidFilenameRetr() will NOT have access to Service Now gs object,it runs in the scope of MID server and it has access to all the jars that are defined with in the MID server setup.More information on this for another day.That post will also have a java code which users Reflection API to get the class definitions and method declarations of the MID jars.

Script Include :
Name : MidFilenameRetr


var MidFilenameRetr= Class.create();

MidFilenameRetr.prototype = {
initialize : function() {

this.debug = false;
this.MIDSERVER_PROCESSED_FILE_PATH = "processed/";
this.resLog = "FTP Log: \n";
this.log("Initializing SNDataRetriever");
this.MIDSERVER_FILE_PATH = "work/";
//this.MIDSERVER_FILE_NAME = probe.getParameter('targetFileName');

this.Encoded_Data = probe.getParameter('encodedData');

this.useProxy = this.getConfigParameter("mid.proxy.use_proxy");
if (this.useProxy){
this.proxyHost =this.getConfigParameter("mid.proxy.host");
this.proxyPort =this.getConfigParameter("mid.proxy.port");
this.proxyUser =this.getConfigParameter("mid.proxy.username");
this.proxyPass =this.getConfigParameter("mid.proxy.password");
}
this.user = this.getConfigParameter("mid.instance.username");
this.password = this.getConfigParameter("mid.instance.password");
/* here we are creating an actual FTP connection between MID server and FTP*/
var ftpCredArr = this.decryptCredentials(probe.getParameter('ftpCred'));
this.ftpUser = ftpCredArr[0];
this.ftpPass = ftpCredArr[1];
this.log('ftp username : '+ftpCredArr[0]);
this.log('ftp password : '+ftpCredArr[1]);
this.ftpTargetServer = probe.getParameter('ftpTargetServer');
this.ftpPort = (this.isANumber(probe.getParameter('ftpPort'))) ? (probe.getParameter('ftpPort')) : null;

this.sysID = probe.getParameter("sysId");
this.targetPath = probe.getParameter('targetPath');
// this.targetFileName = probe.getParameter('targetFileName');

this.host = probe.getParameter('host');

this.transportMethod = probe.getParameter('transportMethod');

if (this.debug){
this.log("\n********** Debug Info **********\nuser: " + this.user + "\npass: " + this.password + "\ntransportMethod: " + this.transportMethod + "\nreport: " + this.reportURL+ "\nhost: "+ this.host);
this.log("\n********** Proxy Info **********\nproxyNeeded: " + this.proxyNeeded +"\nproxyUser : " + this.proxyUser + "\nproxyPass :" + this.proxyPass );
this.log("\nproxyHost: " + this.proxyHost + "\nproxyPort:" + this.proxyPort);
this.log("\n********** FTP Info ************\nftpUser: "+ this.ftpUser + "\nftpPass: " + this.ftpPass + "\nftpPort: " + this.ftpPort);
this.log("\n********** End of Debug ********\n\n");
}
},
getConfigParameter: function(parm){
var m= Packages.com.service_now.mid.MIDServer.get();
var config = m.getConfig();
var res = config.getParameter(parm);
var res2 = config.getProperty(parm);
if (res){
return res;
}
else if (res2){
return res2;
}
else{
config = Packages.com.service_now.mid.services.Config.get();
return config.getProperty(parm);
}

},

decryptCredentials: function(data) {
var cred = new String(data);
var e = new Packages.com.glide.util.Encrypter();

var jsCred = cred + '';
var usernamePass = e.decrypt(jsCred);
var credArr = usernamePass.split(":", 2);
return credArr;
},

execute: function() {
var result = '';
this.log("Running FileDataRetriever execute");
var pt = new Packages.java.util.Properties();
pt.setProperty("connection.host", this.ftpTargetServer);
pt.setProperty("connection.port", this.ftpPort);
pt.setProperty("user.login", this.ftpUser);
pt.setProperty("user.password", this.ftpPass);
pt.setProperty("connection.type", this.transportMethod);
pt.setProperty("connection.timeout", '10000');
pt.setProperty("connection.passive", 'true');
var connection = Packages.org.ftp4che.FTPConnectionFactory.getInstance(pt);
connection.connect();
var myFiles = connection.getDirectoryListing(this.targetPath);
/* myFiles is an ArrayList - connection.getDirectoryListing returns an ArrayList object - hence the lines below, thanks to the community, I found the join method and used it 🙂 */
var toArray = myFiles.toArray();
var ret= toArray.join(',');
ret = this.sysID+'|'+ret;
/* note that, as I said,I am appending the sysID so that i can identify the sys_id that generated the request on MID server, and I can do something on that record */
return ret;


},
getLog: function() {
return this.resLog;
},

log: function(data) {
ms.log(data);
this.resLog+="\n"+data;
},

isANumber: function(data) {
data = data + '';
return ((data - 0) == data && data.length > 0);
},


type : "MidFilenameRetr"
};


Point to note : The result that you return in this MID server Script include will be embedded in the tags


!What ever you return!


in the incoming payload in the ECC Queue.


[Thanks to Mark Stanger and Jacob Andersen for the Script Includes that import the attachments and put them on an FTP, Most of the code is lifted from there]

Now, the last step of processing the ECC queue and returning it back to the record that created the request :

Name : Business Rule
Table: ecc_queue
Condition :current.queue=="input"



function checkFile(){

var content=current.payload;
var xh = new XMLHelper();
var obj = xh.toObject(content);
content = obj.result.output;
var files=content.split('|')[1];
var sysId='';
sysId= content.split('|')[0];
/*This is how you use XML helper to process the output.Thanks to Tom for the XML helper class- I mean Script Include*/
}




Acknowledgements:
1.The original idea was different, it was to move a file into MID server from Service Now and then from MID server to a FTP server.I modified the code, to get the file names. Mohammed Ishaq Khan is the guy who worked on that, and you can read the Send files out to FTP via MID server on Service Now Diary.
2.To James Andersen, for the information on MID server Script Includes.

8 Comments