Copying attachment from one instance to another+

khusboo1
Kilo Expert

I am getting the following error while copying attachments from one instance to another in helsinki instance using SOAP.The error is  

'Illegal attempt to access class 'com.glide.util' via script'.Any help is deeply appreciated.

1 ACCEPTED SOLUTION

Lets try another way to help you... At K17 a few weeks ago I had created a HackLab on this topic and unfortunately that lab guide hasn't been posted yet to the Community.   In that lab there was a use case where an incident needs to be sent from one ServiceNow instance to another and along with the record's attachments.   Basically a business rule runs after insert of an incident based on whatever conditions you need it to.   Below is the script that first send the incident to the target and then query for any attachments and send those as well.   Hopefully this example script will be helpful to solve your issue.



var targetInstanceURL =   "https://TARGET-NAME.service-now.com/";


var targetUserID = "USER-NAME";


var targetUserPassword = "USER-PASSWORD";



var answer = "";


var attachmentMsg = "";



//Create a JSON string with the current incident attributes


var incidentJSON = {};


incidentJSON.caller_id = current.caller_id.toString();


incidentJSON.category = current.category.toString();


incidentJSON.impact = current.impact.toString();


incidentJSON.urgency = current.urgency.toString();


incidentJSON.priority = current.priority.toString();


incidentJSON.short_description = current.short_description.toString();



// Set the Correlation fields to link the new incident with the source incident


incidentJSON.correlation_display = "ServiceNow";


incidentJSON.correlation_id = current.sys_id.toString();



// Encode JSON string


var requestBody = new global.JSON().encode(incidentJSON);



// Create incident in target instance via REST


var restMessage = new sn_ws.RESTMessageV2();


restMessage.setHttpMethod("post");


restMessage.setBasicAuth(targetUserID, targetUserPassword);


restMessage.setEndpoint(targetInstanceURL + "api/now/table/incident");


restMessage.setRequestHeader("Content-Type", "application/json");


restMessage.setRequestBody(requestBody);



var response = restMessage.execute();


var responseBody = response.getBody();


var httpStatus = response.getStatusCode();



if (httpStatus.toString() == "201") {


      answer = "Incident successfully sent.";



      // Get target record's SysID


      var parser = new JSONParser();


      var parsed = parser.parse(responseBody);


      var targetRec = parsed.result;



      var attachmentCount = sendAttachments(current.getTableName(), current.sys_id, targetRec.sys_id);


      if (attachmentCount != "none") {


              attachmentMsg =   " Attachments successfully sent: " + attachmentCount[0].toString() + ". Attachments failed to be sent: " + attachmentCount[1].toString();


      } else {


              attachmentMsg =   " Record had no attachments to send.";


      }


} else {


      answer = "Incident could not be sent.";


}


answer = answer + attachmentMsg;



// Set message at top of screen with results.


gs.addInfoMessage(answer);



function sendAttachments(sourceTable, sourceID, targetID) {


      var answer = [0, 0]; //successful attachments, failed attachments


     


      // Query for any attachments on the current record.


      var attachmentRec = new GlideRecord("sys_attachment");


      attachmentRec.addQuery("table_sys_id", sourceID);


      attachmentRec.addQuery("table_name", sourceTable);


      attachmentRec.query();


      if (attachmentRec.hasNext()) {


              while (attachmentRec.next()) {


                      var attachmentMessage = new sn_ws.RESTMessageV2();


                      attachmentMessage.setHttpMethod("post");


                      attachmentMessage.setBasicAuth(targetUserID, targetUserPassword);


                      attachmentMessage.setEndpoint(targetInstanceURL + "api/now/attachment/file");


                      attachmentMessage.setQueryParameter("table_name", attachmentRec.table_name);


                      attachmentMessage.setQueryParameter("table_sys_id", targetID);


                      attachmentMessage.setQueryParameter("file_name", attachmentRec.file_name);


                      attachmentMessage.setRequestHeader("Content-Type", attachmentRec.content_type);


                      attachmentMessage.setRequestHeader("Accept", "application/json");


                      attachmentMessage.setRequestBodyFromAttachment(attachmentRec.sys_id);



                      var response = attachmentMessage.execute();


                      var responseBody = response.getBody();


                      var httpStatus = response.getStatusCode();



                      if (httpStatus.toString() == "201") {


                              answer[0] += 1;


                      } else {


                              answer[1] += 1;


                      }


              }


      } else {


              answer = "none";


      }


      return answer;


}


View solution in original post

25 REPLIES 25

As mentioned the SysID of your incident in your target instance is going to be different than your source. The REST Attachment API requires the SysID if the record the attachment needs to link to.   Since the source SysID doesn't exist in the target, that is why its failing.



How are you creating the attachments in your target instance?   Are you storing the target SysID in the source incident?


Agree to your thoughts,but i have used the sys_id of attachment record present in target instance.I have not used source sys_ids.Hope this helps.


Lets try another way to help you... At K17 a few weeks ago I had created a HackLab on this topic and unfortunately that lab guide hasn't been posted yet to the Community.   In that lab there was a use case where an incident needs to be sent from one ServiceNow instance to another and along with the record's attachments.   Basically a business rule runs after insert of an incident based on whatever conditions you need it to.   Below is the script that first send the incident to the target and then query for any attachments and send those as well.   Hopefully this example script will be helpful to solve your issue.



var targetInstanceURL =   "https://TARGET-NAME.service-now.com/";


var targetUserID = "USER-NAME";


var targetUserPassword = "USER-PASSWORD";



var answer = "";


var attachmentMsg = "";



//Create a JSON string with the current incident attributes


var incidentJSON = {};


incidentJSON.caller_id = current.caller_id.toString();


incidentJSON.category = current.category.toString();


incidentJSON.impact = current.impact.toString();


incidentJSON.urgency = current.urgency.toString();


incidentJSON.priority = current.priority.toString();


incidentJSON.short_description = current.short_description.toString();



// Set the Correlation fields to link the new incident with the source incident


incidentJSON.correlation_display = "ServiceNow";


incidentJSON.correlation_id = current.sys_id.toString();



// Encode JSON string


var requestBody = new global.JSON().encode(incidentJSON);



// Create incident in target instance via REST


var restMessage = new sn_ws.RESTMessageV2();


restMessage.setHttpMethod("post");


restMessage.setBasicAuth(targetUserID, targetUserPassword);


restMessage.setEndpoint(targetInstanceURL + "api/now/table/incident");


restMessage.setRequestHeader("Content-Type", "application/json");


restMessage.setRequestBody(requestBody);



var response = restMessage.execute();


var responseBody = response.getBody();


var httpStatus = response.getStatusCode();



if (httpStatus.toString() == "201") {


      answer = "Incident successfully sent.";



      // Get target record's SysID


      var parser = new JSONParser();


      var parsed = parser.parse(responseBody);


      var targetRec = parsed.result;



      var attachmentCount = sendAttachments(current.getTableName(), current.sys_id, targetRec.sys_id);


      if (attachmentCount != "none") {


              attachmentMsg =   " Attachments successfully sent: " + attachmentCount[0].toString() + ". Attachments failed to be sent: " + attachmentCount[1].toString();


      } else {


              attachmentMsg =   " Record had no attachments to send.";


      }


} else {


      answer = "Incident could not be sent.";


}


answer = answer + attachmentMsg;



// Set message at top of screen with results.


gs.addInfoMessage(answer);



function sendAttachments(sourceTable, sourceID, targetID) {


      var answer = [0, 0]; //successful attachments, failed attachments


     


      // Query for any attachments on the current record.


      var attachmentRec = new GlideRecord("sys_attachment");


      attachmentRec.addQuery("table_sys_id", sourceID);


      attachmentRec.addQuery("table_name", sourceTable);


      attachmentRec.query();


      if (attachmentRec.hasNext()) {


              while (attachmentRec.next()) {


                      var attachmentMessage = new sn_ws.RESTMessageV2();


                      attachmentMessage.setHttpMethod("post");


                      attachmentMessage.setBasicAuth(targetUserID, targetUserPassword);


                      attachmentMessage.setEndpoint(targetInstanceURL + "api/now/attachment/file");


                      attachmentMessage.setQueryParameter("table_name", attachmentRec.table_name);


                      attachmentMessage.setQueryParameter("table_sys_id", targetID);


                      attachmentMessage.setQueryParameter("file_name", attachmentRec.file_name);


                      attachmentMessage.setRequestHeader("Content-Type", attachmentRec.content_type);


                      attachmentMessage.setRequestHeader("Accept", "application/json");


                      attachmentMessage.setRequestBodyFromAttachment(attachmentRec.sys_id);



                      var response = attachmentMessage.execute();


                      var responseBody = response.getBody();


                      var httpStatus = response.getStatusCode();



                      if (httpStatus.toString() == "201") {


                              answer[0] += 1;


                      } else {


                              answer[1] += 1;


                      }


              }


      } else {


              answer = "none";


      }


      return answer;


}


Hi Michael,
 
I was able to successfully create incident from one instance to another along with attachments.
 In source instance when i create an incident along with attachments, an incident is created in target instance along with attachment. This worked fine!
 
Issues
 
1.In source instance when i remove an attachment, attachment should be removed in target instance
 
2.In source instance if add a second attachment, only that second attachment should be updated in target instance. 
 
Is there a way to implement this? Please advice.
 
Regards,
Lakshmi Elangovan
 
 
 
 
 
 

 

Hi Lakshmi,

In regards to your issues, I imagine you could solve this by retrieving the metadata of the attachments of a specific record in the target instance using GET https://dev21997.service-now.com/api/now/attachment, and loop through that response to check if the filenames and types line up with your local instance record's attachments. If there is not a match, then delete or push the attachment as deemed appropriate using this logic:

If the attachment exists locally but not remotely, push it to your target instance via REST call.
If the attachment exists remotely but not locally, delete it from your target instance via REST call