- Post History
- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Printer Friendly Page
- Report Inappropriate Content
on ‎05-07-2022 03:13 AM
This article contains my recent findings on ServiceNow Attachments. Though the Attachment function seems like a simple use case, it can be challenging depending on business requirements. Fortunately, ServiceNow has interesting APIs, OOB properties, and Plugins to tackle. The following topics are discussed in this Article:
1. How do Attachments Work.
2. Copy Attachments from one record to another record.
3. Copy Specific Attachments from one record to another record.
4. ServiceNow Document Viewer
5. Disabling Attachment on Table
1. How do Attachments Work?
Unlike many tables in ServiceNow Attachments table (sys_attachment) is tricky. There are two tables that do the job of storing and retrieving the attachments in ServiceNow.
1. Attachments (sys_attachment)
2. Attachment Documents (sys_attachment_doc)
When you upload a file into ServiceNow as an attachment, the Attachments (sys_attachment) table stores the metadata such as File Name, Content-Type, File Size, Sys_ID, and Table of the Record on with the attachment is made, etc. Whereas the contents of the attachment are stored in the Attachment Documents (sys_attachment_doc) table.
Creating just a record in the Attachments table using GlideRecord.initialize() method will create an attachment for the record but when you try to open it, the file throws an error message stating the file is empty. This is because the attachment record doesn’t have corresponding Attachment Document records.
The binary data of the attachment is split into 4KB chunks and are stored in the Data field of the table. The length field in the table defines the number of bytes stored in this chunk and the Position field defines the sequence of data that should be put back while retrieving the attachment for viewing or downloading and we got the Sys Attachment field which gives the sys_id of the Attachment Record. Each Attachment file in attachments tables might have one or more Attachment Document records. ServiceNow combines multiple Attachment Document records in sequence and returns them to the users for viewing.
ServiceNow provides GlideSysAttachment() API to handle attachments. It has some interesting methods which can be used to play with attachments and their contents. It creates an instance of GlideSysAttachment class.
2. Copy Attachments from one Record to another record
Business Scenario: This happened recently with one of our clients, we have implemented CSM on top of ITSM and created cases for all the existing incidents and associated the incidents to the case, Case Record being the Parent of Incident Record. After that, we copied the attachments from Incidents to its parent Cases using Copy method.
copy(String source table, String sourceID, String targetTable, String targetID)
Copy method copies attachments from the source record to the target record. This method returns an array of sys_id of attachments that are copied.
Proposed Solution:
Configure a fixed script to copy attachments from the Incident to the associated Case Record. Using Fix script because it’s a one-time activity.
Script:
3. Copy specific records from one record to another on upload.
Business Scenario: Continue to our previous requirement, whenever a file is attached to the case record, the same should be copied to the associated incident record. It is difficult to use the copy method since it copies all the attachments on the source record to the target record each time a file is uploaded. This results in duplicate attachments on incident records. Hence, we need to copy files that are specific to each upload.
Proposed Solution: Configured a after insert business rule on sys_attachment table and using getContentStream() and writeContentStream() methods to create an attachment on the target record.
Under GlideSysAttachment() API, we got multiple methods to retrieve and write the contents of the attachment. Some of them are:
• getContent(GlideRecord sysAttachment)
Returns attachment contents as a String
• getContentStream(String sysID of Attachment)
Returns GlideScriptableInputStream object that contains the attachment contains
• writeContentStream(GlideRecord now_GR, String fileName, String contentType, GlideScriptableInputStream inputStream)
Creates Attachment and return the sys_id of the attachment created
Parameters
now_GR-GlideObject of the record where the attachment should be copied.
filename-File Name of Attachment from sys_attachment table.
contentType-Content Type of the attachment from sys_attachment table.
GlideScriptableInputStream inputStream- Contents of the attachment
**Content is returned as a string, not as a byte array when getContent() is called.
Content is returned as a GlideScriptableInputStream object when getContentStream() is called. The GlideScriptableInputStream contains the actual bytes not converted into a String.
Script:
4. ServiceNow Document Viewer
ServiceNow comes with this interesting plugin- ServiceNow Document Viewer to view documents directly rather than download them to view them in their native applications. Though ServiceNow Document Viewer is active by default, it needs to be enabled at the table level to use it.
Make sure system property com.snc.documentviewer.enable_document_viewer is set to true or create it if it does not already exist.
Procedure:
1. Navigate to System Definition>Dictionary.
2. Search for the table where you want to enable Document Viewer.
3. Open the record with type as Collections and empty name.
4. Enter use_document_viewer=true in the attributes.
5. View UI Action will be visible on the attachments instead of Download, clicking it will open the attachment in a separate window.
5. Disable Attachments on a table
Attachments on a form can be disabled using dictionary attributes.
Procedure:
1. Navigate to System Definition>Dictionary.
2. Search for the table where you want to enable Document Viewer.
3. Open the record with type as Collections and empty name.
4. Enter no_attachment in the attributes.
Thanks for reading, have a great day!
Liked this article? Hit bookmark and mark it as helpful, it would mean a lot.
References:
https://docs.servicenow.com/
https://developer.servicenow.com/dev.do#!/reference/api/rome/server/no-namespace/c_GlideSysAttachmentScopedAPI
- 17,337 Views
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
One thing about this regarding number 3. Typically when using a case, most companies will require that the Tech uses agent workspace. Here they will create a case, attach a screenshot or attachment, save it, assign it to themselves, and then escalate to an incident by using the UI action within AWS "Create Incident" especially if they are following ITIL. How would #3 work in the case of copying the attachment from the case to the incident? Keep in mind, after they attach the attachment to the case, they must save it first before getting the option to create an incident. At this point the attachment has been attached to the sys_attachment table with the table_name of sn_customerservice_case. An incident has yet to be created at this point. Therefore, how does this business rule work if the Incident has not been created? This BR is based off "After Insert" of the attachment to the attachment table. Case in point, exactly when does this copy the attachment, that has now been INSERTed on the sys_attachment table and on the sn_customerservice_case table, to the incident, which has yet to be created by the case? How would one make that work?
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi @@Jimmy45
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi Jimmy,
You are absolutely right, Agent Workspace is very productive when handling cases, even Servicenow is proposing the clients to use AW for productivity. Regarding your question on Point 3, Attachment records are created as soon as you attach anything to a ticket, it doesn't need to be saved. If you can see the business rule looks for the associated incidents before copying the attachments. If there is no incident yet created the script won't even execute which is the obvious one.
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi Vedavrath thanks for posting this. Its working but i am facing an issue on activation the business rules on adding one attachemnt multiple attachments are getting uploaded. Do u know what may be the reason.
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi @Prashanna1,
Please refer to the second script I mentioned in the article. The initial script is to Copy all the existing attachments of the Parent to a child case at the time of creation, Hence the initial BR should is written on the target table only on insert. Whereas the second script will be written on the sys_attachments table so that every time a new attachment is added to the source form, that particular attachment will only get copied to the target record. For better understanding, if you can send me the script you have written we can debug the issue.
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi Vedhavrath,
I am trying to copy attachment from parent facilities record to child facilities record.
on activating this br, on adding one attachment many copies of it are getting updated even before running while condition.
(function executeRule(current, previous /*null when async*/) {
// Add your code here
var recordId = current.table_sys_id;// Is it sys_id of child record ?
var tableName = current.table_name;
var source = new GlideSysAttachment();
var source_content=source.getContentStream(current.sys_id);
var targetGlideRecord = new GlideRecord("facilities");
targetGlideRecord.addQuery('parent', recordId);
targetGlideRecord.query();
var a=targetGlideRecord.getRowCount();
gs.log("rows"+a );// rows is coming 0
while(targetGlideRecord.next())
{ gs.log("check"+a ); // here rows coming as 1
var fileName= current.file_name;
var contentType=current.content_type;
var sourceAttachmentSysid = current.getValue('sys_id');
var targetId=targetGlideRecord.sys_id;
var targetTbl=targetGlideRecord.getTableName();
var attachment= new GlideSysAttachment();
attachment.writeContentStream(targetGlideRecord,fileName,contentType, source_content);
}
})(current, previous);
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
var recordId = current.table_sys_id;// ---> this should be the sys_id of the parent(source) on which you are uploading attachment.
-------------------------------------------------------------------------------------------------------------------------------
targetGlideRecord.addQuery('parent', recordId);//---->here we are looking for child records whose parent is current record.
_____________________________________________________________________________________________________
Are you doing the same? Also the BR should be written on attachment table
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
@Vedhavrath_Kond , yes i am doing these things u mentioned and br is on the sys_attachment table on insert condition. other things are also similar. But the problem is still happening.
u said that
var recordId = current.table_sys_id;// ---> this should be the sys_id of the parent(source) on which you are uploading attachment.
which is true cos i am able to attach from parent to child but
still when i apply log on recordId to find its value, multiple values are coming for duplicate attachment records.
and this value of record id is not present on the facilities table (i was expecting child record) but on the sys_attachment only.
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
So, if I required this to work from case to incident from this point onwards, I should just create the business rule using the script in step 3?
If so, I've typed it in, but it doesn't appear to be working.
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi Vedhavrath,
I have one requirement, when file is getting attached to a data source for every half an hour, I want to trigger a notification along with the attachment from data source.
Where already there is scheduled Job running to remove the attachment after the file is getting processed.
Before removing I want a notification to be triggerred including attachment.
Could you please help?
Regards,
Anusha
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi,
The aricle is very helpful for me, thanks for that. But I need some help here, using the method #3, copying specific records attachment from one record to other, when I am trying this method, the files which are attached on the source record are not being copied on the target record in the same order that they were attached on source. Is it possible to achieve this? kindly respond to my comment.
Thanks in advance!