How to send attachment to Jira from Servicenow

Mike Patel
Tera Sage

Hi all,

When we create ticket in ServiceNow and assigns it to Jira group it creates ticket in Jira with all the information except the attachment.

Can anyone help on how to send attachment to Jira from Servienow.

Thank you

1 ACCEPTED SOLUTION

Solution:


Add below to business rule;


j.addExistingComments(current.sys_id, current.correlation_id);



Create MID Server Script Include


Name: CopyAttachments


Script:


var CopyAttachments = Class.create();




CopyAttachments.prototype = {


      initialize: function() {


              this.debug = probe.getParameter("debug");


              this.debug = true;


              this.logMsg("Starting MID Server File Transfer");


              this.charset = "UTF-8";


              this.LINE_FEED = "\r\n";




              this.boundary = "-----------------------------" + new Date().getTime();


              this.probeParameters = this._getProbeParameters();


              this.response = this.getRemoteFileAndUploadToInstance();


      },




      getRemoteFileAndUploadToInstance: function() {


              var url = this._getInstanceConnectionURL();


              var conn = this._getURLConnection(url);


              var file = this._getFile();


              var response = this._writeFile(conn, file);


              if (response != 200)


                      throw "HTTP response " + response;


              this.logMsg("HTTP response " + response, "debug");




              ms.log("Completed MID Server File Transfer");


              return response;


      },




      _getProbeParameters: function() {


              var probeObj = {};


              probeObj.encpayload = probe.getParameter("filePayload");


              probeObj.fileName = probe.getParameter("fileName");


              probeObj.username = ms.getConfigParameter("mid.jira.user");


              probeObj.password = this._decryptParam(ms.getConfigParameter("mid.jira.password"));


              probeObj.contentType = probe.getParameter("contentType");


              probeObj.JIRA = probe.getParameter("JIRA");


              probeObj.correlationID = probe.getParameter("correlationID");


              return probeObj;


      },




      _getInstanceConnectionURL: function() {


              var base = this.probeParameters.JIRA;


              var mid = "/rest/api/2/issue/";


              var issue = this.probeParameters.correlationID;


              var end = "/attachments";


              return base + mid + issue + end;


      },




      _encodeParam: function(k, v) {


              return k + "=" + Packages.java.net.URLEncoder.encode(v);


      },




      _joinParams: function(base, arr) {


              return base + '?' + arr.join('&');


      },




      _decryptParam: function(encPass) {


              var e = new Packages.com.glide.util.Encrypter();


              var unEncPass = e.decrypt(encPass);  


              return unEncPass;


      },




      _getURLConnection: function(url) {


              if (ms.getConfigParameter("mid.proxy.use_proxy") == 'true') {


                      Packages.java.lang.System.setProperty("https.proxyHost", ms.getConfigParameter("mid.proxy.host"));


                      Packages.java.lang.System.setProperty("http.proxyHost", ms.getConfigParameter("mid.proxy.host"));


                      Packages.java.lang.System.setProperty("https.proxyPort", ms.getConfigParameter("mid.proxy.port"));


                      Packages.java.lang.System.setProperty("http.proxyPort", ms.getConfigParameter("mid.proxy.port"));


              }


              var conn = new Packages.java.net.URL(url).openConnection();




              this.logMsg("Sending to : " + url, "debug");




              var userpass = new java.lang.String(this.probeParameters.username + ":" + this.probeParameters.password);


              conn.setRequestProperty("X-Atlassian-Token", "nocheck");


              conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + this.boundary);


              var basicAuth = "Basic " + (new Packages.javax.xml.bind.DatatypeConverter.printBase64Binary(userpass.getBytes()) + '');


              conn.setRequestProperty("Authorization", basicAuth);


              conn.setDoOutput(true);


              conn.setDoInput(true);


              conn.setRequestMethod("POST");


              conn.setUseCaches(false);


              //conn.setRequestProperty("User-Agent", "ServiceNow MID Server POST");


              return conn;


      },




      _getFile: function() {


              //Get The File as Base64 and convert to ByteArrayInputStream


              return new Packages.com.glide.util.StringUtil.base64DecodeAsBytes(this.probeParameters.encpayload);


      },




      _writeFile: function(conn, uploadFile) {


              var outputStream = conn.getOutputStream();


              var writer = new Packages.java.io.PrintWriter(new Packages.java.io.OutputStreamWriter(outputStream, this.charset), true);


              var fieldName = 'file'; // JIRA Requires this as 'file'


              var fileName = this.probeParameters.fileName;




              this.logMsg("Sending file : " + fileName, "debug");




              writer.append("--" + this.boundary).append(this.LINE_FEED);


              writer.append("Content-Disposition: form-data; name=\"" + fieldName + "\"; filename=\"" + fileName + "\"").append(this.LINE_FEED);


              //Sometimes ServiceNow does not have the content type for a file (attempt to get it, otherwise default to octet-stream):


              if (JSUtil.notNil(this.probeParameters.contentType)) {


                      writer.append("Content-Type: " + this.probeParameters.contentType).append(this.LINE_FEED);


              } else if (JSUtil.notNil(Packages.java.net.URLConnection.guessContentTypeFromName(fileName))) {


                      writer.append("Content-Type: " + Packages.java.net.URLConnection.guessContentTypeFromName(fileName)).append(this.LINE_FEED);


              } else {


                      writer.append("Content-Type: application/octet-stream").append(this.LINE_FEED);


              }


              writer.append("Content-Transfer-Encoding: binary").append(this.LINE_FEED);


              writer.append(this.LINE_FEED).flush();




              this._writeFileData(uploadFile, outputStream);




              writer.append(this.LINE_FEED).flush();


              writer.append(this.LINE_FEED).flush();


              writer.append("--" + this.boundary + "--").append(this.LINE_FEED);


              writer.close();


              var readResponse = "";


              if (conn.getResponseCode() == 200) {


                      var reader = new Packages.java.io.BufferedReader(new Packages.java.io.InputStreamReader(conn.getInputStream()));


                      var line = reader.readLine();


                      while (line != null) {


                              readResponse += line;


                              line = reader.readLine();


                      }


              }


              return conn.getResponseCode();


      },






      _writeFileData: function(uploadFile, outputStream) {


              var inputStream = new Packages.java.io.ByteArrayInputStream(uploadFile);




              var data = new Packages.java.lang.reflect.Array.newInstance(java.lang.Byte.TYPE, 4096);


              var bytesRead = 0;


              while ((bytesRead = inputStream.read(data)) != -1) {


                      outputStream.write(data, 0, bytesRead);


                      outputStream.flush();


              }


              inputStream.close();


      },




      logMsg: function(message, logType) {


              logType = logType || 'info';


              var prefixStr = "*** MID Server Remote File";


              if (logType == 'info' || logType == 'error') {


                      ms.log(prefixStr + " " + logType.toUpperCase() + "*** " + message);


              }


              if (this.debug && logType == 'debug') {


                      ms.log(" DEBUG *** " + message);


              }


      },




      type: "CopyAttachments"


};



Add to Main Script Library (under Jira)


addExistingAttachments: function(taskID, corrID) {


              this.debug("Adding Attachments for : " + taskID);


              var attachment = new GlideRecord('sys_attachment');


              attachment.addQuery('table_sys_id', taskID);


              attachment.query();


              while (attachment.next()) {


                      this._buildAttachmentRequest(attachment, taskID, corrID);


              }


      },




      _buildAttachmentRequest: function(att, taskID, corrID) {


              try {


                      var sa = new GlideSysAttachment();


                      var binData = sa.getBytes(att);


                      var encData = GlideStringUtil.base64Encode(binData);


                      var file_name = att.file_name.toString();


                      var contentType = att.content_type.toString();


                      this._sendAttachmentRequest(encData, file_name, contentType, corrID);


                      this.debug("Adding Attachment : " + file_name + " Content-Type: " + contentType);


              } catch (Exception) {


                      this.debug('Failed sending Attachment to due to Exception: ' + Exception);


              }




      },




      _sendAttachmentRequest: function(encData, file_name, contentType, corrID) {


              //Calls the MID Server Script Include


              this.debug("Calling MID Server Script Include");


              var jp = new JavascriptProbe(this.midServer);


              jp.setName("CopyAttachments");


              jp.setJavascript("var req = new CopyAttachments();");


              jp.addParameter("filePayload", encData);


              jp.addParameter("JIRA", gs.getProperty('com.snc.integration.jira.base_jira_instance_url'));


              jp.addParameter("fileName", file_name);


              jp.addParameter("contentType", contentType);


              jp.addParameter("correlationID", corrID);


              jp.create();


      },



Make sure you have MID Server selected


Untitled.png


View solution in original post

29 REPLIES 29

Hi Patel,



I also implemented this for one of our customers and everything works fine, expect that when sending X office files such as .docx, .xlsx, .pptx, the files are sent correctly, however when downloading them from Jira, we got these messages:



If you click yes and ignore, the files open just fine.



Have you seen this?



Screen Shot 2017-08-30 at 15.41.04.png




Screen Shot 2017-08-30 at 15.41.15.png


No, I never had that issue. It opens up perfectly without any prompt. Check office settings, it might have something related to that.


Hi Mike

 

thanks for the code,

 

I have tried this as you posted and but it is not working I am getting an error as soon I add a MidServer in the property.

org.mozilla.javascript.EcmaError: Cannot read property "self" from null
Caused by error in sys_ui_action.dff28cbb1b9d37005839eb186e4bcb06.script at line 54

51:
52: j.debug("Jira fields set. Ready to create issue in Jira");
53: var jiraIssue = j.createIssue(issue);
==> 54: j.debug("Jira issue created: " + jiraIssue.self);
55:
56: current.correlation_id = jiraIssue.key;
57: current.correlation_display = j.CORRELATION_DISPLAY;

ERROR: Web Service did not respond after 30 seconds

 

Under the RESTProbe Queue I can see also an input error: No sensors defined

When I remove it from the setting it works but without the attachment.

 

my API to Jira is working only I am not able to add the attachment with creating the issue in Jira,.

 

Any Idea?

 

thanks

Elias

may i ask what does it means, in the script#2, Add to Main Script Library (under Jira), I am quite confused, now i am using ROME version and in the need of sending attachment to JIRA

epam
Kilo Guru

Hi Mike,



you also may use base64 encoding for attachments and send them via SOAP/REST to JIRA.