NOTE: The illustrations here will all use RESTMessageV2 as the example, but the same principles all apply to SOAPMessageV2 as well.
Call Directly from the instance
This is the default behavior. In order to use a MID Server, you must explicitly specify the MID Server to be used. In this case an HTTP request will be sent from your ServiceNow instance to the web server end point that you specify.
Keeping it simple with execute()
Using the execute() method means that a web service call will execute directly from the ServiceNow instance on the currently executing thread and we will wait for the response to be returned. If the execute() method is used then the thread will pause until a response is received. This method can be problematic depending on how long it takes for the request to be processed and a response returned to ServiceNow. While ServiceNow is waiting for a response, whatever thread initiated the call will be frozen. For example, if the call was initiated by end user activity, then the end user will experience a frozen screen until the response is returned.
Benefits: Using execute() is simple. You call the method and it returns the Response object in one line of code. Then you do your response handling against response object API (SOAPResponseV2 or RESTResponseV2).
Drawbacks: The executing thread is frozen until the response comes back. While a direct call is by far the simplest option, if your web service call is initiating from the UI, this can be a problem.
Breaking out of your dull synchronous life with executeAsync()
Usually executeAsync() is used with a MID Server. However, you can also use it without a MID Server. Using the executeAsync() method without a MID Server will send the SOAP/REST request through a scheduled job (sys_trigger table) and the details of the response to the REST request will be stored in the ECC Queue (ecc_queue table). This means that the currently executing thread will move to the next line directly after the scheduled job has been created and will not wait on that line of code for the response to come back. This helps improve performance time for requests triggered by the UI. However, since the thread moves on without waiting for a response there is no way to handle the response.
Besides not being able to handle the response, executeAsync() also introduces a couple layers of complexity due to using a scheduled job and the ECC queue. Since the request now executes on a scheduled job, this means whatever latency was hitting the users from the UI will now be shifted to the scheduled job queue. This could be problematic if the scheduled job queue fills up with slow web service request calls or other jobs. Also, this method incurs the overhead of creation and execution of a scheduled job - a process that usually takes around 6 to 10 seconds. That can have devastating performance impact if you need your web service to execute within couple milliseconds! The user who initiated the original thread won't have to wait, which is good, but the overall response time for the integration will be impacted. This makes executeAsync() a questionable choice for any integration that needs to execute in near real-time. However, if your integration can tolerate a few seconds of added latency to each request, maybe this will work for you.
So, the above method improves the situation in some ways because now the UI is not getting hung while we wait for the web service response. However, since we are not waiting for the response we have no way to handle the response! Our web request has presumably been sent out across the ether to do its work, but how do we know if it worked or not - what response came back? Ground control to Major Tom, can you hear me Major Tom?!
To overcome the issue of not being able to handle the response, sometimes people decide to use the waitForResponse(seconds) method. However, I am going to recommend that unless you are using a MID Server, this is almost never a good idea! Why, you say? I will tell you why. Because the method waitForResponse() causes the initiating thread to freeze again, so we are back to poor response times on the initiating thread - the problem we were trying to avoid by becoming asynchronous. The fact is, when used in combination with waitForResponse(), executeAsync() is no longer asynchronous.
Don't worry. I have a solution. We can make your web service request truly asynchronous and we can handle the response too! ANNOUNCER VOICE: Now introducing (queue generic fanfare music) the setEccTopic() method! The setEccTopic() method takes a little more development work, but it allows for truly asynchronous request handling, while at the same time benefitting from the ability to define a custom "sensor" that will handle the response. There are still some drawbacks to this method. We now have two scheduled jobs that must be created, scheduled, picked up and processed and therefore have at least 12-20 seconds of added latency before we can start processing the response, but, by and large, this is a good solution as long as your web service can tolerate the added latency. See below diagram. Also, there is an in depth discussion of this method's usage here: KB0563615 - RESTMessageV2 API EccTopic Support.
Benefits: If waitForResponse() is not used, then executeAsync() method will allow the executing thread to continue immediately without waiting for a response. This can speed things up considerably - an important concern when your web service is triggered by the UI. However, if response handling is required, then it is recommended to use the setEccTopic() method in combination with executeAsync() to achieve the solution.
Drawbacks: Most web service implementations expect some type of response handling for the requests that are sent out. Using the waitForResponse() method allows you to process a request, but then looses any performance advantage from being processed asynchronously. setEccTopic() allows asynchronous response handling but like all executeAsync() method implementations, it does suffer from the inherent lag of scheduling a job and the potential of latency from other jobs causing queue overload.
Using a MID Server
Using a MID Server is a way to have a web service request initiate from a point within your, ServiceNow's customer's, network. A MID Server is a Java Virtual Machine that sits inside your network firewall and talks to the ServiceNow instance [mostly] through a SOAP integration.
Use execute() or executeAsync(), they work the same
When a MID Server is used, the execute() command implicitly becomes asynchronous and both methods act the same way. Whatever method you use to execute the request, the waitForResponse() method must be used to get the response back from the MID Server.
Benefits: Generally the reason for using a MID Server to execute a REST or SOAP message is concern about exposing web service endpoints to external clients. By having the MID Server act as a go-between to your web service, you can keep the web service exposed only to consumers within your network. Another reason that using a MID Server might be preferable is to offload the REST or SOAP requests from the main ServiceNow instance to the remote MID Server for execution.
Drawbacks: As with the previous scenario, the main drawback of this method is if you want to handle the HTTP response, you must use the waitForResponse(sec) method, that freezes the executing thread until the response has totally completed. This potentially overloads the thread pool if multiple threads are attempting to do the same thing at the same time. As a general rule of thumb it is a bad idea to have a computer thread busy doing nothing.
NOTE: There is one exception the above drawback. If you need handle the HTTP response in a truly asynchronous way and are willing to write the extra code. There is a way that you can do this without freezing the thread that initiates the request. You can use a custom "probe" business rule on the ecc_queue to handle the "input" ECC record that brings back the response. See KB0563615 - RESTMessageV2 API EccTopic Support for details.
The HTTP timeout value is how long a request will wait for TCP connection to the web service end point. This can be set manually for each request using the setHttpTimeout(milliseconds) method. This timeout value applies to both synchronous and asynchronous requests.
The ECC timeout value is the amount of time that an asynchronous request will wait for the response to show up in the ECC Queue. This timeout applies to all asynchronous requests, both with a MID Server and without. However, this does not apply to synchronous requests because they do not use the ECC Queue. This can be controlled globally using the properties glide.rest.outbound.ecc_response.timeout or glide.soap.outbound.ecc_response.timeout. This is also controlled on a per request basis through passing the number of seconds to the waitForResponse(seconds) method.