One of ServiceNow’s principal strengths comes from its extensible framework. Built into the framework is the ability to retrieve information using one of a myriad of methods. If you want to get data out of any table, you can get it via direct web services, using basic auth data retrieval, having it pushed to a client, FTP server or  linux server by using the scheduled data extract, and more.  However, there are times when none of these solutions give you a logical way to achieve what you want in a simple manner.  I will give two examples: 1) adding an item to a cart, 2) fetching an attachment from a record.  For tasks such as these, the flexible Scripted Web Services is the answer.
Scripted web services are used in many integrations where a product wants to accomplish something that doesn’t have a simple solution already built-in.
How to use Scripted Web Services
There are four parts to scripted web services: WSDL (generated for you), script, input variables, output variables.  The WSDL is created for you and is what you’ll use on the client side to access your new web service.  The script is simple JavaScript and performs the required action.  Within the script you retrieve the input variables that you expect the client to send your web services.  Those variables are references using request. notation.  Once the script nears an end, you can set the output variables – the data you want to send back to the client – by using  response. notation.
This is the most flexible way to receive SOAP data and to return whatever you wish to return. Â Let me explain by solving to two problems mentioned above.
Ordering a Blackberry
var cart = new Cart(); var item = cart.addItem('e2132865c0a801650010e411699'); cart.setVariable(item, 'original', request.phone_number); // set the requested for var gr = new GlideRecord("sys_user"); gr.addQuery("user_name", request.requested_for); gr.query(); if (gr.next()) { var cartGR = cart.getCart(); cartGR.requested_for = gr.sys_id; cartGR.update(); } var rc = cart.placeOrder(); response.request_number = rc.number;
The script is a simple example of how to order a backberrry for a specific user. Â Phone_number and requested_for are sent via the soap client to the script and the scripted web service returns the request_number back to the client. Â Something that would be very difficult to figure out using traditional web service methodologies is quite simple to do with using this technique.
Fetching an attachment from a task record
if (typeof GlideStringUtil != 'undefined') var StringUtil = GlideStringUtil; else var StringUtil = Packages.com.glide.util.StringUtil;var  gr = new GlideRecord("sys_attachment"); gr.addQuery("table_sys_id", request.sys_id); gr.query(); if (gr.next()){ if (typeof GlideSysAttachment != 'undefined') var sa = new GlideSysAttachment(); else var sa = new  Packages.com.glide.ui.SysAttachment(); var binData =  sa.getBytes(gr); var encData =  StringUtil.base64Encode(binData); response.file_name = gr.file_name; response.table_name = gr.table_name; response.encodedAttachment = encData; } else{ gs.log("Record not found"); }
Again, this is pretty straightforward. Â What would be the alternative if direct web services were used? Â Well, there would need to be a call to the sys_attachment record to find out the file_name, table_name, and associated task record. Â Then there would need to be several more calls to fetch every attachment chunch (attachments are stored as chunks of data internally) only to reassemble the data client-side….not very friendly.
I created an update set for the fetch attachment record that you may download and apply to your instance:Â Fetch Attachment scripted web service. Â Remember to enable the Web Service Provider – Scripted plugin before applying the update set.
Hi Mark,
I am creating a scripted web services in which i was query some table and it returns more than 1 record . I want to send all the return records in response so that to which I am sending the response extract that response and store all the records. I am able to send the 1 record in response.
Can you please help me out how to achieve this.
Thanks
It appears the fileattachment web service update set is missing the parameters.
I downloaded the xml zip and commited to my instance, the result was the scripted web service but it was missing the 1 input and 3 output parameters.
I’ve successfully implemented the Scripted Web Services plug-in and loaded your update set to fetch an attachment from our instance but I’m having trouble constituting the returned Base64 encoded “encodedAttachment” data to an actual file is usable. I have a couple of PNG images attached to an incident, am able to call the above and get the filename, tablename and encodedAttachment data but when I try to Decode the data and write it to a file on my local system it does not appear as a valid PNG image.
I’m using PowerShell with Msxml2.XMLHTTP to call the service and then using [System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String($encodedAttachment)); and a System.IO.StreamWriter to decode and write the data to disk.
Any guidance on how to get this encoded return value writeen in a usable form? I’m sure I’m just missing something simple (I hope).
Does anyone know how to control the order of the elements returned in the response of the SOAP message. I’ve provided our WSDL to a client who will be consuming it and they require the order of the output elements in the SOAP response same as the WSDL contract provided to the.
There is a order field which can be defined in the output parameters related list which helps to generate the WSDL contract in a particular order but the actual SOAP response doesn’t follow this order.
Any help would be appreciated.
Thanks
Hi Krutik,
I am also facing same issue. Did you get any resolution for the above problem?
Thanks in advance.
Regards,
Toshit Bhatt
Hi mark having issues in this line…..var StringUtil = GlideStringUtil;
I am using a scoped APP and GlideStringUtil is not valid in a scoped app?can you suggest ant workaround