Several design principles and patterns have guided the design and implementation of the ICWS
APIs. These principles are discussed here.
This topic contains the following sections:
Subscriptions in ICWS
provide a way for applications to be informed when changes to the Interaction Center system take place. Applications first express interest in a subscription by calling the PUT
method on the desired subscription resource. Each subscription resource has an associated message that will be sent to the client application via the messaging channel. This associated message is documented in the "Response" section of the subscription resource documentation. Once interest in a subscription has been established, messages will begin to be delivered through the messaging channel. Subscriptions can be stopped by calling the DELETE
method on the subscription resource.
The messaging channel is provided by the GET /icws/{sessionId}/messaging/messages method. Client applications should periodically poll this resource to obtain the messages. When the messages are retrieved by the client application, ICWS
will remove them from the queue and begin queuing new messages.
All messages are complex types that derive from a single message
type. For more on derived types, see Derived Complex Types. Messages can be differentiated by the special __type
(with two underscore characters) property which is a constant value that matches the __type
value in the documentation for each message.
Messages also have an isDelta
property which indicates whether or not the message is an update to information the client has already received or if the information in the message should replace all previously received information. When a subscription is started, the first message will be sent with "isDelta": false
to indicate the message is providing the initial data. Subsequent messages will usually be sent with "isDelta": true
and will only provide the differences from the previous state that was communicated to the client. If ICWS
determines that it is better to resend the entire state instead of calculating and sending a difference, the message will be sent with "isDelta": false
and clients are expected to clear all cached data and replace it with the information provided in the message.
Each API in ICWS
describes the status codes that should be expected when using that API. The status codes that have a consistent meaning across all APIs are listed below with descriptions of their meanings.
GET configuration/users/userThatDoesNotExist
). This can also indicate that the server does not implement the API. Checking the version information (see Versioning) when connecting will allow client applications to refrain from making requests to resources that the server does not support.The HTTP status codes provide a broad classification of an error type, however many times it is useful to provide additional details about the particular error case. The errorId
property provides the additional details and can be consumed programmatically for improved error handling in the client application. The message
property on the error representations provides a string that is meant for user consumption and can be displayed to the user.
The error identifiers provided in the errorId
property are constructed using a hierarchy of period-separated segments. This hierarchy allows for classes of errors to be handled in the same manner without having to handle each individual error identifier. Additionally it allows for the addition of more detailed error identifiers without breaking existing error handling. For example, client code that is handling error.foo
will not break if a more detailed error.foo.bar
error identifier is added.
In order to check an error identifier, a 'prefix match' must be performed. An error identifier matches a prefix value if every segment in the prefix value is equal to the corresponding segment in the error identifier starting from the first segment in the error identifier. This match takes into account the entire segment when matching, so error.f
does not match error.foo.bar
but error.foo
does.
In order to ensure that future enhancements to an error response do not cause consuming code to break, the 'prefix match' must be used. Do not use a string equality comparison or the addition of a more detailed error identifier may break client-side error handling.
The following JavaScript code provides an example function to match error identifiers:
function isMatch(prefix, errorId) { if (errorId === prefix) { // the prefix is a match if it is an exact match to the errorId return true; } if (errorId.indexOf(prefix + '.') === 0) { // the prefix is a match if the errorId starts with the prefix followed // by the period character to ensure the entire segment was matched return true; } // the prefix is not a match return false; }
Enumerations (enums), as in many common programming languages, are distinct value types each represented by a set of named constants. In JSON
, the enum values are represented as numbers by their integer values. The following is an example of the documentation and associated example JSON
showing the enumeration licenseStatus
.
{ "licenseOperationResultList": [ { "licenseName": "<License 1>", "isAvailable": true, "licenseStatus": 2, "errorDetails": "" } ] }
In this example, the value of 2 indicates that the licenseStatus
is available
.
Bit flags enumerations are a special kind of enumeration where the representation of multiple values can be stored on individual bits. Using bitwise operations on the enumeration value, specific values can be added, detected or removed. As with standard enumerations, bit flags enumerations are represented as numbers by their integer values. The following is a simplified JavaScript
example of a bit flags enumeration. Notice that each value is a power of 2.
var Colors = { RED: 1, GREEN: 2, BLUE: 4 };
OR
operator (|
). The following example creates a value representing magenta using Colors.RED
and Colors.BLUE
.
var magenta = Colors.RED | Colors.BLUE;The value of
magenta
will be 5
.
AND
operator (&
) and the equality operator (===
). The following example illustrates how to check for Colors.BLUE
and Colors.GREEN
in magenta
.
var hasBlue = Colors.BLUE === (magenta & Colors.BLUE), hasGreen = Colors.GREEN === (magenta & Colors.GREEN);
hasBlue
will be true
, while hasGreen
will be false
.
NOT
operator (~
) and the bitwise AND
operator (&
). The following example removes the value of Colors.RED
and leaves Colors.BLUE
.
var blue = magenta & ~Colors.RED, isBlue = blue === Colors.BLUE;The value of
isBlue
will be true
.