Last week, one of our users posted a question about how to get the event ID back to the requesting system when firing through the Integration Agent (note, this article refers to the integration agent, not the xMatters Agent. These are very different technologies so make sure to use the right one for your environment and integration. And consider upgrading to the new agent). This is a great question and I thought it could use the GIG treatment. You might want to have this immediate response when the requesting application requires the event ID for future searching or storing, however, the IA by default will process asynchronously. So read along as we dive into asynchronous vs synchronous responses in the little agent that could.
Send me an email, I'm on the phone
The Integration Agent is a useful tool for making integrations and we’ve already run into this handy agent in a few previous posts (Inbound REST, Making HTTP Calls, and Command Line). Anything that receives web service requests must be built in a robust fashion, after all, it wouldn’t be much good if it fell over when you put a bit of load on it.
One way that the agent is resilient, is through processing incoming web service requests asynchronously. This Stack Overflow post does a good job of explaining the difference between synchronous and asynchronous communications. Here's a nutshell: consider a telephone conversation (synchronous) versus sending a text or email (asynchronous):
- In a telephone conversation, you ask a question and wait for a more or less immediate response from the person at the other end of the call.
- In email, you ask a question and then go make coffee or goof off on the Internet.
The Integration Agent is like the latter: It will acknowledge it has accepted the request and then go off and do other things while a worker process completes the request. This is helpful because it prevents lots of incoming requests from overwhelming the agent and causing it to be delayed in processing further requests. Going back the telephone versus email example, you can only talk to one person on the phone, but you can respond to several emails before you get one answer back.
But I need it now
However, sometimes you need to get information (such as the event ID from xMatters) back from the IA, so you need to force the IA do its work now, not later. To do this, we’ll dive into the apia_http
function in a little more detail. We first ran into this function when making inbound REST calls and it is called with two arguments:
-
httpRequestProperties
- The incoming request object including headers and body. (a wrapper for ServletRequest) -
httpResponse
- The response object to respond back to the http client (a wrapper for ServletResponse)
For the purposes of this article, we are going to focus on httpResponse
. There are only a couple of functions we need for working with this:
-
setHeader
- Sets a header entry. A common header isContent-Type
. -
setStatusLine
- Sets the HTTP Status. This will be one of the 200 or 400 http statuses you’ll see and the originating application can take action based on this value. -
setBodyString
- Probably the most important one as this will contain the “payload” we want to return to the originating system.
So, putting it all together, assuming eventID
contains the event ID returned from xMatters, this is what we end up with:
1.function apia_http(httpRequestProperties, httpResponse) {
2. // .. other stuff to generate an event
3. // .. set eventID
4.
5. // Now, build the response object
6. // First, set the headers
7. var header = new Header("Content-Type", "application/json" );
8. httpResponse.setHeader( header );
9.
10. // We'll return a JSON payload
11. var responsePayload = {
12. "xM Event ID": eventID,
13. "Other Stuff": "Other value",
14. "From Request": requestPayload.item
15. }
16. // The http status code of 200 means A-OK.
17. httpResponse.setStatusLine( HttpVersion.HTTP_1_1, 200 );
18. httpResponse.setBodyString( JSON.stringify( responsePayload ) );
19.
20. ServiceAPI.getLogger().debug("Exit - apia_http");
21.
22. return httpResponse;
23.}
To test this, we can use the handy curl
command. The format for the endpoint exposed by the Integration Agent is:
http://{IA_HOST}:8081/http/{domain}_{name}
Where {domain}
and {name}
are defined in the integration xml file. In this case, httpExample
for both.
An HTTP POST example:
1.curl --request POST --data '{"item": "value"}' "http://localhost:8081/http/httpExample_httpExample"
which returns
1.{"xM Event ID":"12345","Other Stuff":"Other value","From Request":"value"}
or, since this is a generic HTTP endpoint, we can do a GET as well:
1.curl --request GET "http://localhost:8081/http/httpExample_httpExample?item=passed%20in&other=some%20value&stuff=valuable"
which returns
1.{"xM Event ID":"12345","Other Stuff":"Other value","From Request":"passed%20in"}
The key to all of this is the return
at the end of the apia_http
function. If we returned null or did not have a return statement, the agent would process the request asynchronously and the requesting application can continue on merrily. However, since we are explicitly returning a non null value, then the agent processes the request synchronously.
The goods
I’ve attached an example integration service that can be used as a base for building new http integrations that go through the IA and return a custom response. It also contains a parseQueryString
function that will parse the ?&
mess at the end of a GET url. Just unzip it and throw it into the IAHOME/integrationservices directory. Then update the IAHOME/conf/IAConfig.xml file to include this new httpExample in the </service-configs> section, like so:
<path>httpExample/httpExample.xml</path>
Happy Integrating!
Comments
8 commentsPlease sign in to leave a comment.
Thanks, very helpful indeed.
Any chance you can post a similar article explaining how we can use a ticket reference number (eg: 123456) generated by our management system as the incident id event property on communication plans when injecting events via the IA? this is easily done using legacy integration scripts by passing the ticket id as part of the APCLIENT command line.
This would be *extremely* useful.
Alistair
Hey Alistair! Glad it was helpful. I'm thinking you are referring to the "Incident ID" value in the "Profile" section of the Properties tab in the event report, just above the Event ID? Unfortunately, this is no longer writable by integrations. What are you intending to do with this value? You can still search on the event properties with the search button on the event report.
Alistair's response got lost in the Internets: Hi Travis, yes it's the incident Id which I'm referring to. The need is this. Our service desk tool (CA SDM).... Currently when viewing event reports or notification reports Xmatters displays both the Event ID and the Incident ID, while useful in an Xmatters context they are no help when trying to relate back to the incident id which SDM uses.
Yes we can search on a property of an event which contains our injected SDM incident id, however when exporting this information or viewing an event the SDM ticket id is not readily visible, ie you need to go into the properties tab and when exporting the properties are not included at all.
It seems redundant to have an Event ID and Incident ID in Xmatters which are the same and there is no need to duplicate this information. By mapping an injected value into the Incident ID event property we could, for example easily see and correlate all Xmatters events to a specific incident in SDM when exporting the events from Xmatters.
I don't understand the reasoning behind not being able to map an injected value to replace the incident id for Comms plans, especially when this is possible using older legacy script integrations and is still available for properties such as priority via doing a data remap in the apia_input function...???
Alistair
Hi Alistair, Incident_ID is part of SDM and in this case it matches with the Event_ID in xMatters but xMatters integrates with so many other applications that we cannot rely on Incident_IDs as our identifier . As an example our integration with Twitter does not have any Incident_ID whatsoever, thus we have to have our own ID even if it matches the ID on another application.
Hi Travis, thanks for the reply. I don't think you quite understand what I'm saying.
The incident_ID field is a Xmatters field not SDM.
On events initiated from Comms Plans there is an "event id" which is a Xmatters sequential number.
There is also a property called "Incident_ID". It is automatically populated by Xmatters with a value of "INCIDENT_".
This is what I would like to populate with my own reference number when injecting events via the IA.
Alistair, so if I'm hearing you right, you'd like the event report export to have some or all of the event properties? We don't do that now obviously, but I can get an enhancement request opened. I've seen a couple other people request similar items on this forum, so it sounds like there is a need for it. If we can't export all the event properties, I'm guessing we'd need a way to select which properties to include in the export, ideally at report run time?
Hi Travis, yes you are on the right track with your thinking. I believe many would find value in being able to select which event properties are exported.
Is the existing "incident_id" property in the event profile being retired going forward and that's why there is no interest in changing things?
I had a enhancement request raised previously however the latest update on that was product management simply said "not in roadmap".
Alistair
I think it is more that the Incident ID field is part of the meta data of the event, rather than the properties/payload of the event. So the idea is to allow for exporting the event's properties.
And actually, I was digging into this and I realized you can export the event properties, you just have to search for the events using those properties. For example, say I need to export all the events for the ServiceNow Comm Plan and include the "Incident Number" (number) and "Category" properties, then I just have to search using those.
As I start typing "ServiceNow" (no quotes), a popup comes up and I select "Communications Plan" contains ServiceNow. Then I type "number" (no quotes) and select the number#en and category#en for category. At this point I've filtered out all non ServiceNow comm plans and added the number and category properties to the export. I'm requesting docs to put up some more details, because I don't see it well documented and I'll drop you an email with some screen shots.